diff GUI/GUIWindow.cpp @ 2544:c674d547cc7c

GUIWindow switch logic refactored into behaviour classes
author a.parshin
date Mon, 11 May 2015 09:51:04 +0200
parents b6140dfeac27
children e06a3fe9ad6e
line wrap: on
line diff
--- a/GUI/GUIWindow.cpp	Sun May 10 03:21:14 2015 +0200
+++ b/GUI/GUIWindow.cpp	Mon May 11 09:51:04 2015 +0200
@@ -61,10 +61,10 @@
     {0x96, 0xD4, 0xFF}}};
 
 
-int pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[1]; // idb
+enum WindowType current_character_screen_window;
 struct GUIWindow *pWindow_MMT_MainMenu;
 struct GUIWindow *pWindow_MainMenu;
-std::array<struct GUIWindow, 20> pWindowList;
+std::array<struct GUIWindow *, 20> pWindowList;
 
 struct GUIMessageQueue *pMessageQueue_50CBD0 = new GUIMessageQueue;
 struct GUIMessageQueue *pMessageQueue_50C9E8 = new GUIMessageQueue;
@@ -74,6 +74,194 @@
 
 
 
+GUIWindow_Inventory_CastSpell::GUIWindow_Inventory_CastSpell(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int button, const char *hint) :
+    GUIWindow(x, y, width, height, button, hint)
+{
+    pMouse->SetCursorBitmap("MICON2");
+    pBtn_ExitCancel = CreateButton(392, 318, 75, 33, 1, 0, UIMSG_Escape, 0, 0, pGlobalTXT_LocalizationStrings[34],//Отмена
+        pIcons_LOD->GetTexture(uTextureID_BUTTDESC2), 0);
+    ShowStatusBarString(pGlobalTXT_LocalizationStrings[39], 2); // Choose target / Выбрать цель
+    ++pIcons_LOD->uTexturePacksCount;
+    current_character_screen_window = WINDOW_CharacterWindow_Inventory;
+    current_screen_type = SCREEN_CASTING;
+    if (!pIcons_LOD->uNumPrevLoadedFiles)
+        pIcons_LOD->uNumPrevLoadedFiles = pIcons_LOD->uNumLoadedFiles;
+}
+
+GUIWindow_House::GUIWindow_House(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int button, const char *hint) :
+    GUIWindow(x, y, width, height, button, hint)
+{
+    current_screen_type = SCREEN_HOUSE;
+    pBtn_ExitCancel = CreateButton(471, 445, 169, 35, 1, 0, UIMSG_Escape, 0, 0, pGlobalTXT_LocalizationStrings[80], // Quit building / Выйти из здания
+        pIcons_LOD->GetTexture(uExitCancelTextureId), 0);
+    for (int v26 = 0; v26 < uNumDialogueNPCPortraits; ++v26)
+    {
+        char *v29, *v30;
+        if (v26 + 1 == uNumDialogueNPCPortraits && uHouse_ExitPic)
+        {
+            v30 = pMapStats->pInfos[uHouse_ExitPic].pName;
+            v29 = (char*)pGlobalTXT_LocalizationStrings[LOCSTR_ENTER_S];
+        }
+        else
+        {
+            if (v26 || !dword_591080)
+                v30 = HouseNPCData[v26 + 1 - ((dword_591080 != 0) ? 1 : 0)]->pName;
+            else
+                v30 = (char*)p2DEvents[button - 1].pProprieterName;
+            v29 = (char*)pGlobalTXT_LocalizationStrings[435];
+        }
+        sprintfex(byte_591180[v26].data(), v29, v30);
+        HouseNPCPortraitsButtonsList[v26] = CreateButton(pNPCPortraits_x[uNumDialogueNPCPortraits - 1][v26],
+            pNPCPortraits_y[uNumDialogueNPCPortraits - 1][v26],
+            63, 73, 1, 0, UIMSG_ClickHouseNPCPortrait, v26, 0, byte_591180[v26].data(), 0, 0, 0);
+    }
+    if (uNumDialogueNPCPortraits == 1)
+    {
+        window_SpeakInHouse = this;
+        _4B4224_UpdateNPCTopics(0);
+    }
+}
+
+GUIWindow_Dialogue::GUIWindow_Dialogue(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int button, const char *hint) :
+    GUIWindow(x, y, width, height, button, hint)
+{
+    prev_screen_type = current_screen_type;
+    current_screen_type = SCREEN_NPC_DIALOGUE;
+    pBtn_ExitCancel = CreateButton(0x1D7u, 0x1BDu, 0xA9u, 0x23u, 1, 0, UIMSG_Escape, 0, 0, pGlobalTXT_LocalizationStrings[79], //"Exit"
+        pIcons_LOD->GetTexture(uExitCancelTextureId), 0);
+    if (par1C != 1)
+    {
+        int num_menu_buttons = 0;
+        int v11 = LOBYTE(pFontArrus->uFontHeight) - 3;
+        NPCData *speakingNPC = GetNPCData(sDialogue_SpeakingActorNPC_ID);
+        if (GetGreetType(sDialogue_SpeakingActorNPC_ID) == 1)//QuestsNPC_greet
+        {
+            if (speakingNPC->joins)
+            {
+                CreateButton(480, 130, 140, v11, 1, 0, UIMSG_SelectNPCDialogueOption, 0xDu, 0, "", 0);
+                num_menu_buttons = 1;
+            }
+            if (speakingNPC->evt_A)
+            {
+                if (num_menu_buttons < 4)
+                {
+                    int v14 = NPC_EventProcessor(speakingNPC->evt_A);
+                    if (v14 == 1 || v14 == 2)
+                        CreateButton(0x1E0u, num_menu_buttons++ * v11 + 130, 0x8Cu, v11, 1, 0, UIMSG_SelectNPCDialogueOption, 0x13u, 0, "", 0);
+                }
+            }
+            if (speakingNPC->evt_B)
+            {
+                if (num_menu_buttons < 4)
+                {
+                    int v16 = NPC_EventProcessor(speakingNPC->evt_B);
+                    if (v16 == 1 || v16 == 2)
+                        CreateButton(0x1E0u, num_menu_buttons++ * v11 + 130, 0x8Cu, v11, 1, 0, UIMSG_SelectNPCDialogueOption, 0x14u, 0, "", 0);
+                }
+            }
+            if (speakingNPC->evt_C)
+            {
+                if (num_menu_buttons < 4)
+                {
+                    int v18 = NPC_EventProcessor(speakingNPC->evt_C);
+                    if (v18 == 1 || v18 == 2)
+                        CreateButton(0x1E0u, num_menu_buttons++ * v11 + 130, 0x8Cu, v11, 1, 0, UIMSG_SelectNPCDialogueOption, 0x15u, 0, "", 0);
+                }
+            }
+            if (speakingNPC->evt_D)
+            {
+                if (num_menu_buttons < 4)
+                {
+                    int v20 = NPC_EventProcessor(speakingNPC->evt_D);
+                    if (v20 == 1 || v20 == 2)
+                        CreateButton(0x1E0u, num_menu_buttons++ * v11 + 130, 0x8Cu, v11, 1, 0, UIMSG_SelectNPCDialogueOption, 0x16u, 0, "", 0);
+                }
+            }
+            if (speakingNPC->evt_E)
+            {
+                if (num_menu_buttons < 4)
+                {
+                    int v22 = NPC_EventProcessor(speakingNPC->evt_E);
+                    if (v22 == 1 || v22 == 2)
+                        CreateButton(0x1E0u, num_menu_buttons++ * v11 + 130, 0x8Cu, v11, 1, 0, UIMSG_SelectNPCDialogueOption, 0x17u, 0, "", 0);
+                }
+            }
+            if (speakingNPC->evt_F)
+            {
+                if (num_menu_buttons < 4)
+                {
+                    int v24 = NPC_EventProcessor(speakingNPC->evt_F);
+                    if (v24 == 1 || v24 == 2)
+                        CreateButton(0x1E0u, num_menu_buttons++ * v11 + 130, 0x8Cu, v11, 1, 0, UIMSG_SelectNPCDialogueOption, 0x18u, 0, "", 0);
+                }
+            }
+        }
+        else
+        {
+            if (speakingNPC->joins)
+            {
+                CreateButton(0x1E0u, 0x82u, 0x8Cu, v11, 1, 0, UIMSG_SelectNPCDialogueOption, 0x4Du, 0, pGlobalTXT_LocalizationStrings[407], 0);//Подробнее
+                if (speakingNPC->Hired())
+                {
+                    sprintf(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[408], speakingNPC->pName); //Отпустить
+                    CreateButton(0x1E0u, v11 + 130, 0x8Cu, v11, 1, 0, UIMSG_SelectNPCDialogueOption, 0x4Cu, 0, pTmpBuf.data(), 0);
+                }
+                else
+                    CreateButton(0x1E0u, v11 + 130, 0x8Cu, v11, 1, 0, UIMSG_SelectNPCDialogueOption, 0x4Cu, 0, pGlobalTXT_LocalizationStrings[406], 0);//Нанять
+                num_menu_buttons = 2;
+            }
+        }
+        _41D08F_set_keyboard_control_group(num_menu_buttons, 1, 0, 1);
+    }
+}
+
+GUIWindow_Travel::GUIWindow_Travel(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int button, const char *hint) :
+    GUIWindow(x, y, width, height, button, hint)
+{
+    prev_screen_type = current_screen_type;
+    current_screen_type = SCREEN_CHANGE_LOCATION;
+    pBtn_ExitCancel = CreateButton(566, 445, 75, 33, 1, 0, UIMSG_CHANGE_LOCATION_ClickCencelBtn, 0, 'N', pGlobalTXT_LocalizationStrings[156], pIcons_LOD->GetTexture(uTextureID_BUTTDESC2), 0);// Stay in this area / Остаться в этой области
+    pBtn_YES = CreateButton(486, 445, 75, 33, 1, 0, UIMSG_OnTravelByFoot, 0, 'Y', hint, pIcons_LOD->GetTexture(uTextureID_BUTTYES2), 0);
+    CreateButton(pNPCPortraits_x[0][0], pNPCPortraits_y[0][0], 63, 73, 1, 0, UIMSG_OnTravelByFoot, 1, ' ', hint, 0, 0, 0);
+    CreateButton(8, 8, 460, 344, 1, 0, UIMSG_OnTravelByFoot, 1, 0, hint, 0);
+}
+
+GUIWindow_Transition::GUIWindow_Transition(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int button, const char *hint) :
+    GUIWindow(x, y, width, height, button, hint)
+{
+    prev_screen_type = current_screen_type;
+    current_screen_type = SCREEN_INPUT_BLV;
+    pBtn_ExitCancel = CreateButton(0x236u, 0x1BDu, 0x4Bu, 0x21u, 1, 0, UIMSG_TransitionWindowCloseBtn, 0, 'N', pGlobalTXT_LocalizationStrings[34], pIcons_LOD->GetTexture(uTextureID_BUTTDESC2), 0); // Cancel / Отмена
+    pBtn_YES = CreateButton(0x1E6u, 0x1BDu, 0x4Bu, 0x21u, 1, 0, UIMSG_TransitionUI_Confirm, 0, 'Y', hint, pIcons_LOD->GetTexture(uTextureID_BUTTYES2), 0);
+    CreateButton(pNPCPortraits_x[0][0], pNPCPortraits_y[0][0], 0x3Fu, 0x49u, 1, 0, UIMSG_TransitionUI_Confirm, 1, 0x20u, hint, 0);
+    CreateButton(8, 8, 0x1CCu, 0x158u, 1, 0, UIMSG_TransitionUI_Confirm, 1u, 0, hint, 0);
+}
+
+GUIWindow_Spellbook::GUIWindow_Spellbook(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int button, const char *hint) :
+    GUIWindow(x, y, width, height, button, hint)
+{
+    InitializeBookTextures();
+    OpenSpellBook();
+}
+
+GUIWindow_GenericDialogue::GUIWindow_GenericDialogue(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int button, const char *hint) :
+    GUIWindow(x, y, width, height, button, hint)
+{
+    prev_screen_type = current_screen_type;
+    pKeyActionMap->EnterText(0, 15, this);
+    current_screen_type = SCREEN_BRANCHLESS_NPC_DIALOG;
+}
+
+OnCastTargetedSpell::OnCastTargetedSpell(unsigned int x, unsigned int y, unsigned int width, unsigned int height, int button, const char *hint) :
+    GUIWindow(x, y, width, height, button, hint)
+{
+    pEventTimer->Pause();
+    pAudioPlayer->StopChannels(-1, -1);
+    pMouse->SetCursorBitmap("MICON2");
+    ShowStatusBarString(pGlobalTXT_LocalizationStrings[39], 2u); // ChooseTarget / Выберите цель
+}
+
+
 // inlined
 //----- (mm6c::00420520) --------------------------------------------------
 void GUIMessageQueue::Flush()
@@ -104,9 +292,8 @@
 }
 
 //----- (0041B4E1) --------------------------------------------------------
-int __fastcall GUI_ReplaceHotkey(unsigned __int8 uOldHotkey, unsigned __int8 uNewHotkey, char bFirstCall)
+void GUI_ReplaceHotkey(unsigned __int8 uOldHotkey, unsigned __int8 uNewHotkey, char bFirstCall)
 {
-  int result; // eax@1
   int i; // edx@2
   GUIButton *j; // ecx@3
   int k; // edx@7
@@ -116,35 +303,29 @@
 
   //v3 = uNewHotkey;
   old_hot_key = toupper(uOldHotkey);
-  result = toupper(uNewHotkey);
-  v9 = result;
+  v9 = toupper(uNewHotkey);
   if ( bFirstCall )
   {
     for ( i = uNumVisibleWindows; i >= 0; --i )
     {
-      result = 84 * pVisibleWindowsIdxs[i];
-      for ( j = pWindowList[pVisibleWindowsIdxs[i] - 1].pControlsHead; j; j = j->pNext )
+      for ( j = pWindowList[pVisibleWindowsIdxs[i] - 1]->pControlsHead; j; j = j->pNext )
         j->field_28 = 0;
     }
   }
   for ( k = uNumVisibleWindows; k >= 0; --k )
   {
-    result = 84 * pVisibleWindowsIdxs[k];
-    for ( l = pWindowList[pVisibleWindowsIdxs[k] - 1].pControlsHead; l; l = l->pNext )
+    for ( l = pWindowList[pVisibleWindowsIdxs[k] - 1]->pControlsHead; l; l = l->pNext )
     {
-      LOBYTE(result) = old_hot_key;
       if ( l->uHotkey == old_hot_key )
       {
         if ( !l->field_28 )
         {
-          LOBYTE(result) = v9;
           l->field_28 = 1;
           l->uHotkey = v9;
         }
       }
     }
   }
-  return result;
 }
 
 //----- (0041B438) --------------------------------------------------------
@@ -157,7 +338,7 @@
   Hot_key_num = toupper(uHotkey);
   for( int i = uNumVisibleWindows; i >= 0 && pVisibleWindowsIdxs[i] > 0; i-- )
   {
-	current_window = &pWindowList[pVisibleWindowsIdxs[i] - 1];
+	current_window = pWindowList[pVisibleWindowsIdxs[i] - 1];
 	for ( result = current_window->pControlsHead; result; result = result->pNext )
 	{
 	  if ( result->uHotkey == Hot_key_num )
@@ -237,6 +418,85 @@
 }
 
 
+
+void GUIWindow_Book::Release()
+{
+    OnCloseBook();
+
+    GUIWindow::Release();
+}
+
+void GUIWindow_Travel::Release()
+{
+    pTexture_outside->Release();
+    pTexture_Dialogue_Background->Release();
+    pIcons_LOD->SyncLoadedFilesCount();
+    current_screen_type = prev_screen_type;
+
+    GUIWindow::Release();
+}
+
+void GUIWindow_Transition::Release()
+{
+    //pVideoPlayer->Unload();
+    pTexture_outside->Release();
+    pTexture_Dialogue_Background->Release();
+    pIcons_LOD->SyncLoadedFilesCount();
+    current_screen_type = prev_screen_type;
+
+    GUIWindow::Release();
+}
+
+void GUIWindow_Dialogue::Release()
+{
+    if (!dword_591084)
+        pDialogueNPCPortraits[0]->Release();
+    uNumDialogueNPCPortraits = 0;
+    pTexture_Dialogue_Background->Release();
+
+    pIcons_LOD->SyncLoadedFilesCount();
+    current_screen_type = prev_screen_type;
+
+    GUIWindow::Release();
+}
+
+void GUIWindow_Spellbook::Release()
+{
+    OnCloseSpellBookPage();
+    OnCloseSpellBook();
+
+    GUIWindow::Release();
+}
+
+void GUIWindow_GenericDialogue::Release()
+{
+    pIcons_LOD->SyncLoadedFilesCount();
+    current_screen_type = prev_screen_type;
+    pKeyActionMap->SetWindowInputStatus(WINDOW_INPUT_CANCELLED);
+
+    GUIWindow::Release();
+}
+
+void GUIWindow_House::Release()
+{
+    for (int i = 0; i < uNumDialogueNPCPortraits; ++i)
+        pDialogueNPCPortraits[i]->Release();
+    uNumDialogueNPCPortraits = 0;
+    pTexture_Dialogue_Background->Release();
+
+    pIcons_LOD->SyncLoadedFilesCount();
+    pIcons_LOD->RemoveTexturesPackFromTextureList();
+    dword_5C35D4 = 0;
+    if (bFlipOnExit)
+    {
+        pParty->sRotationY = (stru_5C6E00->uIntegerDoublePi - 1) & (stru_5C6E00->uIntegerPi + pParty->sRotationY);
+        pIndoorCameraD3D->sRotationY = pParty->sRotationY;
+    }
+    pParty->uFlags |= 2u;
+
+    GUIWindow::Release();
+}
+
 //----- (0041C26A) --------------------------------------------------------
 void GUIWindow::Release()
 {
@@ -251,78 +511,7 @@
   //v1 = this;
   if ( !this )
     return;
-  
-  switch( this->eWindowType )
-  {
-	case WINDOW_GreetingNPC:
-		{
-		pIcons_LOD->SyncLoadedFilesCount();
-		current_screen_type = prev_screen_type;
-		pKeyActionMap->SetWindowInputStatus(WINDOW_INPUT_CANCELLED);
-		break;
-		}
-	case WINDOW_HouseInterior:
-		{
-		for ( i = 0; i < uNumDialogueNPCPortraits; ++i )
-			pDialogueNPCPortraits[i]->Release();
-		uNumDialogueNPCPortraits = 0;
-		pTexture_Dialogue_Background->Release();
 
-		pIcons_LOD->SyncLoadedFilesCount();
-		pIcons_LOD->RemoveTexturesPackFromTextureList();
-		dword_5C35D4 = 0;
-		if ( bFlipOnExit )
-		{
-          pParty->sRotationY = (stru_5C6E00->uIntegerDoublePi - 1) & (stru_5C6E00->uIntegerPi + pParty->sRotationY);
-          pIndoorCameraD3D->sRotationY = pParty->sRotationY;
-		}
-		pParty->uFlags |= 2u;
-		break;
-		}
-	case WINDOW_Transition:
-		{
-		//pVideoPlayer->Unload();
-		pTexture_outside->Release();
-		pTexture_Dialogue_Background->Release();
-		pIcons_LOD->SyncLoadedFilesCount();
-		current_screen_type = prev_screen_type;
-		break;
-		}
-	case WINDOW_SpellBook:
-		{
-		OnCloseSpellBookPage();
-		OnCloseSpellBook();
-		break;
-		}
-	case WINDOW_Book:
-		{
-		OnCloseBook();
-		break;
-		}
-      case WINDOW_ChangeLocation:
-      {
-        pTexture_outside->Release();
-        pTexture_Dialogue_Background->Release();
-        pIcons_LOD->SyncLoadedFilesCount();
-        current_screen_type = prev_screen_type;
-        break;
-		}
-	case WINDOW_Dialogue:
-		{
-        if ( !dword_591084 )
-	        pDialogueNPCPortraits[0]->Release();
-        uNumDialogueNPCPortraits = 0;
-        pTexture_Dialogue_Background->Release();
-
-        pIcons_LOD->SyncLoadedFilesCount();
-        current_screen_type = prev_screen_type;
-        break;
-		}
-  case WINDOW_null:
-    return;
-	default:
-		break;
-  }
   //v8 = this->pControlsHead;
   if ( this->pControlsHead )
   {
@@ -342,7 +531,7 @@
   {
     v12 = pVisibleWindowsIdxs[this->numVisibleWindows + 1];
     pVisibleWindowsIdxs[this->numVisibleWindows] = v12;
-    --pWindowList[v12 - 1].numVisibleWindows;
+    --pWindowList[v12 - 1]->numVisibleWindows;
     ++this->numVisibleWindows;
   }
   pVisibleWindowsIdxs[uNumVisibleWindows] = 0;
@@ -1380,262 +1569,68 @@
     DrawText(a2, uX, uY, 0, "_", 0, 0, 0);
 }
 
-//----- (0041C432) --------------------------------------------------------
-GUIWindow * GUIWindow::Create( unsigned int uX, unsigned int uY, unsigned int uWidth, unsigned int uHeight, enum WindowType eWindowType, int pButton, const char* hint )
-{
-  unsigned int uNextFreeWindowID; // ebp@1
-  //int *v8; // eax@1
-  //GUIWindow *pWindow; // esi@4
-  //int v10; // eax@4
-  unsigned int v11; // ebx@15
-  NPCData *speakingNPC; // ebp@15
-  int v14; // eax@20
-  int v16; // eax@25
-  int v18; // eax@30
-  int v20; // eax@35
-  int v22; // eax@40
-  int v24; // eax@45
-//  int v25; // eax@65
-  unsigned int v26; // ebx@65
-  char *v27; // eax@71
-  const char *v29; // [sp-8h] [bp-18h]@68
-  char *v30; // [sp-4h] [bp-14h]@68
-//  int uWidtha; // [sp+14h] [bp+4h]@66
-  int num_menu_buttons; // [sp+20h] [bp+10h]@15
+
+GUIWindow::GUIWindow() :
+    uNumControls(0),
+    pControlsHead(nullptr),
+    pControlsTail(nullptr),
+    eWindowType(WINDOW_null)
+{}
 
-  for (uNextFreeWindowID = 0; uNextFreeWindowID < 20; ++uNextFreeWindowID)
-  {
-    if (pWindowList[uNextFreeWindowID].eWindowType == WINDOW_null)
-      break;
-  }
-
-  GUIWindow* pWindow = &pWindowList[uNextFreeWindowID];
-  pWindow->uFrameWidth = uWidth;
-  pWindow->uFrameHeight = uHeight;
+//----- (0041C432) --------------------------------------------------------
+GUIWindow::GUIWindow(unsigned int uX, unsigned int uY, unsigned int uWidth, unsigned int uHeight, int pButton, const char* hint) :
+    uNumControls(0),
+    pControlsHead(nullptr),
+    pControlsTail(nullptr),
+    eWindowType(WINDOW_MainMenu)
+{
+    unsigned int uNextFreeWindowID; // ebp@1
+    //int *v8; // eax@1
+    //GUIWindow *pWindow; // esi@4
+    //int v10; // eax@4
+    unsigned int v11; // ebx@15
+    NPCData *speakingNPC; // ebp@15
+    int v14; // eax@20
+    int v16; // eax@25
+    int v18; // eax@30
+    int v20; // eax@35
+    int v22; // eax@40
+    int v24; // eax@45
+    //  int v25; // eax@65
+    unsigned int v26; // ebx@65
+    char *v27; // eax@71
+    const char *v29; // [sp-8h] [bp-18h]@68
+    char *v30; // [sp-4h] [bp-14h]@68
+    //  int uWidtha; // [sp+14h] [bp+4h]@66
+    int num_menu_buttons; // [sp+20h] [bp+10h]@15
 
-  pWindow->uFrameX = uX;
-  pWindow->uFrameY = uY;
-  pWindow->uFrameZ = uX + uWidth - 1;
-  pWindow->uFrameW = uY + uHeight - 1;
-
-  pWindow->ptr_1C = (void *)pButton;
-  pWindow->Hint = hint;
-  
-  pWindow->eWindowType = eWindowType;
-  pWindow->receives_keyboard_input = false;
-  ++uNumVisibleWindows;
-  pWindow->numVisibleWindows = uNumVisibleWindows;
-  pVisibleWindowsIdxs[uNumVisibleWindows] = uNextFreeWindowID + 1;
-  if ( (signed int)eWindowType <= 20 )
-  {
-    if (eWindowType != WINDOW_Chest)
+    for (uNextFreeWindowID = 0; uNextFreeWindowID < 20; ++uNextFreeWindowID)
     {
-      switch (eWindowType)
-      {
-        case WINDOW_Book: {
-          pWindow->InitializeBookView();
-          break;
-          }
-        case WINDOW_Dialogue: {
-          prev_screen_type = current_screen_type;
-          current_screen_type = SCREEN_NPC_DIALOGUE;
-          pBtn_ExitCancel = pWindow->CreateButton(0x1D7u, 0x1BDu, 0xA9u, 0x23u, 1, 0, UIMSG_Escape, 0, 0, pGlobalTXT_LocalizationStrings[79], //"Exit"
-                         pIcons_LOD->GetTexture(uExitCancelTextureId), 0);
-          if ( pWindow->par1C != 1 )
-          {
-            num_menu_buttons = 0;
-            v11 = LOBYTE(pFontArrus->uFontHeight) - 3;
-            speakingNPC = GetNPCData(sDialogue_SpeakingActorNPC_ID);
-            if ( GetGreetType(sDialogue_SpeakingActorNPC_ID) == 1 )//QuestsNPC_greet
-            {
-              if ( speakingNPC->joins )
-              {
-                pWindow->CreateButton(480, 130, 140, v11, 1, 0, UIMSG_SelectNPCDialogueOption, 0xDu, 0, "", 0);
-                num_menu_buttons = 1;
-              }
-              if ( speakingNPC->evt_A )
-              {
-                if ( num_menu_buttons < 4 )
-                {
-                  v14 = NPC_EventProcessor(speakingNPC->evt_A);
-                  if ( v14 == 1 || v14 == 2 )
-                    pWindow->CreateButton(0x1E0u, num_menu_buttons++ * v11 + 130, 0x8Cu, v11, 1, 0, UIMSG_SelectNPCDialogueOption, 0x13u, 0, "", 0);
-                }
-              }
-              if ( speakingNPC->evt_B )
-              {
-                if ( num_menu_buttons < 4 )
-                {
-                  v16 = NPC_EventProcessor(speakingNPC->evt_B);
-                  if ( v16 == 1 || v16 == 2 )
-                    pWindow->CreateButton(0x1E0u, num_menu_buttons++ * v11 + 130, 0x8Cu, v11, 1, 0, UIMSG_SelectNPCDialogueOption, 0x14u, 0, "", 0);
-                }
-              }
-              if ( speakingNPC->evt_C )
-              {
-                if ( num_menu_buttons < 4 )
-                {
-                  v18 = NPC_EventProcessor(speakingNPC->evt_C);
-                  if ( v18 == 1 || v18 == 2 )
-                    pWindow->CreateButton( 0x1E0u, num_menu_buttons++ * v11 + 130, 0x8Cu, v11, 1, 0, UIMSG_SelectNPCDialogueOption, 0x15u, 0, "", 0);
-                }
-              }
-              if ( speakingNPC->evt_D )
-              {
-                if ( num_menu_buttons < 4 )
-                {
-                  v20 = NPC_EventProcessor(speakingNPC->evt_D);
-                  if ( v20 == 1 || v20 == 2 )
-                    pWindow->CreateButton(0x1E0u, num_menu_buttons++ * v11 + 130, 0x8Cu, v11, 1, 0, UIMSG_SelectNPCDialogueOption, 0x16u, 0, "", 0);
-                }
-              }
-              if ( speakingNPC->evt_E )
-              {
-                if ( num_menu_buttons < 4 )
-                {
-                  v22 = NPC_EventProcessor(speakingNPC->evt_E);
-                  if ( v22 == 1 || v22 == 2 )
-                    pWindow->CreateButton(0x1E0u, num_menu_buttons++ * v11 + 130, 0x8Cu, v11, 1, 0, UIMSG_SelectNPCDialogueOption, 0x17u, 0, "", 0);
-                }
-              }
-              if (speakingNPC->evt_F )
-              {
-                if ( num_menu_buttons < 4 )
-                {
-                  v24 = NPC_EventProcessor(speakingNPC->evt_F);
-                  if ( v24 == 1 || v24 == 2 )
-                    pWindow->CreateButton(0x1E0u, num_menu_buttons++ * v11 + 130, 0x8Cu, v11, 1, 0, UIMSG_SelectNPCDialogueOption, 0x18u, 0, "", 0);
-                }
-              }
-            }
-            else
-            {
-              if ( speakingNPC->joins )
-              {
-                pWindow->CreateButton(0x1E0u, 0x82u, 0x8Cu, v11, 1, 0, UIMSG_SelectNPCDialogueOption, 0x4Du, 0, pGlobalTXT_LocalizationStrings[407], 0);//Подробнее
-                if (speakingNPC->Hired())
-                {
-                  sprintf(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[408], speakingNPC->pName); //Отпустить
-                  pWindow->CreateButton(0x1E0u, v11 + 130, 0x8Cu, v11, 1, 0, UIMSG_SelectNPCDialogueOption, 0x4Cu, 0, pTmpBuf.data(), 0);
-                }
-                else
-                  pWindow->CreateButton(0x1E0u, v11 + 130, 0x8Cu, v11, 1, 0, UIMSG_SelectNPCDialogueOption, 0x4Cu, 0, pGlobalTXT_LocalizationStrings[406], 0);//Нанять
-                num_menu_buttons = 2;
-              }
-            }
-            pWindow->_41D08F_set_keyboard_control_group(num_menu_buttons, 1, 0, 1);
-          }
-          break;
-            }
-        case WINDOW_ChangeLocation:
-        {
-          prev_screen_type = current_screen_type;
-          current_screen_type = SCREEN_CHANGE_LOCATION;
-          pBtn_ExitCancel = pWindow->CreateButton(                  566,                   445,  75,  33, 1, 0, UIMSG_CHANGE_LOCATION_ClickCencelBtn, 0, 'N', pGlobalTXT_LocalizationStrings[156], pIcons_LOD->GetTexture(uTextureID_BUTTDESC2), 0);//Остаться в этой области
-          pBtn_YES        = pWindow->CreateButton(                  486,                   445,  75,  33, 1, 0, UIMSG_OnTravelByFoot, 0, 'Y', pWindow->Hint, pIcons_LOD->GetTexture(uTextureID_BUTTYES2), 0);
-                            pWindow->CreateButton(pNPCPortraits_x[0][0], pNPCPortraits_y[0][0],  63,  73, 1, 0, UIMSG_OnTravelByFoot, 1, ' ', pWindow->Hint, 0, 0, 0);
-                            pWindow->CreateButton(                    8,                     8, 460, 344, 1, 0, UIMSG_OnTravelByFoot, 1,   0, pWindow->Hint, 0);
-          break;
-        }
-        case WINDOW_SpellBook: {// окно книги заклов
-          InitializeBookTextures();
-          pWindow->OpenSpellBook();
-          break;
-            }
-        case WINDOW_GreetingNPC: {// окно приветствия НПС
-          prev_screen_type = current_screen_type;
-          pKeyActionMap->EnterText(0, 15, pWindow);
-          current_screen_type = SCREEN_BRANCHLESS_NPC_DIALOG;
-          break;
-            }
+        if (pWindowList[uNextFreeWindowID] == nullptr)
+            break;
+    }
+
+    //GUIWindow* pWindow = &pWindowList[uNextFreeWindowID];
+    pWindowList[uNextFreeWindowID] = this;
+    this->uFrameWidth = uWidth;
+    this->uFrameHeight = uHeight;
 
-      }
-      return pWindow;
-    }
-//LABEL_62:
-    pWindow->CreateButton(61, 424, 31, 0, 2, 94, UIMSG_SelectCharacter, 1, '1', "", 0);
-    pWindow->CreateButton(177, 424, 31, 0, 2, 94, UIMSG_SelectCharacter, 2, '2', "", 0);
-    pWindow->CreateButton(292, 424, 31, 0, 2, 94, UIMSG_SelectCharacter, 3, '3', "", 0);
-    pWindow->CreateButton(407, 424, 31, 0, 2, 94, UIMSG_SelectCharacter, 4, '4', "", 0);
-    pWindow->CreateButton(0, 0, 0, 0, 1, 0, UIMSG_CycleCharacters, 0, 9, "", 0);
-    return pWindow;
-  }
-  if (eWindowType == WINDOW_HouseInterior)
-  {
-    current_screen_type = SCREEN_HOUSE;
-    pBtn_ExitCancel = pWindow->CreateButton(471, 445, 169, 35, 1, 0, UIMSG_Escape, 0, 0, pGlobalTXT_LocalizationStrings[80],//Выйти из здания
-                   pIcons_LOD->GetTexture(uExitCancelTextureId), 0);
-    for ( v26 = 0; v26 < uNumDialogueNPCPortraits; ++v26 )
-    {
-      if ( v26 + 1 == uNumDialogueNPCPortraits && uHouse_ExitPic )
-      {
-        v30 = pMapStats->pInfos[uHouse_ExitPic].pName;
-        v29 = (char*)pGlobalTXT_LocalizationStrings[LOCSTR_ENTER_S];
-      }
-      else
-      {
-        if ( v26 || !dword_591080 )
-          v27 = HouseNPCData[v26 +1 - ((dword_591080 != 0)? 1:0)]->pName;
-        else
-          v27 = (char*)p2DEvents[pButton - 1].pProprieterName;
-        v30 = v27;
-        v29 = (char*)pGlobalTXT_LocalizationStrings[435];
-      }
-      sprintfex(byte_591180[v26].data(), v29, v30);
-      HouseNPCPortraitsButtonsList[v26] = pWindow->CreateButton(pNPCPortraits_x[uNumDialogueNPCPortraits - 1][v26],
-                                                                pNPCPortraits_y[uNumDialogueNPCPortraits - 1][v26],
-                                           63, 73, 1, 0, UIMSG_ClickHouseNPCPortrait, v26, 0, byte_591180[v26].data(), 0, 0, 0);
-    }
-    if ( uNumDialogueNPCPortraits == 1 )
-    {
-      window_SpeakInHouse = &pWindowList[uNextFreeWindowID];
-      _4B4224_UpdateNPCTopics(0);
-    }
-  }
-  else
-  {
-    if (eWindowType == WINDOW_Transition)
-    {
-      prev_screen_type = current_screen_type;
-      current_screen_type = SCREEN_INPUT_BLV;
-      pBtn_ExitCancel = pWindow->CreateButton(0x236u, 0x1BDu, 0x4Bu, 0x21u, 1, 0, UIMSG_TransitionWindowCloseBtn, 0, 'N', pGlobalTXT_LocalizationStrings[34], pIcons_LOD->GetTexture(uTextureID_BUTTDESC2), 0);//Отмена
-      pBtn_YES        = pWindow->CreateButton(0x1E6u, 0x1BDu, 0x4Bu, 0x21u, 1, 0, UIMSG_TransitionUI_Confirm, 0, 'Y', pWindow->Hint, pIcons_LOD->GetTexture(uTextureID_BUTTYES2), 0);
-                        pWindow->CreateButton(pNPCPortraits_x[0][0], pNPCPortraits_y[0][0], 0x3Fu, 0x49u, 1, 0, UIMSG_TransitionUI_Confirm, 1, 0x20u, pWindow->Hint, 0);
-                        pWindow->CreateButton(8, 8, 0x1CCu, 0x158u, 1, 0, UIMSG_TransitionUI_Confirm, 1u, 0, pWindow->Hint, 0);
-      return pWindow;
-    }
-    if (eWindowType == WINDOW_CastSpell)
-    {
-      pEventTimer->Pause();
-      pAudioPlayer->StopChannels(-1, -1);
-      pMouse->SetCursorBitmap("MICON2");
-      ShowStatusBarString(pGlobalTXT_LocalizationStrings[39], 2u);//Выберите цель
-      return pWindow;
-    }
-    if (eWindowType == WINDOW_Scroll)
-    {
-      pWindow->CreateButton(61, 424, 31, 0, 2, 94, UIMSG_SelectCharacter, 1, '1', "", 0);
-      pWindow->CreateButton(177, 424, 31, 0, 2, 94, UIMSG_SelectCharacter, 2, '2', "", 0);
-      pWindow->CreateButton(292, 424, 31, 0, 2, 94, UIMSG_SelectCharacter, 3, '3', "", 0);
-      pWindow->CreateButton(407, 424, 31, 0, 2, 94, UIMSG_SelectCharacter, 4, '4', "", 0);
-      pWindow->CreateButton(0, 0, 0, 0, 1, 0, UIMSG_CycleCharacters, 0, '\t', "", 0);
-      return pWindow;
-    }
-    if (eWindowType == WINDOW_CastSpell_InInventory)
-    {
-      pMouse->SetCursorBitmap("MICON2");
-      pBtn_ExitCancel = pWindow->CreateButton(392, 318, 75, 33, 1, 0, UIMSG_Escape, 0, 0, pGlobalTXT_LocalizationStrings[34],//Отмена
-                     pIcons_LOD->GetTexture(uTextureID_BUTTDESC2), 0);
-      ShowStatusBarString(pGlobalTXT_LocalizationStrings[39], 2);//Выбрать цель
-      ++pIcons_LOD->uTexturePacksCount;
-      pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] = 103;
-      current_screen_type = SCREEN_CASTING;
-      if ( !pIcons_LOD->uNumPrevLoadedFiles )
-        pIcons_LOD->uNumPrevLoadedFiles = pIcons_LOD->uNumLoadedFiles;
-    }
-  }
-  return pWindow;
+    this->uFrameX = uX;
+    this->uFrameY = uY;
+    this->uFrameZ = uX + uWidth - 1;
+    this->uFrameW = uY + uHeight - 1;
+
+    this->ptr_1C = (void *)pButton;
+    this->Hint = hint;
+
+    //this->eWindowType = eWindowType;
+    this->receives_keyboard_input = false;
+    ++uNumVisibleWindows;
+    this->numVisibleWindows = uNumVisibleWindows;
+    pVisibleWindowsIdxs[uNumVisibleWindows] = uNextFreeWindowID + 1;
 }
+
+
 //----- (004B3EF0) --------------------------------------------------------
 void DrawJoinGuildWindow( int pEventCode )
 {
@@ -1643,15 +1638,15 @@
   current_npc_text = (char *)pNPCTopics[pEventCode + 99].pText;
   ContractSelectText(pEventCode);
   pDialogueWindow->Release();
-  pDialogueWindow = GUIWindow::Create(0, 0, window->GetWidth(), 350, WINDOW_MainMenu, pEventCode, 0);
+  pDialogueWindow = new GUIWindow(0, 0, window->GetWidth(), 350, pEventCode, 0);
   pBtn_ExitCancel = pDialogueWindow->CreateButton(471, 445, 169, 35, 1, 0, UIMSG_Escape,                    0, 0, pGlobalTXT_LocalizationStrings[34], pIcons_LOD->GetTexture(uExitCancelTextureId), 0); // Cancel
                     pDialogueWindow->CreateButton(  0,   0,   0,  0, 1, 0, UIMSG_BuyInShop_Identify_Repair, 0, 0, "", 0);
-                    pDialogueWindow->CreateButton(480, 160, 140, 30, 1, 0, UIMSG_ClickNPCTopic,             0x52u, 0, pGlobalTXT_LocalizationStrings[122], 0);
+                    pDialogueWindow->CreateButton(480, 160, 140, 30, 1, 0, UIMSG_ClickNPCTopic,             82, 0, pGlobalTXT_LocalizationStrings[122], 0);
   pDialogueWindow->_41D08F_set_keyboard_control_group(1, 1, 0, 2);
   dialog_menu_id = HOUSE_DIALOGUE_OTHER;
 }
 //----- (0044603D) --------------------------------------------------------
-void  DialogueEnding()
+void DialogueEnding()
 {
   sDialogue_SpeakingActorNPC_ID = 0;
   pDialogueWindow->Release();
@@ -1659,6 +1654,302 @@
   pMiscTimer->Resume();
   pEventTimer->Resume();
 }
+
+
+
+void GUIWindow_GameMenu::Update()
+{
+    pRenderer->DrawTextureIndexed(
+        pViewport->uViewportTL_Y,
+        pViewport->uViewportTL_X,
+        pIcons_LOD->GetTexture(uTextureID_Options)
+    );
+    viewparams->bRedrawGameUI = 1;
+}
+
+void GUIWindow_CharacterRecord::Update()
+{
+    CharacterUI_CharacterScreen_Draw(pPlayers[uActiveCharacter]);
+}
+
+void GUIWindow_Options::Update()
+{
+    GameMenuUI_Options_Draw();
+}
+
+void GUIWindow_KeymappingOptions::Update()
+{
+    GameMenuUI_DrawKeyBindings();
+}
+
+void GUIWindow_VideoOptions::Update()
+{
+    GameMenuUI_DrawVideoOptions();
+}
+
+void GUIWindow_Book::Update()
+{
+    BookUI_Draw((WindowType)(int)ptr_1C);
+}
+
+void GUIWindow_BooksWindow::Update()
+{
+    auto pButton = (GUIButton *)ptr_1C;
+    pRenderer->DrawTextureIndexed(uFrameY, uFrameX, pButton->pTextures[0]);
+    viewparams->bRedrawGameUI = true;
+}
+
+void GUIWindow_QuickReference::Update()
+{
+    GameUI_QuickRef_Draw();
+}
+
+void GUIWindow_Rest::Update()
+{
+    RestUI_Draw();
+}
+
+void GUIWindow_Travel::Update()
+{
+    TravelUI_Draw();
+}
+
+void GUIWindow_Transition::Update()
+{
+    TransitionUI_Draw();
+}
+
+void GUIWindow_Dialogue::Update()
+{
+    GameUI_DrawDialogue();
+}
+
+void GUIWindow_GenericDialogue::Update()
+{
+    GameUI_DrawBranchlessDialogue();
+}
+
+void GUIWindow_Spellbook::Update()
+{
+    DrawSpellBookContent(pPlayers[uActiveCharacter]);
+}
+
+void GUIWindow_Chest::Update()
+{
+    if (current_screen_type == SCREEN_CHEST)
+    {
+        Chest::DrawChestUI(par1C);
+    }
+    else if (current_screen_type == SCREEN_CHEST_INVENTORY)
+    {
+        pRenderer->ClearZBuffer(0, 479);
+        draw_leather();
+        CharacterUI_InventoryTab_Draw(pPlayers[uActiveCharacter], true);
+        pRenderer->DrawTextureIndexed(pBtn_ExitCancel->uX, pBtn_ExitCancel->uY, pIcons_LOD->GetTexture(uExitCancelTextureId));
+    }
+}
+
+void GUIWindow_Save::Update()
+{
+    SaveUI_Draw();
+}
+
+void GUIWindow_Load::Update()
+{
+    LoadUI_Draw();
+}
+
+void GUIWindow_House::Update()
+{
+    HouseDialogManager();
+    if (!window_SpeakInHouse)
+        return;
+    if (window_SpeakInHouse->par1C >= 53)
+        return;
+    if (pParty->PartyTimes._shop_ban_times[window_SpeakInHouse->par1C] <= pParty->uTimePlayed)
+    {
+        if (window_SpeakInHouse->par1C < 53)
+            pParty->PartyTimes._shop_ban_times[window_SpeakInHouse->par1C] = 0;
+        return;
+    }
+    pMessageQueue_50CBD0->AddGUIMessage(UIMSG_Escape, 0, 0);
+}
+
+void GUIWindow_Scroll::Update()
+{
+    CreateScrollWindow();
+}
+
+void GUIWindow_Inventory::Update()
+{
+    DrawMessageBox(0);
+    DrawText(pFontLucida, 10, 20, 0, "Making item number", 0, 0, 0);
+    DrawText(pFontLucida, 10, 40, 0, pKeyActionMap->pPressedKeysBuffer, 0, 0, 0);
+    if (!pKeyActionMap->field_204)
+    {
+        ItemGen ItemGen2;
+        ItemGen2.Reset();
+        Release();
+        pEventTimer->Resume();
+        current_screen_type = SCREEN_GAME;
+        viewparams->bRedrawGameUI = 1;
+        int v39 = atoi(pKeyActionMap->pPressedKeysBuffer);
+        if (v39 > 0 && v39 < 800)
+            SpawnActor(v39);
+    }
+}
+
+void GUIWindow_Inventory_CastSpell::Update()
+{
+    pRenderer->ClearZBuffer(0, 479);
+    draw_leather();
+    CharacterUI_InventoryTab_Draw(pPlayers[uActiveCharacter], true);
+    CharacterUI_DrawPaperdoll(pPlayers[uActiveCharacter]);
+    pRenderer->DrawTextureIndexedAlpha(pBtn_ExitCancel->uX, pBtn_ExitCancel->uY, pIcons_LOD->GetTexture(uTextureID_x_x_u));
+}
+
+void GUIWindow_Modal::Update()
+{
+    ModalWindow_ShowHint();
+}
+
+void GUIWindow_RestWindow::Update()
+{
+    __debugbreak(); // doesnt seems to get here, check stack trace & conditions
+    GUIButton GUIButton2; // [sp+28h] [bp-E0h]@133
+    memset(&GUIButton2, 0, sizeof(GUIButton2));
+    GUIButton2.uZ = 197;
+    GUIButton2.uW = 197;
+    GUIButton2.uX = 27;
+    GUIButton2.uY = 161;
+    GUIButton2.uWidth = 171;
+    GUIButton2.uHeight = 37;
+    GUIButton2.pParent = pButton_RestUI_WaitUntilDawn->pParent;
+    pAudioPlayer->PlaySound(SOUND_StartMainChoice02, 0, 0, -1, 0, 0, 0, 0);
+    pRenderer->DrawTextureIndexed(uFrameX, uFrameY, *((Texture **)ptr_1C + 15));
+    viewparams->bRedrawGameUI = 1;
+    GUIButton2.DrawLabel(pGlobalTXT_LocalizationStrings[183], pFontCreate, 0, 0); // Rest & Heal 8 hrs / Отдых и лечение 8 часов
+    GUIButton2.pParent = 0;
+    Release();
+}
+
+void OnButtonClick::Update()
+{
+    if (Hint != (char *)1)
+        pAudioPlayer->PlaySound(SOUND_StartMainChoice02, 0, 0, -1, 0, 0, 0, 0);
+    GUIButton *pButton = (GUIButton *)ptr_1C;
+    pRenderer->DrawTextureIndexedAlpha(uFrameX, uFrameY, pButton->pTextures[0]);
+    viewparams->bRedrawGameUI = true;
+    if (Hint && Hint != (char *)1)
+        pButton->DrawLabel(Hint, pFontCreate, 0, 0);
+    Release();
+}
+
+void OnButtonClick2::Update()
+{
+    if (Hint != (char *)1)
+        pAudioPlayer->PlaySound(SOUND_StartMainChoice02, 0, 0, -1, 0, 0, 0, 0);
+    GUIButton *pButton = (GUIButton *)ptr_1C;
+    if (pButton->uX >= 0 && pButton->uX <= window->GetWidth())
+    {
+        if (pButton->uY >= 0 && pButton->uY <= window->GetHeight())
+        {
+            pRenderer->DrawTextureIndexed(uFrameX, uFrameY, pButton->pTextures[0]);
+            viewparams->bRedrawGameUI = true;
+            if (Hint && Hint != (char *)1)
+                pButton->DrawLabel(Hint, pFontCreate, 0, 0);
+            Release();
+            return;
+        }
+    }
+    viewparams->bRedrawGameUI = true;
+    if (Hint && Hint != (char *)1)
+        pButton->DrawLabel(Hint, pFontCreate, 0, 0);
+    Release();
+}
+
+void OnButtonClick3::Update()
+{
+    if (Hint != (char *)1)
+        pAudioPlayer->PlaySound(SOUND_StartMainChoice02, 0, 0, -1, 0, 0, 0, 0);
+    auto pButton = (GUIButton *)ptr_1C;
+    pRenderer->DrawTextureIndexed(uFrameX, uFrameY, pButton->pTextures[1]);
+    viewparams->bRedrawGameUI = 1;
+    if (Hint && Hint != (char *)1)
+        pButton->DrawLabel(Hint, pFontCreate, 0, 0);
+    Release();
+}
+
+void OnButtonClick4::Update()
+{
+    if (Hint != (char *)1)
+        pAudioPlayer->PlaySound(SOUND_StartMainChoice02, 0, 0, -1, 0, 0, 0, 0);
+    auto pButton = (GUIButton *)ptr_1C;
+    pRenderer->DrawTextureIndexedAlpha(uFrameX, uFrameY, pButton->pTextures[1]);
+    viewparams->bRedrawGameUI = true;
+
+    Release();
+}
+
+void OnSaveLoad::Update()
+{
+    if (Hint != (char *)1)
+        pAudioPlayer->PlaySound(SOUND_StartMainChoice02, 0, 0, -1, 0, 0, 0, 0);
+    auto pButton = (GUIButton *)ptr_1C;
+    pRenderer->DrawTextureIndexed(uFrameX, uFrameY, pButton->pTextures[0]);
+    viewparams->bRedrawGameUI = true;
+    if (Hint && Hint != (char *)1)
+        pButton->DrawLabel(Hint, pFontCreate, 0, 0);
+    Release();
+
+    if (current_screen_type == SCREEN_SAVEGAME)
+        pMessageQueue_50CBD0->AddGUIMessage(UIMSG_SaveGame, 0, 0);
+    else
+        pMessageQueue_50CBD0->AddGUIMessage(UIMSG_LoadGame, 0, 0);
+}
+
+void OnCancel::Update()
+{
+    if (Hint != (char *)1)
+        pAudioPlayer->PlaySound(SOUND_StartMainChoice02, 0, 0, -1, 0, 0, 0, 0);
+    auto pGUIButton = (GUIButton *)ptr_1C;
+    pRenderer->DrawTextureIndexed(uFrameX, uFrameY, pGUIButton->pTextures[0]);
+    viewparams->bRedrawGameUI = true;
+    if (Hint && Hint != (char *)1)
+        pGUIButton->DrawLabel(Hint, pFontCreate, 0, 0);
+    Release();
+
+    pMessageQueue_50CBD0->AddGUIMessage(UIMSG_Escape, 0, 0);
+}
+
+void OnCancel2::Update()
+{
+    if (Hint != (char *)1)
+        pAudioPlayer->PlaySound(SOUND_StartMainChoice02, 0, 0, -1, 0, 0, 0, 0);
+    auto pButton = (GUIButton *)ptr_1C;
+    pRenderer->DrawTextureIndexed(uFrameX, uFrameY, pButton->pTextures[1]);
+    viewparams->bRedrawGameUI = true;
+    if (Hint && Hint != (char *)1)
+        pButton->DrawLabel(Hint, pFontCreate, 0, 0);
+    Release();
+
+    pMessageQueue_50CBD0->AddGUIMessage(UIMSG_Escape, 0, 0);
+}
+
+void OnCancel3::Update()
+{
+    if (Hint != (char *)1)
+        pAudioPlayer->PlaySound(SOUND_StartMainChoice02, 0, 0, -1, 0, 0, 0, 0);
+    auto pButton = (GUIButton *)ptr_1C;
+    pRenderer->DrawTextureIndexedAlpha(uFrameX, uFrameY, pButton->pTextures[0]);
+    viewparams->bRedrawGameUI = true;
+    if (Hint && Hint != (char *)1)
+        pButton->DrawLabel(Hint, pFontCreate, 0, 0);
+    Release();
+
+    pMessageQueue_50CBD0->AddGUIMessage(UIMSG_Escape, 0, 0);
+}
+
 //----- (004156F0) --------------------------------------------------------
 void GUI_UpdateWindows() 
 {
@@ -1674,7 +1965,6 @@
   int v31; // eax@115
   GUIButton *pButton; // ebp@118
   int v39; // eax@129
-  unsigned int pNumMessages; // eax@142
   GUIButton *pGUIButton; // ebp@146
   //unsigned int pX; // [sp-1Ch] [bp-124h]@17
   //unsigned int pY; // [sp-18h] [bp-120h]@17
@@ -1690,129 +1980,14 @@
 
   for ( i = 1; i <= uNumVisibleWindows; ++i )
   {
-    pWindow = &pWindowList[pVisibleWindowsIdxs[i] - 1];
+    pWindow = pWindowList[pVisibleWindowsIdxs[i] - 1];
+
+    pWindow->Update();
     switch (pWindow->eWindowType)
     {
-      case WINDOW_GameMenu:
-      {
-        pRenderer->DrawTextureIndexed(pViewport->uViewportTL_Y,
-                                      pViewport->uViewportTL_X, pIcons_LOD->GetTexture(uTextureID_Options));
-        viewparams->bRedrawGameUI = 1;
-        continue;
-      }
-      case WINDOW_CharacterRecord:
-      {
-        CharacterUI_CharacterScreen_Draw(pPlayers[uActiveCharacter]);
-        continue;
-      }
-      case WINDOW_Options:
-      {
-        GameMenuUI_Options_Draw();
-        continue;
-      }
-      case WINDOW_Book:
-      {
-        BookUI_Draw((WindowType)(int)pWindow->ptr_1C);
-        continue;
-      }
-      case WINDOW_Dialogue:
-      {
-        GameUI_DrawDialogue();
-        continue;
-      }
-      case WINDOW_QuickReference:
-      {
-        GameUI_QuickRef_Draw();
-        continue;
-      }
-      case WINDOW_Rest:
-      {
-        RestUI_Draw();
-        continue;
-      }
-      case WINDOW_ChangeLocation:
-      {
-        TravelUI_Draw();
-        continue;
-      }
-      case WINDOW_SpellBook:
-      {
-        DrawSpellBookContent(pPlayers[uActiveCharacter]);
-        continue;
-      }
-      case WINDOW_GreetingNPC:
-      {
-        GameUI_DrawBranchlessDialogue();
-        continue;
-      }
-      case WINDOW_Chest:
-      {
-        if ( current_screen_type == SCREEN_CHEST )
-        {
-          Chest::DrawChestUI(pWindow->par1C);
-        }
-        else if ( current_screen_type == SCREEN_CHEST_INVENTORY )
-        {
-          pRenderer->ClearZBuffer(0, 479);
-          draw_leather();
-          CharacterUI_InventoryTab_Draw(pPlayers[uActiveCharacter], true);
-          pRenderer->DrawTextureIndexed(pBtn_ExitCancel->uX, pBtn_ExitCancel->uY, pIcons_LOD->GetTexture(uExitCancelTextureId));
-        }
-        continue;
-      }
-      case WINDOW_SaveLoadButtons:
-      {
-        SaveUI_Draw();
-        continue;
-      }
-      case WINDOW_MainMenu_Load:
-      {
-        LoadUI_Draw();
-        continue;
-      }
-      case WINDOW_HouseInterior:
-      {
-        pWindowList[pVisibleWindowsIdxs[i] - 1].HouseDialogManager();
-        if ( !window_SpeakInHouse )
-          continue;
-        if ( window_SpeakInHouse->par1C >= 53 )
-          continue;
-        if ( pParty->PartyTimes._shop_ban_times[window_SpeakInHouse->par1C] <=pParty->uTimePlayed )
-        {
-          if ( window_SpeakInHouse->par1C < 53 )
-            pParty->PartyTimes._shop_ban_times[window_SpeakInHouse->par1C] = 0;
-          continue;
-        }
-        pNumMessages = pMessageQueue_50CBD0->uNumMessages;
-        pMessageQueue_50CBD0->AddGUIMessage(UIMSG_Escape, 0, 0);
-        continue;
-      }
-      case WINDOW_Transition:
-      {
-        TransitionUI_Draw();
-        continue;
-      }
-      case WINDOW_Scroll:
-      {
-        CreateScrollWindow();
-        continue;
-      }
-      case WINDOW_CastSpell_InInventory:
-      {
-        pRenderer->ClearZBuffer(0, 479);
-        draw_leather();
-        CharacterUI_InventoryTab_Draw(pPlayers[uActiveCharacter], true);
-        CharacterUI_DrawPaperdoll(pPlayers[uActiveCharacter]);
-        pRenderer->DrawTextureIndexedAlpha(pBtn_ExitCancel->uX, pBtn_ExitCancel->uY, pIcons_LOD->GetTexture(uTextureID_x_x_u));
-        continue;
-      }
-      case WINDOW_ModalWindow:
-      {
-        ModalWindow_ShowHint();
-        continue;
-      }
       case WINDOW_50:
       {
+          __debugbreak(); // looks like debugging tools
         v27 = Color16(255, 255, 255);
         if ( ptr_507BD0->receives_keyboard_input_2 == WINDOW_INPUT_IN_PROGRESS)
         {
@@ -1839,9 +2014,12 @@
           ptr_507BD0->Release();
           continue;
         }
+
+        __debugbreak(); // switch pass-through
       }
       case WINDOW_59:
       {
+          __debugbreak(); // looks like debugging tools
         pWindow->DrawMessageBox(0);
         pWindow->DrawText(pFontLucida, 10, 20, 0, "Making item number", 0, 0, 0);
         pWindow->DrawText(pFontLucida, 10, 40, 0, pKeyActionMap->pPressedKeysBuffer, 0, 0, 0);
@@ -1876,193 +2054,11 @@
         }
         continue;
       }
-      case WINDOW_PressedButton2:
-      {
-        if ( pWindow->Hint != (char *)1 )
-          pAudioPlayer->PlaySound(SOUND_StartMainChoice02, 0, 0, -1, 0, 0, 0, 0);
-        pButton = (GUIButton *)pWindow->ptr_1C;
-        if ( pButton->uX >= 0 && pButton->uX <= window->GetWidth() )
-        {
-          if ( pButton->uY >= 0 && pButton->uY <= window->GetHeight() )
-          {
-            pRenderer->DrawTextureIndexed(pWindow->uFrameX, pWindow->uFrameY, pButton->pTextures[0]);
-            viewparams->bRedrawGameUI = 1;
-            if ( pWindow->Hint )
-            {
-              if ( pWindow->Hint != (char *)1 )
-                pButton->DrawLabel(pWindow->Hint, pFontCreate, 0, 0);
-            }
-            pWindow->Release();
-            continue;
-          }
-        }
-        viewparams->bRedrawGameUI = 1;
-        if ( pWindow->Hint )
-        {
-          if ( pWindow->Hint != (char *)1 )
-            pButton->DrawLabel(pWindow->Hint, pFontCreate, 0, 0);
-        }
-        pWindow->Release();
-        continue;
-      }
-      case WINDOW_CharactersPressedButton:
-      {
-        if ( pWindow->Hint != (char *)1 )
-          pAudioPlayer->PlaySound(SOUND_StartMainChoice02, 0, 0, -1, 0, 0, 0, 0);
-        pButton = (GUIButton *)pWindow->ptr_1C;
-        pRenderer->DrawTextureIndexed(pWindow->uFrameX, pWindow->uFrameY, pButton->pTextures[1]);
-        viewparams->bRedrawGameUI = 1;
-        if ( pWindow->Hint )
-        {
-          if ( pWindow->Hint != (char *)1 )
-            pButton->DrawLabel(pWindow->Hint, pFontCreate, 0, 0);
-        }
-        pWindow->Release();
-        continue;
-      }
-      case WINDOW_PressedButton:
-      {
-        if ( pWindow->Hint != (char *)1 )
-          pAudioPlayer->PlaySound(SOUND_StartMainChoice02, 0, 0, -1, 0, 0, 0, 0);
-        pButton = (GUIButton *)pWindow->ptr_1C;
-        pRenderer->DrawTextureIndexedAlpha(pWindow->uFrameX, pWindow->uFrameY, pButton->pTextures[0]);
-        viewparams->bRedrawGameUI = 1;
-        if ( pWindow->Hint )
-        {
-          if ( pWindow->Hint != (char *)1 )
-            pButton->DrawLabel(pWindow->Hint, pFontCreate, 0, 0);
-        }
-        pWindow->Release();
-        continue;
-      }
-      case WINDOW_5D:
-      {
-        if ( pWindow->Hint != (char *)1 )
-          pAudioPlayer->PlaySound(SOUND_StartMainChoice02, 0, 0, -1, 0, 0, 0, 0);
-        pButton = (GUIButton *)pWindow->ptr_1C;
-        pRenderer->DrawTextureIndexedAlpha(pWindow->uFrameX, pWindow->uFrameY, pButton->pTextures[1]);
-        viewparams->bRedrawGameUI = 1;
-        pWindow->Release();
-        continue;
-      }
-      case WINDOW_SaveLoadBtn:
-      {
-        if (pWindow->Hint != (char *)1)
-          pAudioPlayer->PlaySound(SOUND_StartMainChoice02, 0, 0, -1, 0, 0, 0, 0);
-        pButton = (GUIButton *)pWindow->ptr_1C;
-        pRenderer->DrawTextureIndexed(pWindow->uFrameX, pWindow->uFrameY, pButton->pTextures[0]);
-        pHint = pWindow->Hint;
-        viewparams->bRedrawGameUI = 1;
-        if ( pHint && pHint != (char *)1 )
-          pButton->DrawLabel(pHint, pFontCreate, 0, 0);
-        pWindow->Release();
-        if (current_screen_type == SCREEN_SAVEGAME)
-          pMessageQueue_50CBD0->AddGUIMessage(UIMSG_SaveGame, 0, 0);
-        else
-          pMessageQueue_50CBD0->AddGUIMessage(UIMSG_LoadGame, 0, 0);
-        continue;
-      }
-      case WINDOW_LoadGame_CancelBtn:
-      {
-        if ( pWindow->Hint != (char *)1 )
-          pAudioPlayer->PlaySound(SOUND_StartMainChoice02, 0, 0, -1, 0, 0, 0, 0);
-        pButton = (GUIButton *)pWindow->ptr_1C;
-        pRenderer->DrawTextureIndexedAlpha(pWindow->uFrameX, pWindow->uFrameY, pButton->pTextures[0]);
-        viewparams->bRedrawGameUI = 1;
-        if ( pWindow->Hint && pWindow->Hint != (char *)1 )
-          pButton->DrawLabel(pWindow->Hint, pFontCreate, 0, 0);
-        pWindow->Release();
-        pMessageQueue_50CBD0->AddGUIMessage(UIMSG_Escape, 0, 0);
-        continue;
-      }
-      case WINDOW_CloseRestWindowBtn:
-      {
-        if ( pWindow->Hint != (char *)1 )
-          pAudioPlayer->PlaySound(SOUND_StartMainChoice02, 0, 0, -1, 0, 0, 0, 0);
-        pGUIButton = (GUIButton *)pWindow->ptr_1C;
-        pRenderer->DrawTextureIndexed(pWindow->uFrameX, pWindow->uFrameY, pGUIButton->pTextures[0]);
-        pHint = pWindow->Hint;
-        viewparams->bRedrawGameUI = 1;
-        if ( pHint && pHint != (char *)1 )
-          pGUIButton->DrawLabel(pHint, pFontCreate, 0, 0);
-        pWindow->Release();
-        pMessageQueue_50CBD0->AddGUIMessage(UIMSG_Escape, 0, 0);
-        continue;
-      }
-      case WINDOW_ExitCharacterWindow:
-      {
-        if ( pWindow->Hint != (char *)1 )
-          pAudioPlayer->PlaySound(SOUND_StartMainChoice02, 0, 0, -1, 0, 0, 0, 0);
-        pButton = (GUIButton *)pWindow->ptr_1C;
-        pRenderer->DrawTextureIndexed(pWindow->uFrameX, pWindow->uFrameY, pButton->pTextures[1]);
-        pHint = pWindow->Hint;
-        viewparams->bRedrawGameUI = 1;
-        if ( pHint && pHint != (char *)1 )
-          pButton->DrawLabel(pHint, pFontCreate, 0, 0);
-        pWindow->Release();
-        pNumMessages = pMessageQueue_50CBD0->uNumMessages;
-        pMessageQueue_50CBD0->AddGUIMessage(UIMSG_Escape, 0, 0);
-        continue;
-      }
-      case WINDOW_RestWindow:
-      {
-        memset(&GUIButton2, 0, 0xBCu);
-        GUIButton2.uZ = 197;
-        GUIButton2.uW = 197;
-        GUIButton2.uX = 27;
-        GUIButton2.uY = 161;
-        GUIButton2.uWidth = 171;
-        GUIButton2.uHeight = 37;
-        GUIButton2.pParent = pButton_RestUI_WaitUntilDawn->pParent;
-        pAudioPlayer->PlaySound(SOUND_StartMainChoice02, 0, 0, -1, 0, 0, 0, 0);
-        pRenderer->DrawTextureIndexed(pWindow->uFrameX, pWindow->uFrameY, *((Texture **)pWindow->ptr_1C + 15));
-        viewparams->bRedrawGameUI = 1;
-        GUIButton2.DrawLabel(pGlobalTXT_LocalizationStrings[183], pFontCreate, 0, 0);//Отдых и лечение 8 часов
-        GUIButton2.pParent = 0;
-        pGUIWindow2 = pWindow;
-        pGUIWindow2->Release();
-        continue;
-      }
-      case WINDOW_BooksWindow:
-      {
-        pButton = (GUIButton *)pWindow->ptr_1C;
-        pRenderer->DrawTextureIndexed(pWindow->uFrameY,
-                                      pWindow->uFrameX, pButton->pTextures[0]);
-        viewparams->bRedrawGameUI = true;
-        continue;
-      }
-      case WINDOW_CharacterWindow_Inventory:
-      {
-        pWindow->DrawMessageBox(0);
-        pWindow->DrawText(pFontLucida, 10, 20, 0, "Making item number", 0, 0, 0);
-        pWindow->DrawText(pFontLucida, 10, 40, 0, pKeyActionMap->pPressedKeysBuffer, 0, 0, 0);
-        if ( !pKeyActionMap->field_204 )
-        {
-          ItemGen2.Reset();
-          pWindow->Release();
-          pEventTimer->Resume();
-          current_screen_type = SCREEN_GAME;
-          viewparams->bRedrawGameUI = 1;
-          v39 = atoi(pKeyActionMap->pPressedKeysBuffer);
-          if ( v39 > 0 )
-          {
-            if ( v39 < 800 )
-              SpawnActor(v39);
-          }
-        }
-        continue;
-      }
-      case WINDOW_KeyMappingOptions:
-      {
-        GameMenuUI_DrawKeyBindings();
-        continue;
-      }
-      case WINDOW_VideoOptions:
-      {
-        GameMenuUI_DrawVideoOptions();
-        continue;
-      }
+      case WINDOW_MainMenu:
+      case WINDOW_null:
+          continue;
       default:
+          __debugbreak();
         continue;
     }
   }
@@ -2071,11 +2067,7 @@
   if ( sub_4637E0_is_there_popup_onscreen() )
     UI_OnMouseRightClick(0);
 }
-//void LoadFonts_and_DrawCopyrightWindow()
-//{
-  //MainMenuUI_LoadFontsAndSomeStuff();
- // DrawCopyrightWindow();
-//}
+
 //----- (00415485) --------------------------------------------------------
 void DrawMM7CopyrightWindow()
 {
@@ -2111,7 +2103,7 @@
 {
   pEventTimer->Pause();
   modal_window_prev_screen_type = current_screen_type;
-  pModalWindow = GUIWindow::Create(0, 0, window->GetWidth(), window->GetHeight(), WINDOW_ModalWindow, OnRelease_message, pStrHint);
+  pModalWindow = new GUIWindow_Modal(0, 0, window->GetWidth(), window->GetHeight(), OnRelease_message, pStrHint);
   current_screen_type = SCREEN_MODAL_WINDOW;
 }
 
@@ -2186,7 +2178,7 @@
     if ( mscroll_id <= 782 )
     {
       uTextureID_720980 = pIcons_LOD->LoadTexture("leather", TEXTURE_16BIT_PALETTE);
-      pGUIWindow_ScrollWindow = GUIWindow::Create(0, 0, window->GetWidth(), window->GetHeight(), WINDOW_Scroll, mscroll_id - 700, 0);
+      pGUIWindow_ScrollWindow = new GUIWindow_Scroll(0, 0, window->GetWidth(), window->GetHeight(), mscroll_id - 700, 0);
     }
   }
 }
@@ -2798,7 +2790,7 @@
 }
 
 //----- (004B3E1E) --------------------------------------------------------
-void  sub_4B3E1E()
+void sub_4B3E1E()
 {
 	NPCData *v0; // ST40_4@1
 	signed int v1; // edi@1
@@ -2809,7 +2801,7 @@
 	v1 = 0;
 	pDialogueWindow->eWindowType = WINDOW_MainMenu;
 	pDialogueWindow->Release();
-	pDialogueWindow = GUIWindow::Create(0, 0, window->GetWidth(), window->GetHeight(), WINDOW_Dialogue, 1, 0);
+    pDialogueWindow = new GUIWindow_Dialogue(0, 0, window->GetWidth(), window->GetHeight(), 1, 0);
 	if (pNPCStats->pProfessions[v0->uProfession].pBenefits)//*(&pNPCStats->field_13A5C + 5 * v0->uProfession) )
 	{
 		pDialogueWindow->CreateButton(480, 160, 140, 28, 1, 0, UIMSG_SelectNPCDialogueOption, 77, 0, pGlobalTXT_LocalizationStrings[407], 0);//Подробнее
@@ -3122,7 +3114,7 @@
 	current_npc_text = (char *)pNPCTopics[a4 + 168].pText;
 	_4B254D_SkillMasteryTeacher(a4);  //might be needed because of contract_approved ?
 	pDialogueWindow->Release();
-	pDialogueWindow = GUIWindow::Create(0, 0, window->GetWidth(), 350, WINDOW_MainMenu, a4, 0);
+    pDialogueWindow = new GUIWindow(0, 0, window->GetWidth(), 350, a4, 0);
 	pBtn_ExitCancel = pDialogueWindow->CreateButton(471, 445, 169, 35, 1, 0, UIMSG_Escape, 0, 0,
 		pGlobalTXT_LocalizationStrings[34], pIcons_LOD->GetTexture(uExitCancelTextureId), 0);
 	pDialogueWindow->CreateButton(0, 0, 0, 0, 1, 0, UIMSG_BuyInShop_Identify_Repair, 0, 0, "", 0);
@@ -3234,7 +3226,7 @@
 
 	uDialogueType = 83;
 	pDialogueWindow->Release();
-	pDialogueWindow = GUIWindow::Create(0, 0, window->GetWidth(), 350, WINDOW_MainMenu, 0, 0);
+    pDialogueWindow = new GUIWindow(0, 0, window->GetWidth(), 350, 0, 0);
 	pBtn_ExitCancel = pDialogueWindow->CreateButton(471, 445, 169, 35, 1, 0, UIMSG_Escape, 0, 0, pGlobalTXT_LocalizationStrings[34],// "Cancel"
 		pIcons_LOD->GetTexture(uExitCancelTextureId), 0);
 	pDialogueWindow->CreateButton(0, 0, 0, 0, 1, 0, UIMSG_BuyInShop_Identify_Repair, 0, 0, "", 0);