diff GUI/UI/UiGame.cpp @ 2501:0ff6a9e9bf7f

GUI folger
author Ritor1
date Fri, 19 Sep 2014 04:21:12 +0600
parents
children a77c34acdbc9
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GUI/UI/UiGame.cpp	Fri Sep 19 04:21:12 2014 +0600
@@ -0,0 +1,2260 @@
+#define _CRTDBG_MAP_ALLOC
+#include <stdlib.h>
+#include <crtdbg.h>
+
+#define _CRT_SECURE_NO_WARNINGS
+#include "..\../Engine/Events.h"
+#include "..\../Engine/Graphics/Texture.h"
+#include "..\../Engine/MM7.h"
+#include "..\../Engine/ErrorHandling.h"
+
+#include "..\../Mouse.h"
+#include "..\../Keyboard.h"
+#include "..\../Engine/mm7_data.h"
+
+#include "..\../Engine/Graphics/Vis.h"
+#include "..\../Engine/MapInfo.h"
+#include "..\../Engine/Game.h"
+#include "..\../GUIWindow.h"
+#include "..\../GUIFont.h"
+#include "..\../Engine/Party.h"
+#include "..\../AudioPlayer.h"
+#include "..\../Engine/Graphics/Outdoor.h"
+#include "..\../Engine/LOD.h"
+#include "..\../Engine/Objects/Actor.h"
+#include "..\../Engine/Graphics/Viewport.h"
+#include "..\../Engine/Objects/SpriteObject.h"
+#include "..\../Engine/Objects/ObjectList.h"
+#include "..\../Engine/Graphics/DecorationList.h"
+#include "..\../Engine/Tables/PlayerFrameTable.h"
+#include "..\../Engine/stru123.h"
+#include "..\../Engine/Timer.h"
+#include "..\../Engine/Tables/IconFrameTable.h"
+#include "..\../Engine/TurnEngine/TurnEngine.h"
+#include "..\../Engine/texts.h"
+#include "UIHouses.h"
+#include "..\../Engine/Graphics/BSPModel.h"
+#include "..\../Engine/OurMath.h"
+#include "..\../Engine/Graphics/Level/Decoration.h"
+#include "..\../Engine/Objects/Chest.h"
+#include "UIGame.h"
+
+#include "..\../Engine/Graphics/Overlays.h"
+
+#include "..\../Engine/Graphics/Sprites.h"
+#include "..\../Engine/Graphics/PaletteManager.h"
+
+int uTextureID_GameUI_CharSelectionFrame; // 50C98C
+
+//----- (00421D00) --------------------------------------------------------
+void __fastcall GameUI_OnPlayerPortraitLeftClick(unsigned int uPlayerID)
+{
+  Player* player = &pParty->pPlayers[uPlayerID - 1];
+  if (pParty->pPickedItem.uItemID)
+  {
+    if (int slot = player->AddItem(-1, pParty->pPickedItem.uItemID))
+    {
+      memcpy(&player->pInventoryItemList[slot-1], &pParty->pPickedItem, 0x24u);
+      viewparams->bRedrawGameUI = true;
+      pMouse->RemoveHoldingItem();
+      return;
+    }
+
+    if (!player->CanAct())
+    {
+      player = pPlayers[uActiveCharacter];
+    }
+    if( player->CanAct() || !pPlayers[uActiveCharacter]->CanAct() )
+      player->PlaySound(SPEECH_NoRoom, 0);
+  }
+
+  if (pCurrentScreen == SCREEN_GAME)
+  {
+    viewparams->bRedrawGameUI = true;
+    if ( uActiveCharacter != uPlayerID )
+    {
+      if ( pPlayers[uPlayerID]->uTimeToRecovery )
+        return;
+
+      uActiveCharacter = uPlayerID;
+      return;
+    }
+    pGUIWindow_CurrentMenu = CharacterUI_Initialize(7);
+    return;
+  }
+  if ( pCurrentScreen == SCREEN_SPELL_BOOK )
+    return;
+  if ( pCurrentScreen == SCREEN_CHEST )
+  {
+    viewparams->bRedrawGameUI = true;
+    if ( uActiveCharacter == uPlayerID )
+    {
+      pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] = 103;
+      pCurrentScreen = SCREEN_CHEST_INVENTORY;
+      uActiveCharacter = uPlayerID;
+      return;
+    }
+    if ( pPlayers[uPlayerID]->uTimeToRecovery )
+      return;
+    uActiveCharacter = uPlayerID;
+    return;
+  }
+  if ( pCurrentScreen != SCREEN_HOUSE )
+  {
+    if ( pCurrentScreen == SCREEN_E )
+    {
+      uActiveCharacter = uPlayerID;
+      return;
+    }
+    if ( pCurrentScreen != SCREEN_CHEST_INVENTORY )
+    {
+      viewparams->bRedrawGameUI = true;
+      uActiveCharacter = uPlayerID;
+      if ( pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] == 102 )
+        FillAwardsData();
+      return;
+    }
+    viewparams->bRedrawGameUI = true;
+    if ( uActiveCharacter == uPlayerID )
+    {
+      pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] = 103;
+      pCurrentScreen = SCREEN_CHEST_INVENTORY;
+      uActiveCharacter = uPlayerID;
+      return;
+    }
+    if ( pPlayers[uPlayerID]->uTimeToRecovery )
+      return;
+    uActiveCharacter = uPlayerID;
+    return;
+  }
+  if ( window_SpeakInHouse->receives_keyboard_input_2 == WINDOW_INPUT_IN_PROGRESS)
+    return;
+  viewparams->bRedrawGameUI = true;
+  if ( uActiveCharacter != uPlayerID )
+  {
+    uActiveCharacter = uPlayerID;
+    return;
+  }
+  if (dialog_menu_id == HOUSE_DIALOGUE_SHOP_BUY_STANDARD || dialog_menu_id == HOUSE_DIALOGUE_SHOP_6)
+  {
+    __debugbreak(); // fix indexing
+    pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] = 103;
+    pGUIWindow_CurrentMenu = CharacterUI_Initialize(14);
+    return;
+  }
+}
+// 4E28F8: using guessed type int pCurrentScreen;
+// F8B19C: using guessed type int dword_F8B19C;
+
+//----- (00416B01) --------------------------------------------------------
+void GameUI_DrawNPCPopup(void *_this)//PopupWindowForBenefitAndJoinText
+{
+  int v1; // edi@2
+  NPCData *pNPC; // eax@16
+  const CHAR *pText; // eax@18
+  char *v11; // esi@26
+  GUIWindow popup_window; // [sp+Ch] [bp-60h]@23
+  int a2; // [sp+60h] [bp-Ch]@16
+  LPCSTR lpsz; // [sp+68h] [bp-4h]@6
+
+  if ( bNoNPCHiring != 1 )
+  {
+    v1 = 0;
+    /*do
+    {
+      if ( v3->pName )
+        pTmpBuf[v1++] = v2;
+      ++v3;
+      ++v2;
+    }
+    while ( (signed int)v3 < (signed int)&pParty->pPickedItem );*/
+    for (int i = 0; i < 2; ++i)
+    {
+     if (pParty->pHirelings[i].pName)
+        pTmpBuf[v1++] = i;
+    }
+    lpsz = 0;
+    if ( (signed int)pNPCStats->uNumNewNPCs > 0 )
+    {
+      /*v4 = pNPCStats->pNewNPCData;
+      do
+      {
+        if ( v4->uFlags & 0x80
+          && (!pParty->pHirelings[0].pName || strcmp(v4->pName, pParty->pHirelings[0].pName))
+          && (!pParty->pHirelings[1].pName || strcmp(v4->pName, pParty->pHirelings[1].pName)) )
+          pTmpBuf[v1++] = (char)lpsz + 2;
+        ++lpsz;
+        ++v4;
+      }
+      while ( (signed int)lpsz < (signed int)pNPCStats->uNumNewNPCs );*/
+      for ( uint i = 0; i < pNPCStats->uNumNewNPCs; ++i )
+      {
+        if (pNPCStats->pNewNPCData[i].Hired())
+        {
+          if (!pParty->pHirelings[0].pName || strcmp((char *)pNPCStats->pNewNPCData[i].pName, (char *)pParty->pHirelings[0].pName))
+          {
+            if (!pParty->pHirelings[1].pName || strcmp((char *)pNPCStats->pNewNPCData[i].pName, (char *)pParty->pHirelings[1].pName))
+              pTmpBuf[v1++] = i + 2;
+          }
+        }
+      }
+    }
+    if ( (signed int)((char *)_this + pParty->hirelingScrollPosition) < v1 )
+    {
+      sDialogue_SpeakingActorNPC_ID = -1 - pParty->hirelingScrollPosition - (int)_this;
+      pNPC = GetNewNPCData(sDialogue_SpeakingActorNPC_ID, &a2);
+      if ( pNPC )
+      {
+        if ( a2 == 57 )
+          pText = pNPCTopics[512].pText; // Baby dragon
+        else
+          pText = (const CHAR *)pNPCStats->pProfessions[pNPC->uProfession].pBenefits;
+        lpsz = pText;
+        if ( !pText )
+        {
+          lpsz = (LPCSTR)pNPCStats->pProfessions[pNPC->uProfession].pJoinText;
+          if ( !lpsz )
+            lpsz = "";
+        }
+        popup_window.Hint = nullptr;
+        popup_window.uFrameX = 38;
+        popup_window.uFrameY = 60;
+        popup_window.uFrameWidth = 276;
+        popup_window.uFrameZ = 313;
+        popup_window.uFrameHeight = pFontArrus->CalcTextHeight(lpsz, &popup_window, 0, 0) + 2 * LOBYTE(pFontArrus->uFontHeight) + 24;
+        if ( (signed int)popup_window.uFrameHeight < 130 )
+          popup_window.uFrameHeight = 130;
+        popup_window.uFrameWidth = 400;
+        popup_window.uFrameZ = popup_window.uFrameX + 399;
+        popup_window.DrawMessageBox(0);
+        sprintfex(pTmpBuf2.data(), "NPC%03d", pNPC->uPortraitID);
+        pRenderer->DrawTextureIndexed(popup_window.uFrameX + 22, popup_window.uFrameY + 36,
+            (Texture *)(pIcons_LOD->LoadTexture(pTmpBuf2.data(), TEXTURE_16BIT_PALETTE) != -1
+            ? &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture(pTmpBuf2.data(), TEXTURE_16BIT_PALETTE)] : 0));
+        if ( pNPC->uProfession )
+        {
+          v11 = pTmpBuf.data();
+          sprintfex(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[429], pNPC->pName, aNPCProfessionNames[pNPC->uProfession]);
+        }
+        else
+        {
+          v11 = pTmpBuf.data();
+          strcpy(pTmpBuf.data(), pNPC->pName);
+        }
+        popup_window.DrawTitleText(pFontArrus, 0, 12, Color16(0xFFu, 0xFFu, 0x9Bu), v11, 3);
+        popup_window.uFrameWidth -= 24;
+        popup_window.uFrameZ = popup_window.uFrameX + popup_window.uFrameWidth - 1;
+        popup_window.DrawText(pFontArrus, 100, 36, 0, BuildDialogueString((char *)lpsz, uActiveCharacter - 1, 0, 0, 0, 0), 0, 0, 0);
+      }
+    }
+  }
+}
+
+//----- (00445D4A) --------------------------------------------------------
+void GameUI_InitializeDialogue(Actor *actor, int bPlayerSaysHello)
+{
+  NPCData *pNPCInfo; // ebp@1
+  int v9; // esi@8
+  int pNumberContacts; // eax@11
+  char pContainer[32]; // [sp+14h] [bp-28h]@3
+
+  dword_A74CDC = -1;
+  pNPCStats->dword_AE336C_LastMispronouncedNameFirstLetter = -1;
+  pEventTimer->Pause();
+  pMiscTimer->Pause();
+  pAudioPlayer->StopChannels(-1, -1);
+  uDialogueType = 0;
+  sDialogue_SpeakingActorNPC_ID = actor->sNPC_ID;
+  pDialogue_SpeakingActor = actor;
+  pNPCInfo = GetNPCData(actor->sNPC_ID);
+  if ( (pNPCInfo->uFlags & 3) != 2 )
+    pNPCInfo->uFlags = pNPCInfo->uFlags + 1;
+
+  switch (pParty->alignment)
+  {
+    case PartyAlignment_Good:    sprintfex(pContainer, "evt%02d-b", const_2()); break;
+    case PartyAlignment_Neutral: sprintfex(pContainer, "evt%02d", const_2());   break;
+    case PartyAlignment_Evil:    sprintfex(pContainer, "evt%02d-c", const_2()); break;
+  }
+
+  pDialogueNPCCount = 0;
+  uNumDialogueNPCPortraits = 1;
+  pTexture_Dialogue_Background = pIcons_LOD->LoadTexturePtr(pContainer, TEXTURE_16BIT_PALETTE);
+  sprintfex(pContainer, "npc%03u", pNPCInfo->uPortraitID);
+  v9 = 0;
+  pDialogueNPCPortraits[0] = pIcons_LOD->LoadTexturePtr(pContainer, TEXTURE_16BIT_PALETTE);
+  dword_591084 = areWeLoadingTexture;
+  uTextureID_right_panel_loop = uTextureID_right_panel;
+  if ( !pNPCInfo->Hired() && pNPCInfo->Location2D >= 0 )
+  {
+    if ( (signed int)pParty->GetPartyFame() <= pNPCInfo->fame
+      || (pNumberContacts = pNPCInfo->uFlags & 0xFFFFFF7F, (pNumberContacts & 0x80000000u) != 0) )
+    {
+      v9 = 1;
+    }
+	else
+	{
+		if ( pNumberContacts > 1 )
+		{
+		  if ( pNumberContacts == 2 )
+		  {
+			v9 = 3;
+		  }
+		  else
+		  {
+			  if ( pNumberContacts != 3 )
+			  {
+				if ( pNumberContacts != 4 )
+				  v9 = 1;
+			  }
+			  else
+			  {
+				v9 = 2;
+			  }
+		  }
+		}
+		else if ( pNPCInfo->rep )
+		{
+		  v9 = 2;
+		}
+	}
+  }
+  if (sDialogue_SpeakingActorNPC_ID < 0)
+    v9 = 4;
+  pDialogueWindow = GUIWindow::Create(0, 0, window->GetWidth(),  window->GetHeight(), WINDOW_Dialogue, 3, 0);//pNumberContacts = 1, v9 = 0; pNumberContacts = 2, v9 = 3;
+  if (pNPCInfo->Hired() && !pNPCInfo->bHasUsedTheAbility)
+  {
+    if (pNPCInfo->uProfession == 10 ||    //Healer
+        pNPCInfo->uProfession == 11 ||    //Expert Healer
+        pNPCInfo->uProfession == 12 ||    //Master Healer
+        pNPCInfo->uProfession == 33 ||    //Cook
+        pNPCInfo->uProfession == 34 ||    //Chef
+        pNPCInfo->uProfession == 39 ||    //Wind Master
+        pNPCInfo->uProfession == 40 ||    //Water Master
+        pNPCInfo->uProfession == 41 ||    //Gate Master
+        pNPCInfo->uProfession == 42 ||    //Chaplain
+        pNPCInfo->uProfession == 43 ||    //Piper
+        pNPCInfo->uProfession == 52       //Fallen Wizard
+      )
+    {
+      pDialogueWindow->CreateButton(480, 250, 140, LOBYTE(pFontArrus->uFontHeight) - 3, 1, 0, UIMSG_SelectNPCDialogueOption, 9, 0, "", 0);
+      pDialogueWindow->_41D08F_set_keyboard_control_group(4, 1, 0, 1);
+    }
+  }
+
+  pDialogueWindow->CreateButton( 61, 424, 31, 40, 2, 94, UIMSG_SelectCharacter, 1, '1', "", 0);
+  pDialogueWindow->CreateButton(177, 424, 31, 40, 2, 94, UIMSG_SelectCharacter, 2, '2', "", 0);
+  pDialogueWindow->CreateButton(292, 424, 31, 40, 2, 94, UIMSG_SelectCharacter, 3, '3', "", 0);
+  pDialogueWindow->CreateButton(407, 424, 31, 40, 2, 94, UIMSG_SelectCharacter, 4, '4', "", 0);
+
+  if (bPlayerSaysHello && uActiveCharacter && !pNPCInfo->Hired())
+  {
+    if (pParty->uCurrentHour < 5 || pParty->uCurrentHour > 21)
+      pPlayers[uActiveCharacter]->PlaySound(SPEECH_GoodEvening, 0);
+    else
+      pPlayers[uActiveCharacter]->PlaySound(SPEECH_GoodDay, 0);
+  }
+}
+
+//----- (00445350) --------------------------------------------------------
+void GameUI_DrawDialogue()
+{
+  NPCData *pNPC; // ebx@2
+  int pGreetType; // eax@2
+  int pTextHeight; // esi@39
+  GUIButton *pButton; // eax@43
+  int all_text_height; // ebx@93
+  signed int index; // esi@99
+  int v42; // edi@102
+  int v45;
+  unsigned __int16 pTextColor; // ax@104
+  GUIWindow window; // [sp+ACh] [bp-68h]@42
+//  GUIFont *pOutString; // [sp+10Ch] [bp-8h]@39
+  const char *pInString=nullptr; // [sp+110h] [bp-4h]@32
+
+  if ( !pDialogueWindow )
+    return;
+
+  // Window title(Заголовок окна)----
+  memcpy(&window, pDialogueWindow, sizeof(window));
+  pNPC = GetNPCData(sDialogue_SpeakingActorNPC_ID);
+  pGreetType = GetGreetType(sDialogue_SpeakingActorNPC_ID);
+  window.uFrameWidth -= 10;
+  window.uFrameZ -= 10;
+  pRenderer->DrawTextureIndexed(477, 0, pTexture_Dialogue_Background);
+  pRenderer->DrawTextureTransparent(468, 0, (Texture *)(uTextureID_right_panel_loop != -1 ? &pIcons_LOD->pTextures[uTextureID_right_panel_loop] : 0));
+  pRenderer->DrawTextureIndexed(pNPCPortraits_x[0][0] - 4, pNPCPortraits_y[0][0] - 4, (Texture *)(uTextureID_50795C != -1 ? &pIcons_LOD->pTextures[uTextureID_50795C] : 0));
+  pRenderer->DrawTextureIndexed(pNPCPortraits_x[0][0], pNPCPortraits_y[0][0], pDialogueNPCPortraits[0]);
+
+  if (pNPC->uProfession)
+  {
+    assert(pNPC->uProfession < sizeof(aNPCProfessionNames) / sizeof(*aNPCProfessionNames.data())); // sometimes buffer overflows; errors emerge both here and in dialogue text
+    sprintfex(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[429], pNPC->pName, aNPCProfessionNames[pNPC->uProfession]);//^Pi[%s] %s
+  }
+  else if (pNPC->pName)
+    strcpy(pTmpBuf.data(), pNPC->pName);
+
+  window.DrawTitleText(pFontArrus, 483, 112, ui_game_dialogue_npc_name_color, pTmpBuf.data(), 3);
+  pParty->GetPartyFame();
+
+  pInString = nullptr;
+  switch (uDialogueType)
+  {
+    case DIALOGUE_13:
+      pInString = BuildDialogueString(pNPCStats->pProfessions[pNPC->uProfession].pJoinText, uActiveCharacter - 1, 0, 0, 0, 0);
+    break;
+
+    case DIALOGUE_PROFESSION_DETAILS:
+    {
+      //auto prof = pNPCStats->pProfessions[pNPC->uProfession];
+
+      if (dialogue_show_profession_details)
+        pInString = BuildDialogueString(pNPCStats->pProfessions[pNPC->uProfession].pBenefits, uActiveCharacter - 1, 0, 0, 0, 0);
+      else if (pNPC->Hired())
+        pInString = BuildDialogueString(pNPCStats->pProfessions[pNPC->uProfession].pDismissText, uActiveCharacter - 1, 0, 0, 0, 0);
+      else
+        pInString = BuildDialogueString(pNPCStats->pProfessions[pNPC->uProfession].pJoinText, uActiveCharacter - 1, 0, 0, 0, 0);
+    }
+    break;
+
+
+    case DIALOGUE_ARENA_WELCOME:
+      pInString = pGlobalTXT_LocalizationStrings[574]; // "Welcome to the Arena of Life and Death.  Remember, you are only allowed one arena combat per visit.  To fight an arena battle, select the option that best describes your abilities and return to me- if you survive:"
+    break;
+
+    case DIALOGUE_ARENA_FIGHT_NOT_OVER_YET:
+      pInString = pGlobalTXT_LocalizationStrings[577]; //"Get back in there you wimps:"
+    break;
+
+    case DIALOGUE_ARENA_REWARD:
+      sprintfex(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[576], gold_transaction_amount);// "Congratulations on your win: here's your stuff: %u gold."
+      pInString = pTmpBuf.data();
+    break;
+
+    case DIALOGUE_ARENA_ALREADY_WON:
+      pInString = pGlobalTXT_LocalizationStrings[582]; // "You already won this trip to the Arena:"
+    break;
+
+    default:
+      if (uDialogueType > DIALOGUE_18 && uDialogueType < DIALOGUE_EVT_E && !byte_5B0938[0])
+      {
+        pInString = (char *)current_npc_text;
+      }
+      else if (pGreetType == 1)//QuestNPC_greet
+      {
+        if (pNPC->greet)
+        {
+          if ((pNPC->uFlags & 3) == 2)
+            pInString = pNPCStats->pNPCGreetings[pNPC->greet].pGreeting2;
+          else
+            pInString = pNPCStats->pNPCGreetings[pNPC->greet].pGreeting1;
+        }
+      }
+      else if (pGreetType == 2)//HiredNPC_greet
+      {
+        NPCProfession* prof = &pNPCStats->pProfessions[pNPC->uProfession];
+
+        if (pNPC->Hired())
+          pInString = BuildDialogueString(prof->pDismissText, uActiveCharacter - 1, 0, 0, 0, 0);
+        else
+          pInString = BuildDialogueString(prof->pJoinText, uActiveCharacter - 1, 0, 0, 0, 0);
+      }
+    break;
+  }
+
+  // Message window(Окно сообщения)---- 
+  if (pInString)
+  {
+    window.uFrameWidth = game_viewport_width;
+    window.uFrameZ = 452;
+    GUIFont* font = pFontArrus;
+    pTextHeight = pFontArrus->CalcTextHeight(pInString, &window, 13, 0) + 7;
+    if ( 352 - pTextHeight < 8 )
+    {
+      font = pFontCreate;
+       pTextHeight = pFontCreate->CalcTextHeight(pInString, &window, 13, 0) + 7;
+    }
+    if (uTextureID_Leather != -1)
+      pRenderer->GetLeather(8, 352 - pTextHeight, &pIcons_LOD->pTextures[uTextureID_Leather], pIcons_LOD->pTextures[uTextureID_Leather].uTextureHeight - pTextHeight);
+    pRenderer->DrawTextureIndexed(8, 347 - pTextHeight, pTexture_591428);
+    pDialogueWindow->DrawText(font, 13, 354 - pTextHeight, 0, FitTextInAWindow(pInString, font,  &window, 13, 0), 0, 0, 0);
+  }
+  // Right panel(Правая панель)------- 
+  memcpy(&window, pDialogueWindow, sizeof(window));
+  window.uFrameX = 483;
+  window.uFrameWidth = 148;
+  window.uFrameZ = 334;
+  for (int i = window.pStartingPosActiveItem; i < window.pStartingPosActiveItem + window.pNumPresenceButton; ++i)
+  {
+    pButton = window.GetControl(i);
+    if ( !pButton )
+      break;
+
+    if ( pButton->msg_param > 88 )
+      pButton->pButtonName[0] = 0;
+    else if (pButton->msg_param == 88)
+      strcpy(pButton->pButtonName, pGlobalTXT_LocalizationStrings[581]); // Lord
+    else if (pButton->msg_param == 87)
+      strcpy(pButton->pButtonName, pGlobalTXT_LocalizationStrings[580]); // Knight
+    else if (pButton->msg_param == 86)
+      strcpy(pButton->pButtonName, pGlobalTXT_LocalizationStrings[579]); // Squire
+    else if (pButton->msg_param == 85)
+      strcpy(pButton->pButtonName, pGlobalTXT_LocalizationStrings[578]); // Page
+    else if (pButton->msg_param == 77)
+      strcpy(pButton->pButtonName, pGlobalTXT_LocalizationStrings[407]); // Details
+    else if (pButton->msg_param == 76)
+    {
+      if (pNPC->Hired())
+        sprintf(pButton->pButtonName, (const char*)pGlobalTXT_LocalizationStrings[408], pNPC->pName); // Release %s
+      else
+        strcpy(pButton->pButtonName, pGlobalTXT_LocalizationStrings[406]); // Hire
+    }
+    else if (pButton->msg_param == 24)
+    {
+      __debugbreak(); // learn conditions of this event
+      if (!pNPC->evt_F)
+      {
+        pButton->pButtonName[0] = 0;
+        pButton->msg_param = 0;
+      }
+      else
+        strcpy(pButton->pButtonName, pNPCTopics[pNPC->evt_F].pTopic);
+    }
+    else if (pButton->msg_param == 9)
+      strcpy(pButton->pButtonName, GetProfessionActionText(pNPC->uProfession));
+    else if (pButton->msg_param == 19) // Scavenger Hunt
+    {
+      if (!pNPC->evt_A)
+      {
+        pButton->pButtonName[0] = 0;
+        pButton->msg_param = 0;
+      }
+      else
+        strcpy(pButton->pButtonName, pNPCTopics[pNPC->evt_A].pTopic);
+    }
+    else if (pButton->msg_param == 20) // Scavenger Hunt
+    {
+      if (!pNPC->evt_B)
+      {
+        pButton->pButtonName[0] = 0;
+        pButton->msg_param = 0;
+      }
+      else strcpy(pButton->pButtonName, pNPCTopics[pNPC->evt_B].pTopic);
+    }
+    else if (pButton->msg_param == 21)
+    {
+      //__debugbreak(); // learn conditions of this event
+      if (!pNPC->evt_C)
+      {
+        pButton->pButtonName[0] = 0;
+        pButton->msg_param = 0;
+      }
+      else strcpy(pButton->pButtonName, pNPCTopics[pNPC->evt_C].pTopic);
+    }
+    else if (pButton->msg_param == 22)
+    {
+      //__debugbreak(); // learn conditions of this event
+      if (!pNPC->evt_D)
+      {
+        pButton->pButtonName[0] = 0;
+        pButton->msg_param = 0;
+      }
+      else strcpy(pButton->pButtonName, pNPCTopics[pNPC->evt_D].pTopic);
+    }
+    else if (pButton->msg_param == 23)
+    {
+      //__debugbreak(); // learn conditions of this event
+      if (!pNPC->evt_E)
+      {
+        pButton->pButtonName[0] = 0;
+        pButton->msg_param = 0;
+      }
+      else strcpy(pButton->pButtonName, pNPCTopics[pNPC->evt_E].pTopic);
+    }
+    else if (pButton->msg_param == 13)
+    {
+      if (pNPC->Hired())
+        sprintf(pButton->pButtonName, pGlobalTXT_LocalizationStrings[408], pNPC->pName); // Release %s
+      else
+        strcpy(pButton->pButtonName, pGlobalTXT_LocalizationStrings[122]); // Join
+    }
+    else
+      pButton->pButtonName[0] = 0;
+
+    if (pParty->field_7B5_in_arena_quest && pParty->field_7B5_in_arena_quest != -1)
+    {
+      int num_dead_actors = 0;
+      pInString = nullptr;
+      for ( uint i = 0; i < uNumActors; ++i )
+      {
+        if (pActors[i].uAIState == Dead || pActors[i].uAIState == Removed || pActors[i].uAIState  == Disabled)
+          ++num_dead_actors;
+        else
+        {
+          int sumonner_type = PID_TYPE(pActors[i].uSummonerID);
+          if (sumonner_type == OBJECT_Player)
+            ++num_dead_actors;
+        }
+      }
+      if (num_dead_actors == uNumActors)
+        strcpy(pButton->pButtonName, pGlobalTXT_LocalizationStrings[658]); // Collect Prize
+    }
+  }
+
+  // Install Buttons(Установка кнопок)-------- 
+  index = 0;
+  all_text_height = 0;
+  for ( int i = pDialogueWindow->pStartingPosActiveItem;
+        i < pDialogueWindow->pStartingPosActiveItem + pDialogueWindow->pNumPresenceButton; ++i )
+  {
+    pButton = pDialogueWindow->GetControl(i);
+    if ( !pButton )
+      break;
+    all_text_height += pFontArrus->CalcTextHeight(pButton->pButtonName, &window, 0, 0);
+    index++;
+  }
+  if ( index )
+  {
+    v45 = (174 - all_text_height) / index;
+    if ( v45 > 32 )
+      v45 = 32;
+    v42 = (174 - v45 * index - all_text_height)/ 2 - v45 / 2 + 138;
+    for ( int i = pDialogueWindow->pStartingPosActiveItem;
+          i < pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem; ++i )
+    {
+      pButton = pDialogueWindow->GetControl(i);
+      if ( !pButton )
+        break;
+      pButton->uY = (unsigned int)(v45 + v42);
+      pTextHeight = pFontArrus->CalcTextHeight(pButton->pButtonName, &window, 0, 0);
+      pButton->uHeight = pTextHeight;
+      v42 = pButton->uY + pTextHeight - 1;
+      pButton->uW = v42;
+      pTextColor = ui_game_dialogue_option_normal_color;
+      if ( pDialogueWindow->pCurrentPosActiveItem == i )
+		pTextColor = ui_game_dialogue_option_highlight_color;
+      window.DrawTitleText(pFontArrus, 0, pButton->uY, pTextColor, pButton->pButtonName, 3);
+    }
+  }
+  pRenderer->DrawTextureIndexed(471, 445, pIcons_LOD->GetTexture(uExitCancelTextureId));
+}
+
+//----- (00444FBE) --------------------------------------------------------
+void GameUI_DrawBranchlessDialogue()
+{
+  int pTextHeight; // esi@4
+  char Str[200]; // [sp+Ch] [bp-120h]@12
+  GUIWindow BranchlessDlg_window; // [sp+D4h] [bp-58h]@4
+  GUIFont *pFont; // [sp+128h] [bp-4h]@1
+
+  pFont = pFontArrus;
+  if ( current_npc_text && !byte_5B0938[0] )
+    strcpy(byte_5B0938.data(), current_npc_text);
+  BranchlessDlg_window.uFrameWidth = game_viewport_width;
+  BranchlessDlg_window.uFrameZ = 452;
+  pTextHeight = pFontArrus->CalcTextHeight(byte_5B0938.data(), &BranchlessDlg_window, 12, 0) + 7;
+  if ( 352 - pTextHeight < 8 )
+  {
+    pFont = pFontCreate;
+    pTextHeight = pFontCreate->CalcTextHeight(byte_5B0938.data(), &BranchlessDlg_window, 12, 0) + 7;
+  }
+  pRenderer->GetLeather(8, 352 - pTextHeight, pIcons_LOD->GetTexture(uTextureID_Leather), pIcons_LOD->GetTexture(uTextureID_Leather)->uTextureHeight - pTextHeight);
+  pRenderer->DrawTextureIndexed(8, 347 - pTextHeight, pTexture_591428);
+  pGUIWindow2->DrawText(pFont, 12, 354 - pTextHeight, 0, FitTextInAWindow(byte_5B0938.data(), pFont, &BranchlessDlg_window, 12, 0), 0, 0, 0);
+  pRenderer->DrawTextureRGB(0, 0x160u, pTexture_StatusBar);
+  if ( pGUIWindow2->receives_keyboard_input_2 != WINDOW_INPUT_IN_PROGRESS)
+  {
+    if ( pGUIWindow2->receives_keyboard_input_2 == WINDOW_INPUT_CONFIRMED)
+    {
+      pGUIWindow2->receives_keyboard_input_2 = WINDOW_INPUT_NONE;
+      strcpy(GameUI_Footer_TimedString.data(), pKeyActionMap->pPressedKeysBuffer);
+      sub_4452BB();
+      return;
+    }
+    if ( pGUIWindow2->receives_keyboard_input_2 != WINDOW_INPUT_CANCELLED)
+      return;
+    pGUIWindow2->receives_keyboard_input_2 = WINDOW_INPUT_NONE;
+    memset(GameUI_Footer_TimedString.data(), 0, 0xC8u);
+    sub_4452BB();
+    return;
+  }
+  if ( pGUIWindow2->ptr_1C == (void *)26 )
+  {
+    sprintf(Str, "%s %s", GameUI_Footer_TimedString, pKeyActionMap->pPressedKeysBuffer);
+    pGUIWindow2->DrawText(pFontLucida, 13, 357, 0, Str, 0, 0, 0);
+    pGUIWindow2->DrawFlashingInputCursor(pFontLucida->GetLineWidth(Str) + 13, 357, pFontLucida);
+    return;
+  }
+  if ( pKeyActionMap->pPressedKeysBuffer[0] )
+  {
+    pKeyActionMap->SetWindowInputStatus(WINDOW_INPUT_NONE);
+    memset(GameUI_Footer_TimedString.data(), 0, 0xC8u);
+    sub_4452BB();
+    return;
+  }
+}
+
+//----- (004443D5) --------------------------------------------------------
+const char *GameUI_GetMinimapHintText()
+{
+  double v3; // st7@1
+  int v7; // eax@4
+  const char *v14; // eax@8
+  char *result; // eax@12
+  unsigned int pMapID; // eax@14
+  int global_coord_X; // [sp+10h] [bp-1Ch]@1
+  int global_coord_Y; // [sp+14h] [bp-18h]@1
+  unsigned int pY; // [sp+1Ch] [bp-10h]@1
+  unsigned int pX; // [sp+28h] [bp-4h]@1
+
+  result = 0;
+  pMouse->GetClickPos(&pX, &pY);
+  v3 = 1.0 / (float)((signed int)viewparams->uMinimapZoom * 0.000015258789);
+  global_coord_X = (signed __int64)((double)(pX - 557) * v3 + (double)pParty->vPosition.x);
+  global_coord_Y = (signed __int64)((double)pParty->vPosition.y - (double)(pY - 74) * v3);
+  if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor || pOutdoor->uNumBModels <= 0 )
+  {
+    pMapID = pMapStats->GetMapInfo(pCurrentMapName);
+    if ( pMapID == 0 )
+      result = "No Maze Info for this maze on file!";
+    else
+      result = pMapStats->pInfos[pMapID].pName;
+  }
+  else
+  {
+    for ( uint j = 0; j < (uint)pOutdoor->uNumBModels; ++j )
+    {
+      v7 = int_get_vector_length(abs((signed)pOutdoor->pBModels[j].vBoundingCenter.x - global_coord_X),
+                                 abs((signed)pOutdoor->pBModels[j].vBoundingCenter.y - global_coord_Y), 0);
+      if ( v7 < 2 * pOutdoor->pBModels[j].sBoundingRadius )
+      {
+        if ( pOutdoor->pBModels[j].uNumFaces )
+        {
+          for ( uint i = 0; i < (uint)pOutdoor->pBModels[j].uNumFaces; ++i )
+          {
+            if ( pOutdoor->pBModels[j].pFaces[i].sCogTriggeredID )
+            {
+              if ( !(pOutdoor->pBModels[j].pFaces[i].uAttributes & FACE_HAS_EVENT) )
+              {
+                v14 = GetEventHintString(pOutdoor->pBModels[j].pFaces[i].sCogTriggeredID);
+                if ( v14 )
+                {
+                  if ( _stricmp(v14, "") )
+                    result = (char *)v14;
+                }
+              }
+            }
+          }
+        }
+        if ( result )
+          return result;
+      }
+    }
+    pMapID = pMapStats->GetMapInfo(pCurrentMapName);
+    if ( pMapID == 0 )
+      result = "No Maze Info for this maze on file!";
+    else
+      result = pMapStats->pInfos[pMapID].pName;
+    return result;
+  }
+  return result;
+}
+
+//----- (0041D3B7) --------------------------------------------------------
+void GameUI_CharacterQuickRecord_Draw(GUIWindow *window, Player *player)
+{
+  Texture *v13; // eax@6
+  PlayerFrame *v15; // eax@12
+  unsigned int pTextColor; // eax@15
+  const char *v29; // eax@16
+  int v36; // esi@22
+  const char *v39; // eax@24
+  signed int uFramesetID; // [sp+20h] [bp-8h]@9
+  int uFramesetIDa; // [sp+20h] [bp-8h]@18
+
+  uint numActivePlayerBuffs = 0;
+  for (uint i = 0; i < 24; ++i)
+    if (player->pPlayerBuffs[i].uExpireTime > 0)
+      ++numActivePlayerBuffs;
+
+  window->uFrameHeight = ((pFontArrus->uFontHeight + 162) + ((numActivePlayerBuffs - 1) * pFontArrus->uFontHeight));
+  window->uFrameZ = window->uFrameWidth + window->uFrameX - 1;
+  window->uFrameW = ((pFontArrus->uFontHeight + 162) + ((numActivePlayerBuffs - 1) * pFontArrus->uFontHeight)) + window->uFrameY - 1;
+  window->DrawMessageBox(0);
+
+  if (player->IsEradicated())
+    v13 = pTexture_PlayerFaceEradicated;
+  else if (player->IsDead())
+    v13 = pTexture_PlayerFaceDead;
+  else
+  {
+      uFramesetID = pPlayerFrameTable->GetFrameIdByExpression(player->expression);
+      if ( !uFramesetID )
+        uFramesetID = 1;
+      if ( player->expression == CHARACTER_EXPRESSION_21)
+        v15 = pPlayerFrameTable->GetFrameBy_y(&player->_expression21_frameset, &player->_expression21_animtime, pMiscTimer->uTimeElapsed);
+      else
+        v15 = pPlayerFrameTable->GetFrameBy_x(uFramesetID, pMiscTimer->Time());
+      player->field_1AA2 = v15->uTextureID - 1;
+      v13 = pTextures_PlayerFaces[(unsigned int)window->ptr_1C][v15->uTextureID - 1];
+  }
+
+  pRenderer->DrawTextureTransparent(window->uFrameX + 24, window->uFrameY + 24, v13);
+
+  sprintfex(pTmpBuf.data(), "\f%05d", ui_character_header_text_color);
+  sprintfex(pTmpBuf2.data(), pGlobalTXT_LocalizationStrings[429], player->pName, pClassNames[player->classType]); // "%s the %s"
+  strcat(pTmpBuf.data(), pTmpBuf2.data());
+  strcat(pTmpBuf.data(), "\f00000\n");
+
+  pTextColor = UI_GetHealthManaAndOtherQualitiesStringColor(player->sHealth, player->GetMaxHealth());
+  sprintfex(pTmpBuf2.data(), "%s : \f%05u%d\f00000 / %d\n", pGlobalTXT_LocalizationStrings[108], // "Hit Points"
+            pTextColor, player->sHealth, player->GetMaxHealth());
+  strcat(pTmpBuf.data(), pTmpBuf2.data());
+
+  pTextColor = UI_GetHealthManaAndOtherQualitiesStringColor(player->sMana, player->GetMaxMana());
+  sprintfex(pTmpBuf2.data(), "%s : \f%05u%d\f00000 / %d\n", pGlobalTXT_LocalizationStrings[212], // "Spell Points"
+            pTextColor, player->sMana, player->GetMaxMana());
+  strcat(pTmpBuf.data(), pTmpBuf2.data());
+
+  pTextColor = player->GetMajorConditionIdx();
+  sprintfex(pTmpBuf2.data(), "%s: \f%05d%s\f00000\n", pGlobalTXT_LocalizationStrings[47], // "Condition
+            GetConditionDrawColor(pTextColor), aCharacterConditionNames[pTextColor]);
+  strcat(pTmpBuf.data(), pTmpBuf2.data());
+
+  if ( player->uQuickSpell )
+    v29 = pSpellStats->pInfos[player->uQuickSpell].pShortName;
+  else
+    v29 = pGlobalTXT_LocalizationStrings[153];
+  sprintfex(pTmpBuf2.data(), "%s: %s", pGlobalTXT_LocalizationStrings[172], v29); // "Quick Spell"
+  strcat(pTmpBuf.data(), pTmpBuf2.data());
+
+  window->DrawText(pFontArrus, 120, 22, 0, pTmpBuf.data(), 0, 0, 0);
+
+  uFramesetIDa = 0;
+  for (uint i = 0; i < 24; ++i)
+  {
+    SpellBuff* buff = &player->pPlayerBuffs[i];
+    if (buff->uExpireTime > 0)
+    {
+      v36 = uFramesetIDa++ * pFontComic->uFontHeight + 134;
+      window->DrawText(pFontComic, 52, v36, ui_game_character_record_playerbuff_colors[i], aSpellNames[20 + i], 0, 0, 0);
+      DrawBuff_remaining_time_string(v36, window, buff->uExpireTime - pParty->uTimePlayed, pFontComic);
+    }
+  }
+
+  v39 = "";
+  if ( uFramesetIDa == 0 )
+    v39 = pGlobalTXT_LocalizationStrings[153]; // "None"
+  sprintfex(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[450], v39); // "Active Spells: %s"
+  window->DrawText(pFontArrus, 14, 114, 0, pTmpBuf.data(), 0, 0, 0);
+}
+
+//----- (0041A57E) --------------------------------------------------------
+void GameUI_QuickRef_Draw()
+{
+  unsigned int pTextColor; // eax@7
+  unsigned int pX; // [sp+14h] [bp-18h]@2
+  unsigned int pY; // edi@9
+  int pSkillsCount; // ecx@27
+  const char *pText; // eax@38
+  int pFontHeight; // [sp+18h] [bp-14h]@1
+
+  pRenderer->DrawTextureIndexed(8, 8, pIcons_LOD->LoadTexturePtr("quikref", TEXTURE_16BIT_PALETTE));
+  pFontHeight = LOBYTE(pFontArrus->uFontHeight) + 1;
+  for ( uint i = 0; i < 4; ++i )
+  {
+    Player* player = &pParty->pPlayers[i];
+    pX = 94 * i + 89;
+    if ( i == 0 )
+      pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, 22, 18, 0, pGlobalTXT_LocalizationStrings[149], 60, 0);//Name
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, 94 * i + 89, 18, ui_character_header_text_color, player->pName, 84, 0);
+    if ( i == 0 )
+      pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, 22, 47, 0, pGlobalTXT_LocalizationStrings[131], 60, 0); //Уров.
+    sprintf(pTmpBuf.data(), "%lu", player->GetActualLevel());
+    if ( player->GetActualLevel() <= player->GetBaseLevel())
+      pTextColor = player->GetExperienceDisplayColor();
+    else
+      pTextColor = ui_character_bonus_text_color;
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, pX, 47, pTextColor, pTmpBuf.data(), 84, 0);
+    pY = pFontHeight + 47;
+    if ( i == 0 )
+      pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, 22, pFontHeight + 47, 0, pGlobalTXT_LocalizationStrings[41], 60, 0);//Класс
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, pX, pY, 0, pClassNames[player->classType], 84, 0);
+    pY = pFontHeight + pY;
+    if ( i == 0 )
+      pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, 22, pY, 0, pGlobalTXT_LocalizationStrings[107], 60, 0);//Здор.
+    sprintf(pTmpBuf.data(), "%d", player->sHealth);
+    pTextColor = UI_GetHealthManaAndOtherQualitiesStringColor(player->sHealth, player->GetMaxHealth());
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, pX, pY, pTextColor, pTmpBuf.data(), 84, 0);
+    pY = pFontHeight + pY;
+    if ( i == 0 )
+      pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, 22, pY, 0, pGlobalTXT_LocalizationStrings[209], 60, 0);//Мана
+    sprintf(pTmpBuf.data(), "%d", player->sMana);
+    pTextColor = UI_GetHealthManaAndOtherQualitiesStringColor(player->sMana, player->GetMaxMana());
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, pX, pY, pTextColor, pTmpBuf.data(), 84, 0);
+    pY = pFontHeight + pY;
+    if ( i == 0 )
+      pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, 22, pY, 0, pGlobalTXT_LocalizationStrings[0], 60, 0);//Класс брони
+    sprintf(pTmpBuf.data(), "%d", player->GetActualAC());
+    pTextColor = UI_GetHealthManaAndOtherQualitiesStringColor(player->GetActualAC(), player->GetBaseAC());
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, pX, pY, pTextColor, pTmpBuf.data(), 84, 0);
+    pY = pFontHeight + pY;
+    if ( !i )
+      pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, 22, pY, 0, pGlobalTXT_LocalizationStrings[18], 60, 0);//Атака
+    sprintf(pTmpBuf.data(), "%+d", player->GetActualAttack(false));
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, pX, pY, 0, pTmpBuf.data(), 84, 0);
+    pY = pFontHeight + pY;
+    if ( !i )
+      pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, 22, pY, 0, pGlobalTXT_LocalizationStrings[66], 60, 0);//Повр.
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, pX, pY, 0, player->GetMeleeDamageString(), 84, 0);
+    pY = pFontHeight + pY;
+    if ( !i )
+      pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, 22, pY, 0, pGlobalTXT_LocalizationStrings[203], 60, 0);// Стрелять
+    sprintf(pTmpBuf.data(), "%+d", player->GetRangedAttack());
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, pX, pY, 0, pTmpBuf.data(), 84, 0);
+    pY = pFontHeight + pY;
+    if ( !i )
+      pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, 22, pY, 0, pGlobalTXT_LocalizationStrings[66], 60, 0);//Повр.
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, pX, pY, 0, player->GetRangedDamageString(), 84, 0);
+    pY = pFontHeight + pY;
+    if ( !i )
+      pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, 22, pY, 0, pGlobalTXT_LocalizationStrings[205], 60, 0);//Навыки
+    pSkillsCount = 0;
+    for ( uint j = 0; j <= 36; ++j )
+    {
+      if ( player->pActiveSkills[j] )
+      ++pSkillsCount;
+    }
+    sprintf(pTmpBuf.data(), "%lu", pSkillsCount);
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, pX, pY, 0, pTmpBuf.data(), 84, 0);
+    pY = pFontHeight + pY;
+    if ( !i )
+      pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, 22, pY, 0, pGlobalTXT_LocalizationStrings[168], 60, 0);//Очки
+    sprintf(pTmpBuf.data(), "%lu", player->uSkillPoints);
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, pX, pY, player->uSkillPoints ? ui_character_bonus_text_color : ui_character_default_text_color, pTmpBuf.data(), 84, 0);
+    pY = pFontHeight + pY;
+    if ( !i )
+      pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, 22, pY, 0, pGlobalTXT_LocalizationStrings[45], 60, 0);//Сост.
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, pX, pY, pTextColor, aCharacterConditionNames[player->GetMajorConditionIdx()], 84, 0);
+    pY = pFontHeight + pY;
+    if ( !i )
+      pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, 22, pY, 0, pGlobalTXT_LocalizationStrings[170], 60, 0);//Б.Прим.
+    if (player->uQuickSpell)
+      pText = pSpellStats->pInfos[player->uQuickSpell].pShortName;
+    else
+      pText = pGlobalTXT_LocalizationStrings[153];//Нет
+    pGUIWindow_CurrentMenu->DrawTextInRect(pFontArrus, pX, pY, 0, pText, 84, 0);
+  }
+
+  if ( pParty->GetPartyReputation() >= 0 )
+  {
+    if ( pParty->GetPartyReputation() <= 5 )
+      pTextColor = ui_character_default_text_color;
+    else
+      pTextColor = ui_character_bonus_text_color_neg;
+  }
+  else
+    pTextColor = ui_character_bonus_text_color;
+
+  sprintf(pTmpBuf.data(), "%s: \f%05d%s\f00000", pGlobalTXT_LocalizationStrings[180], pTextColor, GetReputationString(pParty->GetPartyReputation()));//Reputation
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 22, 323, 0, pTmpBuf.data(), 0, 0, 0);
+  sprintf(pTmpBuf.data(), "\r261%s: %d", pGlobalTXT_LocalizationStrings[84], pParty->GetPartyFame());// Fame Слава
+  pGUIWindow_CurrentMenu->DrawText(pFontArrus, 0, 323, 0, pTmpBuf.data(), 0, 0, 0);
+}
+
+//----- (0041AD6E) --------------------------------------------------------
+void GameUI_DrawRightPanelItems()
+{
+  if ( (unsigned long long)GameUI_RightPanel_BookFlashTimer > pParty->uTimePlayed )
+    GameUI_RightPanel_BookFlashTimer = 0;
+
+  if ( pParty->uTimePlayed - GameUI_RightPanel_BookFlashTimer > 128 )
+  {
+    GameUI_RightPanel_BookFlashTimer = pParty->uTimePlayed;
+    
+    static bool byte_50697C = false; // 50697C
+    byte_50697C = !byte_50697C;
+    if ( byte_50697C && pCurrentScreen != SCREEN_REST )
+    {
+      if (bFlashQuestBook)     pRenderer->DrawTextureTransparent(493, 355, pIcons_LOD->GetTexture(uTextureID_ib_td1_A));
+      if (bFlashAutonotesBook) pRenderer->DrawTextureTransparent(527, 353, pIcons_LOD->GetTexture(uTextureID_ib_td2_A));
+      if (bFlashHistoryBook)   pRenderer->DrawTextureTransparent(600, 361, pIcons_LOD->GetTexture(uTextureID_ib_td5_A));
+    }
+    else
+    {
+      pRenderer->DrawTextureRGB(468, 0, pTexture_RightFrame);
+      GameUI_DrawHiredNPCs();
+    }
+  }
+}
+
+//----- (0041AEBB) --------------------------------------------------------
+void GameUI_DrawFoodAndGold()
+{
+  int text_y; // esi@2
+
+  if ( uGameState != GAME_STATE_FINAL_WINDOW )
+  {
+    text_y = _44100D_should_alter_right_panel() != 0 ? 381 : 322;
+    sprintf(pTmpBuf.data(), "\r087%lu", pParty->uNumFoodRations);
+    pPrimaryWindow->DrawText(pFontSmallnum, 0, text_y, uGameUIFontMain, pTmpBuf.data(), 0, 0, uGameUIFontShadow);
+    sprintf(pTmpBuf.data(), "\r028%lu", pParty->uNumGold);
+    pPrimaryWindow->DrawText(pFontSmallnum, 0, text_y, uGameUIFontMain, pTmpBuf.data(), 0, 0, uGameUIFontShadow);
+  }
+}
+
+//----- (0041B0C9) --------------------------------------------------------
+void GameUI_DrawLifeManaBars()
+{
+  double v3; // st7@3
+  double v7; // st7@25
+  Texture *pTextureHealth; // [sp-4h] [bp-30h]@10
+  Texture *pTextureMana; // [sp+Ch] [bp-20h]@1
+
+  pTextureMana = pIcons_LOD->GetTexture(uTextureID_BarBlue);
+  for (uint i = 0; i < 4; ++i)
+  {
+    if (pParty->pPlayers[i].sHealth > 0)
+    {
+      int v17 = 0;
+      if (i == 2 || i == 3)
+        v17 = 2;
+      v3 = (double)pParty->pPlayers[i].sHealth / (double)pParty->pPlayers[i].GetMaxHealth();
+      if( v3 > 0.5 )
+      {
+        if ( v3 > 1.0 )
+          v3 = 1.0;
+        pTextureHealth = pIcons_LOD->GetTexture(uTextureID_BarGreen);
+      }
+      else if ( v3 > 0.25 )
+        pTextureHealth = pIcons_LOD->GetTexture(uTextureID_BarYellow);
+      else if ( v3 > 0.0 )
+        pTextureHealth = pIcons_LOD->GetTexture(uTextureID_BarRed);
+      if( v3 > 0.0 )
+      {
+        pRenderer->SetTextureClipRect(v17 + pHealthBarPos[i], (signed __int64)((1.0 - v3) * pTextureHealth->uTextureHeight) + 402,
+                                          v17 + pHealthBarPos[i] + pTextureHealth->uTextureWidth, pTextureHealth->uTextureHeight + 402);
+        pRenderer->DrawTextureIndexed(v17 + pHealthBarPos[i], 402, pTextureHealth);
+        pRenderer->ResetTextureClipRect();
+      }
+    }
+    if (pParty->pPlayers[i].sMana > 0)
+    {
+      v7 = pParty->pPlayers[i].sMana / (double)pParty->pPlayers[i].GetMaxMana();
+      if ( v7 > 1.0 )
+        v7 = 1.0;
+      int v17 = 0;
+      if (i == 2)
+        v17 = 1;
+      pRenderer->SetTextureClipRect(v17 + pManaBarPos[i], (signed __int64)((1.0 - v7) * pTextureMana->uTextureHeight) + 402,
+                                    v17 + pManaBarPos[i] + pTextureMana->uTextureWidth, pTextureMana->uTextureHeight + 402);
+      pRenderer->DrawTextureIndexed(v17 + pManaBarPos[i], 402, pTextureMana);
+      pRenderer->ResetTextureClipRect();
+    }
+  }
+}
+
+//----- (0041B3B6) --------------------------------------------------------
+void GameUI_DrawRightPanel()
+{
+  pRenderer->DrawTextureTransparent(pViewport->uViewportBR_X, 0, pIcons_LOD->GetTexture(uTextureID_right_panel));
+}
+
+//----- (0041B3E2) --------------------------------------------------------
+void GameUI_DrawRightPanelFrames()
+{
+  pRenderer->DrawTextureRGB(0,   0,   pTexture_TopFrame);
+  pRenderer->DrawTextureRGB(0,   8,   pTexture_LeftFrame);
+  pRenderer->DrawTextureRGB(468, 0,   pTexture_RightFrame);
+  pRenderer->DrawTextureRGB(0,   352, pTexture_BottomFrame);
+  GameUI_DrawFoodAndGold();
+  GameUI_DrawRightPanelItems();
+}
+
+//----- (0041C047) --------------------------------------------------------
+void GameUI_Footer_2()
+{
+  char *v1; // edx@2
+  int v5; // eax@5
+
+  pRenderer->DrawTextureRGB(0, 352, pTexture_StatusBar);
+  if (GameUI_Footer_TimeLeft)
+    v1 = GameUI_Footer_TimedString.data();
+  else
+  {
+    if (!pFooterString[0])
+      return;
+    v1 = pFooterString.data();
+  }
+
+  v5 = pFontLucida->AlignText_Center(450, v1);
+  pPrimaryWindow->DrawText(pFontLucida, v5 + 11, 357, uGameUIFontMain, v1, 0, 0, uGameUIFontShadow);
+}
+
+//----- (0041C0B8) --------------------------------------------------------
+void GameUI_SetFooterString(const char *pStr)
+{
+  const char *v1; // esi@1
+
+  v1 = pStr;
+  if ( pStr && strcmp(pStr, "test") && !IsBadStringPtrA(pStr, 1) && (*v1 || GameUI_Footer_TimeLeft) )
+  {
+    if ( GameUI_Footer_TimeLeft )
+    {
+      for ( int i = pFontLucida->GetLineWidth(GameUI_Footer_TimedString.data()); i > 450; i = pFontLucida->GetLineWidth(GameUI_Footer_TimedString.data()) )
+        GameUI_Footer_TimedString[strlen(GameUI_Footer_TimedString.data()) - 1] = 0;
+    }
+    else
+    {
+      strcpy(pFooterString.data(), v1);
+      for ( int j = pFontLucida->GetLineWidth(pFooterString.data()); j > 450; j = pFontLucida->GetLineWidth(pFooterString.data()) )
+        pFooterString[strlen(pFooterString.data()) - 1] = 0;
+    }
+  }
+}
+
+//----- (0041C179) --------------------------------------------------------
+void GameUI_Footer()
+{
+  char *v1; // edi@5
+  int v2; // eax@5
+  int v6; // eax@9
+  char v9; // zf@12
+
+  if ( pFooterString[0] || GameUI_Footer_TimeLeft || bForceDrawFooter )
+  {
+    pRenderer->DrawTextureRGB(0, 352, pTexture_StatusBar);
+    if ( GameUI_Footer_TimeLeft )
+    {
+      v1 = GameUI_Footer_TimedString.data();
+      v2 = pFontLucida->GetLineWidth(GameUI_Footer_TimedString.data());
+      while ( v2 > 450 )
+      {
+        GameUI_Footer_TimedString[strlen(GameUI_Footer_TimedString.data()) - 1] = 0;
+        v2 = pFontLucida->GetLineWidth(GameUI_Footer_TimedString.data());
+      }
+    }
+    else
+    {
+      v1 = pFooterString.data();
+      v6 = pFontLucida->GetLineWidth(pFooterString.data());
+      while ( v6 > 450 )
+      {
+        pFooterString[strlen(pFooterString.data()) - 1] = 0;
+        v6 = pFontLucida->GetLineWidth(pFooterString.data());
+      }
+    }
+    v9 = *v1 == 0;
+    bForceDrawFooter = 0;
+    if ( !v9 )
+      pPrimaryWindow->DrawText(pFontLucida, pFontLucida->AlignText_Center(450, v1) + 11, 357, uGameUIFontMain, v1, 0, 0, uGameUIFontShadow);
+  }
+}
+// 5C35BC: using guessed type int bForceDrawFooter;
+//----- (00420EFF) --------------------------------------------------------
+void GameUI_WritePointedObjectStatusString()
+{
+  GUIWindow *pWindow; // edi@7
+  GUIButton *pButton; // ecx@11
+  int requiredSkillpoints; // ecx@19
+  enum UIMessageType pMessageType1; // esi@24
+  int v14; // eax@41
+  ItemGen *pItemGen; // ecx@44
+  int v16; // ecx@46
+  signed int pickedObjectPID; // eax@55
+  signed int v18b;
+  signed int pickedObjectID; // ecx@63
+  BLVFace *pFace; // eax@69
+  const char *pText; // ecx@79
+  enum UIMessageType pMessageType2; // esi@110
+  enum UIMessageType pMessageType3; // edx@117
+  char Str1[200]; // [sp+Ch] [bp-D4h]@129
+  unsigned int pX; // [sp+D4h] [bp-Ch]@1
+  unsigned int pY; // [sp+D8h] [bp-8h]@1
+
+  pMouse->uPointingObjectID = 0;
+  pMouse->GetClickPos(&pX, &pY);
+  if ( pX < 0 || pX > window->GetWidth() - 1 || pY < 0 || pY > window->GetHeight() - 1 )
+    return;
+  if ( pCurrentScreen == SCREEN_GAME )
+  {
+    if ( pX <= (window->GetWidth() - 1) * 0.73125 && pY <= (window->GetHeight() - 1) * 0.73125 ) 
+    {
+      //if ( pRenderer->pRenderD3D )  // inlined mm8::4C1E01
+      {
+        pickedObjectPID = pGame->pVisInstance->get_picked_object_zbuf_val();
+        if ( pX < (unsigned int)pViewport->uScreen_TL_X || pX > (unsigned int)pViewport->uScreen_BR_X
+          || pY < (unsigned int)pViewport->uScreen_TL_Y || pY > (unsigned int)pViewport->uScreen_BR_Y )
+          pickedObjectPID = -1;
+        if ( pickedObjectPID == -1 )
+        {
+          if ( uLastPointedObjectID != 0 )
+          {
+            pFooterString[0] = 0;
+            bForceDrawFooter = 1;
+          }
+          uLastPointedObjectID = 0;
+          return;
+        }
+      }
+      /*else
+      {
+        v18 = pRenderer->pActiveZBuffer[pX + pSRZBufferLineOffsets[pY]];
+      }*/
+      pMouse->uPointingObjectID = (unsigned __int16)pickedObjectPID;
+      pickedObjectID = (signed)PID_ID(pickedObjectPID);
+      if ( PID_TYPE(pickedObjectPID) == OBJECT_Item )
+      {
+        if ( pObjectList->pObjects[pSpriteObjects[pickedObjectID].uObjectDescID].uFlags & 0x10 )
+        {
+          pMouse->uPointingObjectID = 0;
+          pFooterString[0] = 0;
+          bForceDrawFooter = 1;
+          uLastPointedObjectID = 0;
+          return;
+        }
+        if ( pickedObjectPID >= 0x2000000u || pParty->pPickedItem.uItemID )
+        {
+          GameUI_SetFooterString(pSpriteObjects[pickedObjectID].stru_24.GetDisplayName());
+        }
+        else
+        {
+          sprintfex(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[470], pSpriteObjects[pickedObjectID].stru_24.GetDisplayName());// "Get %s"
+          GameUI_SetFooterString(pTmpBuf.data());
+        } //intentional fallthrough
+      }
+      else if ( PID_TYPE(pickedObjectPID) == OBJECT_Decoration )
+      {
+        if ( !pLevelDecorations[pickedObjectID].uEventID )
+        {
+          if ( pLevelDecorations[pickedObjectID].IsInteractive() )
+            pText = pNPCTopics[stru_5E4C90_MapPersistVars._decor_events[pLevelDecorations[pickedObjectID]._idx_in_stru123 - 75] + 380].pTopic;//неверно для костра
+          else
+            pText = pDecorationList->pDecorations[pLevelDecorations[pickedObjectID].uDecorationDescID].field_20;
+          GameUI_SetFooterString(pText);
+        }
+        else
+        {
+          char* hintString = GetEventHintString(pLevelDecorations[pickedObjectID].uEventID);
+          if (  hintString != '\0' )
+          {
+            GameUI_SetFooterString(hintString);
+          }
+        } //intentional fallthrough
+      }
+      else if ( PID_TYPE(pickedObjectPID) == OBJECT_BModel )
+      {
+        if ( pickedObjectPID < 0x2000000u )
+        {
+          char* newString = nullptr;
+          if ( uCurrentlyLoadedLevelType != LEVEL_Indoor )
+          {
+            v18b = (signed int)(unsigned __int16)pickedObjectPID >> 9;
+            short triggeredId = pOutdoor->pBModels[v18b].pFaces[pickedObjectID & 0x3F].sCogTriggeredID;
+            if (triggeredId != 0)
+            {
+              newString = GetEventHintString(pOutdoor->pBModels[v18b].pFaces[pickedObjectID & 0x3F].sCogTriggeredID);
+            }
+          }
+          else
+          {
+            pFace = &pIndoor->pFaces[pickedObjectID];
+            if ( pFace->uAttributes & FACE_INDICATE )
+            {
+              unsigned short eventId = pIndoor->pFaceExtras[pFace->uFaceExtraID].uEventID;
+              if (eventId != 0)
+              {
+                newString = GetEventHintString(pIndoor->pFaceExtras[pFace->uFaceExtraID].uEventID);
+              }
+            }
+          }
+          if (newString)
+          {
+            GameUI_SetFooterString(newString);
+            if ( pMouse->uPointingObjectID == 0 && uLastPointedObjectID != 0)
+            {
+              pFooterString[0] = 0;
+              bForceDrawFooter = 1;
+            }
+            uLastPointedObjectID = pMouse->uPointingObjectID;
+            return;
+          }
+        }
+        pMouse->uPointingObjectID = 0;
+        pFooterString[0] = 0;
+        bForceDrawFooter = 1;
+        uLastPointedObjectID = 0;
+        return;
+      }
+      else if ( PID_TYPE(pickedObjectPID) == OBJECT_Actor )
+      {          
+        if ( pickedObjectPID >= 0x2000000 )
+        {
+          pMouse->uPointingObjectID = 0;
+          if ( uLastPointedObjectID != 0 )
+          {
+            pFooterString[0] = 0;
+            bForceDrawFooter = 1;
+          }
+          uLastPointedObjectID = 0;
+          return;
+        }
+        if ( pActors[pickedObjectID].dword_000334_unique_name )
+          pText = pMonsterStats->pPlaceStrings[pActors[pickedObjectID].dword_000334_unique_name];
+        else
+          pText = pMonsterStats->pInfos[pActors[pickedObjectID].pMonsterInfo.uID].pName;
+        GameUI_SetFooterString(pText); //intentional fallthrough
+      }
+      if ( pMouse->uPointingObjectID == 0 && uLastPointedObjectID != 0)
+      {
+        pFooterString[0] = 0;
+        bForceDrawFooter = 1;
+      }
+      uLastPointedObjectID = pMouse->uPointingObjectID;
+      return;
+    }
+  }
+  else
+  {    
+    for (int i = uNumVisibleWindows; i > 0; --i)
+    {
+      pWindow = &pWindowList[pVisibleWindowsIdxs[i] - 1];
+      if ( (signed int)pX >= (signed int)pWindow->uFrameX && (signed int)pX <= (signed int)pWindow->uFrameZ
+        && (signed int)pY >= (signed int)pWindow->uFrameY && (signed int)pY <= (signed int)pWindow->uFrameW )
+      {
+        for ( pButton = pWindow->pControlsHead; pButton != nullptr; pButton = pButton->pNext )
+        {
+          switch ( pButton->uButtonType )
+          {
+          case 1://for dialogue window
+            if ( (signed int)pX >= (signed int)pButton->uX && (signed int)pX <= (signed int)pButton->uZ
+              && (signed int)pY >= (signed int)pButton->uY && (signed int)pY <= (signed int)pButton->uW )
+            {
+              pMessageType1 = (UIMessageType)pButton->field_1C;
+              if ( pMessageType1 )
+                pMessageQueue_50CBD0->AddGUIMessage(pMessageType1, pButton->msg_param, 0);
+              GameUI_SetFooterString(pButton->pButtonName);
+              uLastPointedObjectID = 1;
+              return;
+            }
+            break;
+          case 2://hovering over portraits
+            if (pButton->uWidth != 0 && pButton->uHeight != 0)
+            {
+              uint distW = pX - pButton->uX;
+              uint distY = pY - pButton->uY;
+
+              double ratioX = 1.0 * (distW*distW) / (pButton->uWidth*pButton->uWidth);
+              double ratioY = 1.0 * (distY*distY) / (pButton->uHeight*pButton->uHeight);
+
+              if (ratioX + ratioY < 1.0)
+              {
+                pMessageType2 = (UIMessageType)pButton->field_1C;
+                if ( pMessageType2 != 0 )
+                  pMessageQueue_50CBD0->AddGUIMessage(pMessageType2, pButton->msg_param, 0);
+                GameUI_SetFooterString(pButton->pButtonName); // for character name
+                uLastPointedObjectID = 1;
+                return;
+              }
+            }
+            break;
+          case 3:// click on skill
+            if ( pX >= pButton->uX && pX <= pButton->uZ
+              && pY >= pButton->uY && pY <= pButton->uW )
+            {
+              requiredSkillpoints = (LOBYTE(pPlayers[uActiveCharacter]->pActiveSkills[pButton->msg_param]) & 0x3F) + 1;
+              if ( pPlayers[uActiveCharacter]->uSkillPoints < requiredSkillpoints )
+                sprintf(Str1, pGlobalTXT_LocalizationStrings[469], requiredSkillpoints - pPlayers[uActiveCharacter]->uSkillPoints);// "You need %d more Skill Points to advance here"
+              else
+                sprintf(Str1, pGlobalTXT_LocalizationStrings[468], requiredSkillpoints);// "Clicking here will spend %d Skill Points"
+              GameUI_SetFooterString(Str1);
+              uLastPointedObjectID = 1;
+              return;
+            }
+            break;
+          }
+        }
+      }
+      if ( pWindow->uFrameHeight == 480 )
+      {
+        //DebugBreak(); //Why is this condition here (in the original too)? Might check fullscreen windows. Let Silvo know if you find out
+        return;
+      }
+    }
+    //The game never gets to this point even in the original. It's also bugged(neither branch displays anything). 
+    //TODO fix these and move them up before the window check loop.
+    if ( pCurrentScreen == SCREEN_CHEST )
+    {
+      Chest::ChestUI_WritePointedObjectStatusString();
+      if ( uLastPointedObjectID != 0 )
+      {
+        pFooterString[0] = 0;
+        bForceDrawFooter = 1;
+      }
+      uLastPointedObjectID = 0;
+      return;
+    }
+    else if ( pCurrentScreen == SCREEN_HOUSE )
+    {
+      if ( dialog_menu_id != HOUSE_DIALOGUE_SHOP_BUY_STANDARD
+        || (v16 = pRenderer->pActiveZBuffer[pX + pSRZBufferLineOffsets[pY]], v16 == 0)
+        || v16 == -65536 )
+      {
+        if ( uLastPointedObjectID != 0 )
+        {
+          pFooterString[0] = 0;
+          bForceDrawFooter = 1;
+        }
+        uLastPointedObjectID = 0;
+        return;
+      }
+      pItemGen = (ItemGen *)((char *)&pParty->pPickedItem + 36 * (v16 + 12 * (unsigned int)window_SpeakInHouse->ptr_1C) + 4);
+      GameUI_SetFooterString(pItemGen->GetDisplayName());
+      pFooterString[0] = 0;
+      bForceDrawFooter = 1;
+      uLastPointedObjectID = 0;
+      return;
+    }
+    if ( pY < 350 )
+    {
+      v14 = pRenderer->pActiveZBuffer[pX + pSRZBufferLineOffsets[pY]];
+      if ( v14 == 0 || v14 == -65536 || v14 >= 5000 )
+      {
+        if ( pMouse->uPointingObjectID == 0 )
+        {
+          if ( uLastPointedObjectID != 0 )
+          {
+            pFooterString[0] = 0;
+            bForceDrawFooter = 1;
+          }
+        }
+        uLastPointedObjectID = pMouse->uPointingObjectID;
+        return;
+      }
+      pItemGen = (ItemGen *)&pPlayers[uActiveCharacter]->pInventoryItemList[v14-1];
+      GameUI_SetFooterString(pItemGen->GetDisplayName());
+      pFooterString[0] = 0;
+      bForceDrawFooter = 1;
+      uLastPointedObjectID = 0;
+      return;
+    }
+  }
+  if ( (signed int)pX >= (signed int)pWindowList[0].uFrameX && (signed int)pX <= (signed int)pWindowList[0].uFrameZ
+    && (signed int)pY >= (signed int)pWindowList[0].uFrameY && (signed int)pY <= (signed int)pWindowList[0].uFrameW )
+  {
+    for ( pButton = pWindowList[0].pControlsHead; pButton != nullptr; pButton = pButton->pNext )
+    {
+      switch (pButton->uButtonType)
+      {
+      case 1:
+        if ( (signed int)pX >= (signed int)pButton->uX && (signed int)pX <= (signed int)pButton->uZ
+          && (signed int)pY >= (signed int)pButton->uY && (signed int)pY <= (signed int)pButton->uW )
+        {
+          pMessageType3 = (UIMessageType)pButton->field_1C;
+          if ( pMessageType3 == 0 ) // For books
+          {
+            GameUI_SetFooterString(pButton->pButtonName);
+          }
+          else
+          {
+            pMessageQueue_50CBD0->AddGUIMessage(pMessageType3, pButton->msg_param, 0);
+          }
+          uLastPointedObjectID = 1;
+          return;
+        }
+        break;
+      case 2://hovering over portraits
+        if (pButton->uWidth != 0 && pButton->uHeight != 0)
+        {
+          uint distW = pX - pButton->uX;
+          uint distY = pY - pButton->uY;
+
+          double ratioX = 1.0 * (distW*distW) / (pButton->uWidth*pButton->uWidth);
+          double ratioY = 1.0 * (distY*distY) / (pButton->uHeight*pButton->uHeight);
+
+          if (ratioX + ratioY < 1.0)
+          {
+            pMessageType2 = (UIMessageType)pButton->field_1C;
+            if ( pMessageType2 != 0 )
+              pMessageQueue_50CBD0->AddGUIMessage(pMessageType2, pButton->msg_param, 0);
+            GameUI_SetFooterString(pButton->pButtonName); // for character name
+            uLastPointedObjectID = 1;
+            return;
+          }
+        }
+        break;
+      case 3:
+        if ( pX >= pButton->uX && pX <= pButton->uZ
+          && pY >= pButton->uY && pY <= pButton->uW )
+        {
+          requiredSkillpoints = (LOBYTE(pPlayers[uActiveCharacter]->pActiveSkills[pButton->msg_param]) & 0x3F) + 1;
+          if ( pPlayers[uActiveCharacter]->uSkillPoints < requiredSkillpoints )
+            sprintf(Str1, pGlobalTXT_LocalizationStrings[469], requiredSkillpoints - pPlayers[uActiveCharacter]->uSkillPoints);// "You need %d more Skill Points to advance here"
+          else
+            sprintf(Str1, pGlobalTXT_LocalizationStrings[468], requiredSkillpoints);// "Clicking here will spend %d Skill Points"
+          GameUI_SetFooterString(Str1);
+          uLastPointedObjectID = 1;
+          return;
+        }
+        break;
+      }
+    }
+  }
+  //pMouse->uPointingObjectID = sub_46A99B(); //for software
+  if ( uLastPointedObjectID != 0 )
+  {
+    pFooterString[0] = 0;
+    bForceDrawFooter = 1;
+  }
+  uLastPointedObjectID = 0;
+  return;
+}
+
+//----- (0044158F) --------------------------------------------------------
+void GameUI_DrawCharacterSelectionFrame()
+{
+  if ( uActiveCharacter )
+    pRenderer->DrawTextureTransparent(pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing[uActiveCharacter - 1] - 9, 380,
+                                      pIcons_LOD->GetTexture(uTextureID_GameUI_CharSelectionFrame));
+}
+
+//----- (0044162D) --------------------------------------------------------
+void GameUI_DrawPartySpells()
+{
+  unsigned int v0; // ebp@1
+  Texture *spell_texture; // [sp-4h] [bp-1Ch]@12
+  //Texture *v9; // [sp-4h] [bp-1Ch]@21
+
+  v0 = (signed __int64)((double)GetTickCount() * 0.050000001);
+  //v1 = 0;
+  for (uint i = 0; i < 14; ++i)
+  {
+    //v2 =  byte_4E5DD8[v1];
+    if (pParty->pPartyBuffs[byte_4E5DD8[i]].uExpireTime)
+    {
+      Texture* tex = pIcons_LOD->GetTexture(pTextureIDs_PartyBuffIcons[i]);
+      //v3 = pTextureIDs_PartyBuffIcons[i];
+      pRenderer->_4A65CC(pPartySpellbuffsUI_XYs[i][0],
+      pPartySpellbuffsUI_XYs[i][1], tex, tex,
+      v0 + 20 * pPartySpellbuffsUI_smthns[i], 0, 63);
+    }
+    //++v1;
+  }
+  //while ( v1 < 14 );
+  if (pCurrentScreen == SCREEN_GAME || pCurrentScreen == SCREEN_NPC_DIALOGUE)
+  {
+    if (pParty->FlyActive())
+    {
+      if ( pParty->bFlying )
+        spell_texture = pIcons_LOD->GetTexture(pIconsFrameTable->GetFrame(uIconIdx_FlySpell, v0)->uTextureID);
+      else
+        spell_texture = pIcons_LOD->GetTexture(pIconsFrameTable->GetFrame(uIconIdx_FlySpell, 0)->uTextureID);
+      //if ( pRenderer->pRenderD3D )
+        pRenderer->DrawTextureIndexed(8, 8, spell_texture);
+      /*else
+        pRenderer->DrawTextureTransparent(8, 8, v7);*/
+    }
+    if ( pParty->WaterWalkActive() )
+    {
+      if ( pParty->uFlags & PARTY_FLAGS_1_STANDING_ON_WATER )
+        spell_texture = pIcons_LOD->GetTexture(pIconsFrameTable->GetFrame(uIconIdx_WaterWalk, v0)->uTextureID);
+      else
+        spell_texture = pIcons_LOD->GetTexture(pIconsFrameTable->GetFrame(uIconIdx_WaterWalk, 0)->uTextureID);
+      //if ( pRenderer->pRenderD3D )
+        pRenderer->DrawTextureIndexed(396, 8, spell_texture);
+      /*else
+        pRenderer->DrawTextureTransparent(396, 8, v9);*/
+    }
+  }
+  for (uint i = 0; i < 4; ++i)
+  {
+    if ( pParty->pPlayers[i].pPlayerBuffs[PLAYER_BUFF_HAMMERHANDS].uExpireTime )
+      pRenderer->DrawTextureIndexed(pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing[i] + 72, 427, pIcons_LOD->GetTexture(uTextureID_PlayerBuff_Hammerhands));
+    if ( pParty->pPlayers[i].pPlayerBuffs[PLAYER_BUFF_BLESS].uExpireTime )
+      pRenderer->DrawTextureIndexed(pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing[i] + 72, 393, pIcons_LOD->GetTexture(uTextureID_PlayerBuff_Bless));
+    if ( pParty->pPlayers[i].pPlayerBuffs[PLAYER_BUFF_PRESERVATION].uExpireTime )
+      pRenderer->DrawTextureIndexed(pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing[i] + 72, 410, pIcons_LOD->GetTexture(uTextureID_PlayerBuff_Preservation));
+    if ( pParty->pPlayers[i].pPlayerBuffs[PLAYER_BUFF_PAIN_REFLECTION].uExpireTime )
+      pRenderer->DrawTextureIndexed(pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing[i] + 72, 444, pIcons_LOD->GetTexture(uTextureID_PlayerBuff_PainReflection));
+  }
+}
+
+//----- (004921C1) --------------------------------------------------------
+void GameUI_DrawPortraits(unsigned int _this)
+{
+  unsigned int face_expression_ID; // eax@17
+  PlayerFrame *pFrame; // eax@21
+  int pTextureID; // eax@57
+  Texture *pPortrait; // [sp-4h] [bp-1Ch]@27
+
+  if ( _A750D8_player_speech_timer )
+  {
+    _A750D8_player_speech_timer -= (signed int)pMiscTimer->uTimeElapsed;
+    if ( _A750D8_player_speech_timer <= 0 )
+    {
+      if ( pPlayers[uSpeakingCharacter]->CanAct() )
+        pPlayers[uSpeakingCharacter]->PlaySound(PlayerSpeechID, 0);
+      _A750D8_player_speech_timer = 0i64;
+    }
+  }
+
+  for (uint i = 0; i < 4; ++i)
+  {
+    Player* pPlayer = &pParty->pPlayers[i];
+    if ( pPlayer->IsEradicated() )
+    {
+      pPortrait = pTexture_PlayerFaceEradicated;
+      if ( pParty->pPartyBuffs[PARTY_BUFF_INVISIBILITY].uExpireTime )
+        pRenderer->DrawTranslucent(pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing[i], 388, pPortrait);
+      else
+        pRenderer->DrawTextureTransparent(pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing[i] + 1, 388, pPortrait);
+      if ( pPlayer->pPlayerBuffs[PLAYER_BUFF_BLESS].uExpireTime | pPlayer->pPlayerBuffs[PLAYER_BUFF_HASTE].uExpireTime
+         | pPlayer->pPlayerBuffs[PLAYER_BUFF_HEROISM].uExpireTime | pPlayer->pPlayerBuffs[PLAYER_BUFF_SHIELD].uExpireTime
+         | pPlayer->pPlayerBuffs[PLAYER_BUFF_STONESKIN].uExpireTime )
+        sub_441A4E(i);
+      continue;
+    }
+    if (pPlayer->IsDead())
+    {
+      pPortrait = pTexture_PlayerFaceDead;
+      if ( pParty->pPartyBuffs[PARTY_BUFF_INVISIBILITY].uExpireTime )
+        pRenderer->DrawTranslucent(pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing[i], 388, pPortrait);
+      else
+        pRenderer->DrawTextureTransparent(pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing[i] + 1, 388, pPortrait);
+      if ( pPlayer->pPlayerBuffs[PLAYER_BUFF_BLESS].uExpireTime | pPlayer->pPlayerBuffs[PLAYER_BUFF_HASTE].uExpireTime
+         | pPlayer->pPlayerBuffs[PLAYER_BUFF_HEROISM].uExpireTime | pPlayer->pPlayerBuffs[PLAYER_BUFF_SHIELD].uExpireTime
+         | pPlayer->pPlayerBuffs[PLAYER_BUFF_STONESKIN].uExpireTime )
+        sub_441A4E(i);
+      continue;
+    }
+    face_expression_ID = 0;
+    for ( uint j = 0; j < pPlayerFrameTable->uNumFrames; ++j )
+      if ( pPlayerFrameTable->pFrames[j].expression == pPlayer->expression )
+      {
+        face_expression_ID = j;
+        break;
+      }
+    if ( face_expression_ID == 0 )
+      face_expression_ID = 1;
+    if (pPlayer->expression == CHARACTER_EXPRESSION_21)
+      pFrame = pPlayerFrameTable->GetFrameBy_y(&pPlayer->_expression21_frameset, &pPlayer->_expression21_animtime, pMiscTimer->uTimeElapsed);
+    else
+      pFrame = pPlayerFrameTable->GetFrameBy_x(face_expression_ID, pPlayer->uExpressionTimePassed);
+    if (pPlayer->field_1AA2 != pFrame->uTextureID - 1 || _this )
+    {
+      pPlayer->field_1AA2 = pFrame->uTextureID - 1;
+      pPortrait = (Texture *)pTextures_PlayerFaces[i][pPlayer->field_1AA2];//pFace = (Texture *)pTextures_PlayerFaces[i][pFrame->uTextureID];
+      if ( pParty->pPartyBuffs[PARTY_BUFF_INVISIBILITY].uExpireTime )
+        pRenderer->DrawTranslucent(pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing[i], 388, pPortrait);
+      else
+        pRenderer->DrawTextureTransparent(pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing[i] + 1, 388, pPortrait);
+      if ( pPlayer->pPlayerBuffs[PLAYER_BUFF_BLESS].uExpireTime | pPlayer->pPlayerBuffs[PLAYER_BUFF_HASTE].uExpireTime
+         | pPlayer->pPlayerBuffs[PLAYER_BUFF_HEROISM].uExpireTime | pPlayer->pPlayerBuffs[PLAYER_BUFF_SHIELD].uExpireTime
+         | pPlayer->pPlayerBuffs[PLAYER_BUFF_STONESKIN].uExpireTime )
+        sub_441A4E(i);
+      continue;
+    }
+  }
+  if ( pParty->bTurnBasedModeOn == 1 )
+  {
+    if ( pTurnEngine->turn_stage != TE_WAIT )
+    {
+      if (PID_TYPE(pTurnEngine->pQueue[0].uPackedID) == OBJECT_Player)
+      {
+        if ( pTurnEngine->uActorQueueSize > 0 )
+        {
+          for (uint i = 0; i < (uint)pTurnEngine->uActorQueueSize; ++i)
+          {
+            if (PID_TYPE(pTurnEngine->pQueue[i].uPackedID) != OBJECT_Player)
+              break;
+            pTextureID = dword_5079D0;
+            if ( pParty->uFlags & 0x10 )
+              pTextureID = dword_5079CC;
+            else
+            {
+              if ( pParty->uFlags & 0x20 )
+                pTextureID = dword_5079C8;
+            }
+            pRenderer->DrawTextureTransparent(pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing[PID_ID(pTurnEngine->pQueue[i].uPackedID)] - 4, 385, pIcons_LOD->GetTexture(pTextureID));
+          }
+        }
+      }
+    }
+  }
+  else
+  {
+    for (uint i = 0; i < 4; ++i)
+    {
+      if (pParty->pPlayers[i].CanAct() && !pParty->pPlayers[i].uTimeToRecovery)
+      {
+        pTextureID = dword_5079D0;
+        if ( pParty->uFlags & 0x10 )
+          pTextureID = dword_5079CC;
+        else
+        {
+          if ( pParty->uFlags & 0x20 )
+            pTextureID = dword_5079C8;
+        }
+        pRenderer->DrawTextureTransparent(pPlayerPortraitsXCoords_For_PlayerBuffAnimsDrawing[i] - 4, 385, pIcons_LOD->GetTexture(pTextureID));
+      }
+    }
+  }
+}
+
+//----- (00441D38) --------------------------------------------------------
+void GameUI_DrawMinimap(unsigned int uX, unsigned int uY, unsigned int uZ, unsigned int uW, unsigned int uZoom, unsigned int bRedrawOdmMinimap)
+{
+  int uHeight; // ebx@6
+  signed int pW; // ebx@23
+  int v15; // eax@23
+  double v20; // st7@30
+  signed int v27; // eax@37
+  //unsigned __int16 *v28; // ecx@37
+  signed int v29; // edi@40
+  int pPoint_X; // edi@72
+  int pPoint_Y; // ebx@72
+  unsigned int lPitch; // [sp+20h] [bp-34h]@1
+  signed int pY; // [sp+20h] [bp-34h]@23
+  signed int pX; // [sp+24h] [bp-30h]@23
+  signed int v70; // [sp+24h] [bp-30h]@37
+  signed int uBluea; // [sp+28h] [bp-2Ch]@37
+  int v73; // [sp+2Ch] [bp-28h]@30
+  signed int uCenterY; // [sp+48h] [bp-Ch]@1
+  signed int uCenterX; // [sp+4Ch] [bp-8h]@1
+  signed int uWidth; // [sp+5Ch] [bp+8h]@30
+  signed int pZ; // [sp+60h] [bp+Ch]@23
+  float uWb; // [sp+60h] [bp+Ch]@30
+  unsigned int pColor;
+
+  uCenterX = (uX + uZ) / 2;
+  uCenterY = (uY + uW) / 2;
+  lPitch = pRenderer->uTargetSurfacePitch;
+  bool bWizardEyeActive = pParty->WizardEyeActive();
+  int uWizardEyeSkillLevel = pParty->WizardEyeSkillLevel();
+  if ( CheckHiredNPCSpeciality(Cartographer) )
+  {
+    bWizardEyeActive = true;
+    uWizardEyeSkillLevel = 2;
+  }
+
+  if ( wizard_eye )
+  {
+    bWizardEyeActive = true;
+    uWizardEyeSkillLevel = 3;
+  }
+  pRenderer->SetRasterClipRect(uX, uY, uZ - 1, uW - 1);
+  uHeight = uW - uY;
+  uWidth = uZ - uX;
+
+  if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+  {
+    uchar* pMapLod0 = pIcons_LOD->pTextures[viewparams->uTextureID_LocationMap].pLevelOfDetail0_prolly_alpha_mask;
+    ushort* pPal = pIcons_LOD->pTextures[viewparams->uTextureID_LocationMap].pPalette16;
+    v73 = (1 << (pIcons_LOD->pTextures[viewparams->uTextureID_LocationMap].uWidthLn2 + 16)) / (signed int)uZoom;
+    v20 = (double)(pParty->vPosition.x + 32768) / (double)(1 << (16 - pIcons_LOD->pTextures[viewparams->uTextureID_LocationMap].uWidthLn2));
+    uWb = (double)(32768 - pParty->vPosition.y) / (double)(1 << (16 - pIcons_LOD->pTextures[viewparams->uTextureID_LocationMap].uWidthLn2));
+    switch (uZoom)
+    {
+      case 512:
+      {
+        v20 = v20 - (double)(uWidth / 2);
+        uWb = uWb - (double)(uHeight / 2);
+      }
+      break;
+      case 1024:
+      {
+        v20 = v20 - (double)(uWidth / 4);
+        uWb = uWb - (double)(uHeight / 4);
+      }
+      break;
+      case 2048:
+      {
+        v20 = v20 - (double)(uWidth / 8);
+        uWb = uWb - (double)(uHeight / 8);
+      }
+      break;
+      default: assert(false);
+    }
+
+    static unsigned __int16 pOdmMinimap[117][137];
+    assert(sizeof(pOdmMinimap) == 137 * 117 * sizeof(short));
+
+    v70 = floorf(v20 * 65536.0 + 0.5f);//LODWORD(v24);
+    uBluea = floorf(uWb * 65536.0 + 0.5f);//LODWORD(v25);
+    v27 = uBluea >> 16;
+    //v28 = &pRenderer->pTargetSurface[uX + uY * lPitch];
+
+    if (pMapLod0 && bRedrawOdmMinimap)
+    {
+      assert(uWidth == 137 && uHeight == 117);
+      //auto pMinimap = (unsigned __int16 *)pOdmMinimap;
+
+      ushort mapWidth = pIcons_LOD->pTextures[viewparams->uTextureID_LocationMap].uTextureWidth;
+
+      v29 = v70 >> 16;
+      for (int y = 0; y < uHeight; ++y)
+      {
+        uchar* pMapLod0Line = &pMapLod0[v27 * mapWidth];
+        for (int x = 0; x < uWidth; ++x)
+        {
+          //*pMinimap++ = pPal[pMapLod0Line[v29]];
+          pRenderer->WritePixel16(uX + x, uY + y, pPal[pMapLod0Line[v29]]);
+          v29 = (v70 + x * v73) >> 16;
+        }
+        uBluea += v73;
+        v27 = uBluea >> 16;
+      }
+
+      /*v29 = v70 >> 16;
+      for (int y = 0; y < uHeight; ++y)
+      {
+        uchar* pMapLod0Line = &pMapLod0[v27 * mapWidth];
+        for (int x = 0; x < uWidth; ++x)
+        {
+          //*pMinimap++ = pPal[pMapLod0Line[v29]];
+          pOdmMinimap[y][x] = pPal[pMapLod0Line[v29]];
+          v29 = (v70 + x * v73) >> 16;
+        }
+        v29 = v70 >> 16;
+        v28 += 137 - uWidth;
+        uBluea += v73;
+        v27 = uBluea >> 16;
+      }*/
+    }
+
+    /*for (int y = 0; y < 117; ++y)
+    {
+      for (int x = 0; x < 137; ++x)
+      {
+        *v28++ = pOdmMinimap[y][x];
+      }
+      v28 += lPitch - 137;
+    }*/
+    uNumBlueFacesInBLVMinimap = 0;
+  }
+  else// uCurrentlyLoadedLevelType == LEVEL_Indoor
+  {
+    pRenderer->FillRectFast(uX, uY, uZ - uX, uHeight, 0xF);
+    uNumBlueFacesInBLVMinimap = 0;
+
+    for (uint i = 0; i < (uint)pIndoor->pMapOutlines->uNumOutlines; ++i)
+    {
+      BLVMapOutline* pOutline = &pIndoor->pMapOutlines->pOutlines[i];
+      //BLVFace* pFace1 = &pIndoor->pFaces[pOutline->uFace1ID];
+      //BLVFace* pFace2 = &pIndoor->pFaces[pOutline->uFace2ID];
+      if (pIndoor->pFaces[pOutline->uFace1ID].Visible() && pIndoor->pFaces[pOutline->uFace2ID].Visible())
+      {
+        if ( pOutline->uFlags & 1 )
+        {
+          if (bWizardEyeActive && uWizardEyeSkillLevel >= 3 &&
+             (pIndoor->pFaces[pOutline->uFace1ID].Clickable() || pIndoor->pFaces[pOutline->uFace2ID].Clickable()) &&
+             (pIndoor->pFaceExtras[pIndoor->pFaces[pOutline->uFace1ID].uFaceExtraID].uEventID || pIndoor->pFaceExtras[pIndoor->pFaces[pOutline->uFace2ID].uFaceExtraID].uEventID))
+          {
+            if (uNumBlueFacesInBLVMinimap < 49)
+              pBlueFacesInBLVMinimapIDs[uNumBlueFacesInBLVMinimap++] = i;
+          }
+          else
+          {
+            pX = uCenterX + ((signed int)(((unsigned int)(fixpoint_mul(uZoom, pIndoor->pVertices[pIndoor->pMapOutlines->pOutlines[i].uVertex1ID].x)) << 16) - uZoom * pParty->vPosition.x) >> 16);
+            pY = uCenterY - ((signed int)(((unsigned int)(fixpoint_mul(uZoom, pIndoor->pVertices[pIndoor->pMapOutlines->pOutlines[i].uVertex1ID].y)) << 16) - uZoom * pParty->vPosition.y) >> 16);
+            pZ = uCenterX + ((signed int)(((unsigned int)(fixpoint_mul(uZoom, pIndoor->pVertices[pIndoor->pMapOutlines->pOutlines[i].uVertex2ID].x)) << 16) - uZoom * pParty->vPosition.x) >> 16);
+            pW = uCenterY - ((signed int)(((unsigned int)(fixpoint_mul(uZoom, pIndoor->pVertices[pIndoor->pMapOutlines->pOutlines[i].uVertex2ID].y)) << 16) - uZoom * pParty->vPosition.y) >> 16);
+            v15 = abs(pOutline->sZ - pParty->vPosition.z) / 8;
+            if ( v15 > 100 )
+              v15 = 100;
+            pRenderer->RasterLine2D(pX, pY, pZ, pW, viewparams->pPalette[-v15 + 200]);
+          }
+          continue;
+        }
+        if (pIndoor->pFaces[pOutline->uFace1ID].uAttributes & FACE_UNKNOW4 || pIndoor->pFaces[pOutline->uFace2ID].uAttributes & FACE_UNKNOW4)
+        {
+          pOutline->uFlags = pOutline->uFlags | 1;
+          pIndoor->_visible_outlines[i >> 3] |= 1 << (7 - i % 8);
+          if (bWizardEyeActive && uWizardEyeSkillLevel >= 3 &&
+             (pIndoor->pFaces[pOutline->uFace1ID].Clickable() || pIndoor->pFaces[pOutline->uFace2ID].Clickable()) &&
+             (pIndoor->pFaceExtras[pIndoor->pFaces[pOutline->uFace1ID].uFaceExtraID].uEventID || pIndoor->pFaceExtras[pIndoor->pFaces[pOutline->uFace2ID].uFaceExtraID].uEventID))
+          {
+            if (uNumBlueFacesInBLVMinimap < 49)
+              pBlueFacesInBLVMinimapIDs[uNumBlueFacesInBLVMinimap++] = i;
+          }
+          else
+          {
+            pX = uCenterX + ((signed int)(((unsigned int)(fixpoint_mul(uZoom, pIndoor->pVertices[pIndoor->pMapOutlines->pOutlines[i].uVertex1ID].x)) << 16) - uZoom * pParty->vPosition.x) >> 16);
+            pY = uCenterY - ((signed int)(((unsigned int)(fixpoint_mul(uZoom, pIndoor->pVertices[pIndoor->pMapOutlines->pOutlines[i].uVertex1ID].y)) << 16) - uZoom * pParty->vPosition.y) >> 16);
+            pZ = uCenterX + ((signed int)(((unsigned int)(fixpoint_mul(uZoom, pIndoor->pVertices[pIndoor->pMapOutlines->pOutlines[i].uVertex2ID].x)) << 16) - uZoom * pParty->vPosition.x) >> 16);
+            pW = uCenterY - ((signed int)(((unsigned int)(fixpoint_mul(uZoom, pIndoor->pVertices[pIndoor->pMapOutlines->pOutlines[i].uVertex2ID].y)) << 16) - uZoom * pParty->vPosition.y) >> 16);
+            v15 = abs(pOutline->sZ - pParty->vPosition.z) / 8;
+            if ( v15 > 100 )
+              v15 = 100;
+            pRenderer->RasterLine2D(pX, pY, pZ, pW, viewparams->pPalette[-v15 + 200]);
+          }
+          continue;
+        }
+      }
+    }
+
+    for (uint i = 0; i < uNumBlueFacesInBLVMinimap; ++i)
+    {
+      BLVMapOutline* pOutline = &pIndoor->pMapOutlines->pOutlines[pBlueFacesInBLVMinimapIDs[i]];
+      pX = uCenterX + ((signed int)(((unsigned int)(fixpoint_mul(uZoom, pIndoor->pVertices[pOutline->uVertex1ID].x)) << 16) - uZoom * pParty->vPosition.x) >> 16);
+      pY = uCenterY - ((signed int)(((unsigned int)(fixpoint_mul(uZoom, pIndoor->pVertices[pOutline->uVertex1ID].y)) << 16) - uZoom * pParty->vPosition.y) >> 16);
+      pZ = uCenterX + ((signed int)(((unsigned int)(fixpoint_mul(uZoom, pIndoor->pVertices[pOutline->uVertex2ID].x)) << 16) - uZoom * pParty->vPosition.x) >> 16);
+      pW = uCenterY - ((signed int)(((unsigned int)(fixpoint_mul(uZoom, pIndoor->pVertices[pOutline->uVertex2ID].y)) << 16) - uZoom * pParty->vPosition.y) >> 16);
+      pRenderer->RasterLine2D(pX, pY, pZ, pW, ui_game_minimap_outline_color);
+    }
+  }
+
+  //draw arrow on the minimap(include. Ritor1)
+  uint arrow_idx;
+  unsigned int rotate = pParty->sRotationY & stru_5C6E00->uDoublePiMask;
+  if ( (signed int)rotate <= 1920 )
+    arrow_idx = 6;
+  if ( (signed int)rotate < 1664 )
+    arrow_idx = 5;
+  if ( (signed int)rotate <= 1408 )
+    arrow_idx = 4;
+  if ( (signed int)rotate < 1152 )
+    arrow_idx = 3;
+  if ( (signed int)rotate <= 896 )
+    arrow_idx = 2;
+  if ( (signed int)rotate < 640 )
+    arrow_idx = 1;
+  if ( (signed int)rotate <= 384 )
+    arrow_idx = 0;
+  if ( (signed int)rotate < 128 || (signed int)rotate > 1920 )
+    arrow_idx = 7;
+  pRenderer->DrawTextureTransparent(uCenterX - 3, uCenterY - 3, pIcons_LOD->GetTexture(pTextureIDs_pMapDirs[arrow_idx]));//стрелка
+
+  //draw objects on the minimap
+  if ( bWizardEyeActive )
+  {
+    if ( uWizardEyeSkillLevel >= 2 )
+    {
+      for ( uint i = 0; i < uNumSpriteObjects; ++i )
+      {
+        if ( !pSpriteObjects[i].uType || !pSpriteObjects[i].uObjectDescID )
+          continue;
+        //if (uWizardEyeSkillLevel == 1
+        pPoint_X = uCenterX + fixpoint_mul((pSpriteObjects[i].vPosition.x - pParty->vPosition.x), uZoom);
+        pPoint_Y = uCenterY - fixpoint_mul((pSpriteObjects[i].vPosition.y - pParty->vPosition.y), uZoom);
+        //if ( pPoint_X >= pRenderer->raster_clip_x && pPoint_X <= pRenderer->raster_clip_z &&
+        //     pPoint_Y >= pRenderer->raster_clip_y && pPoint_Y <= pRenderer->raster_clip_w)
+        {
+          if (pObjectList->pObjects[pSpriteObjects[i].uObjectDescID].uFlags & OBJECT_DESC_UNPICKABLE)
+          {
+            pRenderer->RasterLine2D(pPoint_X, pPoint_Y, pPoint_X, pPoint_Y, ui_game_minimap_projectile_color);
+          }
+          else if ( uZoom > 512 )
+          {
+            pRenderer->RasterLine2D(pPoint_X - 2, pPoint_Y,     pPoint_X - 2, pPoint_Y + 1, ui_game_minimap_treasure_color);
+            pRenderer->RasterLine2D(pPoint_X - 1, pPoint_Y - 1, pPoint_X - 1, pPoint_Y + 1, ui_game_minimap_treasure_color);
+            pRenderer->RasterLine2D(pPoint_X,     pPoint_Y - 2, pPoint_X,     pPoint_Y + 1, ui_game_minimap_treasure_color);
+            pRenderer->RasterLine2D(pPoint_X + 1, pPoint_Y - 1, pPoint_X + 1, pPoint_Y + 1, ui_game_minimap_treasure_color);
+            pRenderer->RasterLine2D(pPoint_X + 2, pPoint_Y,     pPoint_X + 2, pPoint_Y + 1, ui_game_minimap_treasure_color);
+          }
+          else
+          {
+            pRenderer->RasterLine2D(pPoint_X - 1, pPoint_Y - 1, pPoint_X - 1, pPoint_Y, ui_game_minimap_treasure_color);
+            pRenderer->RasterLine2D(pPoint_X,     pPoint_Y - 1, pPoint_X,     pPoint_Y, ui_game_minimap_treasure_color);
+          }
+        }
+      }
+    }
+    for ( uint i = 0; i < uNumActors; ++i )//draw actors(отрисовка монстров и нпс)
+    {
+      if ( pActors[i].uAIState != Removed && pActors[i].uAIState != Disabled
+       && (pActors[i].uAIState == Dead || pActors[i].ActorNearby()) )
+      {
+        pPoint_X = uCenterX + (fixpoint_mul((pActors[i].vPosition.x - pParty->vPosition.x), uZoom));
+        pPoint_Y = uCenterY - (fixpoint_mul((pActors[i].vPosition.y - pParty->vPosition.y), uZoom));
+        //if ( pPoint_X >= pRenderer->raster_clip_x && pPoint_X <= pRenderer->raster_clip_z
+        //  && pPoint_Y >= pRenderer->raster_clip_y && pPoint_Y <= pRenderer->raster_clip_w )
+        {
+          pColor = ui_game_minimap_actor_friendly_color;
+          if ( pActors[i].uAttributes & ACTOR_HOSTILE )
+            pColor = ui_game_minimap_actor_hostile_color;
+          if ( pActors[i].uAIState == Dead)
+            pColor = ui_game_minimap_actor_corpse_color;
+          if ( uZoom > 1024 )
+          {
+            pRenderer->RasterLine2D(pPoint_X - 2, pPoint_Y - 1, pPoint_X - 2, pPoint_Y + 1, pColor);
+            pRenderer->RasterLine2D(pPoint_X - 1, pPoint_Y - 2, pPoint_X - 1, pPoint_Y + 2, pColor);
+            pRenderer->RasterLine2D(pPoint_X,     pPoint_Y - 2, pPoint_X,     pPoint_Y + 2, pColor);
+            pRenderer->RasterLine2D(pPoint_X + 1, pPoint_Y - 2, pPoint_X + 1, pPoint_Y + 2, pColor);
+            pRenderer->RasterLine2D(pPoint_X + 2, pPoint_Y - 1, pPoint_X + 2, pPoint_Y + 1, pColor);
+          }
+          else
+          {
+            pRenderer->RasterLine2D(pPoint_X - 1, pPoint_Y - 1, pPoint_X - 1, pPoint_Y, pColor);
+            pRenderer->RasterLine2D(pPoint_X,     pPoint_Y - 1, pPoint_X,     pPoint_Y, pColor);
+          }
+        }
+      }
+    }
+    for ( uint i = 0; i < (signed int)uNumLevelDecorations; ++i )//draw items(отрисовка предметов)
+    {
+      if ( pLevelDecorations[i].uFlags & 8 )
+      {
+        pPoint_X = uCenterX + (fixpoint_mul((pLevelDecorations[i].vPosition.x - pParty->vPosition.x), uZoom));
+        pPoint_Y = uCenterY - (fixpoint_mul((pLevelDecorations[i].vPosition.y - pParty->vPosition.y), uZoom));
+        //if ( pPoint_X >= pRenderer->raster_clip_x && pPoint_X <= pRenderer->raster_clip_z
+        //  && pPoint_Y >= pRenderer->raster_clip_y && pPoint_Y <= pRenderer->raster_clip_w )
+        {
+          if ( (signed int)uZoom > 512 )
+          {
+            pRenderer->RasterLine2D(pPoint_X - 1, pPoint_Y - 1, pPoint_X - 1, pPoint_Y + 1, ui_game_minimap_decoration_color_1);
+            pRenderer->RasterLine2D(pPoint_X,     pPoint_Y - 1, pPoint_X,     pPoint_Y + 1, ui_game_minimap_decoration_color_1);
+            pRenderer->RasterLine2D(pPoint_X + 1, pPoint_Y - 1, pPoint_X + 1, pPoint_Y + 1, ui_game_minimap_decoration_color_1);
+          }
+          else
+            pRenderer->RasterLine2D(pPoint_X, pPoint_Y, pPoint_X, pPoint_Y, ui_game_minimap_decoration_color_1);
+        }
+      }
+    }
+  }
+  pRenderer->DrawTextureTransparent(468, 0, pIcons_LOD->GetTexture(uTextureID_Minimap_Loop));//draw minimap_loop
+  pRenderer->SetTextureClipRect(541, 0, 567, 480);
+  pRenderer->DrawTextureIndexed(floorf(((double)pParty->sRotationY * 0.1171875) + 0.5f) + 285, 136, pIcons_LOD->GetTexture(uTextureID_Compas));//draw compas
+  pRenderer->ResetTextureClipRect();
+}
+
+//----- (00441498) --------------------------------------------------------
+void  GameUI_DrawTorchlightAndWizardEye()
+{
+  if (pCurrentScreen == SCREEN_GAME
+      || pCurrentScreen == SCREEN_MENU
+      || pCurrentScreen == SCREEN_OPTIONS
+      || pCurrentScreen == SCREEN_REST
+      || pCurrentScreen == SCREEN_SPELL_BOOK
+      || pCurrentScreen == SCREEN_CHEST
+      || pCurrentScreen == SCREEN_SAVEGAME
+      || pCurrentScreen == SCREEN_LOADGAME
+      || pCurrentScreen == SCREEN_CHEST_INVENTORY
+      || pCurrentScreen == SCREEN_BOOKS
+      || pCurrentScreen == SCREEN_BRANCHLESS_NPC_DIALOG )
+  {
+    if (pParty->TorchlightActive())
+    {
+      IconFrame* icon = pIconsFrameTable->GetFrame((signed __int16)pUIAnum_Torchlight->uIconID, pEventTimer->Time());
+      pRenderer->DrawTextureTransparent(pUIAnum_Torchlight->x, pUIAnum_Torchlight->y, pIcons_LOD->GetTexture(icon->uTextureID));
+    }
+    if (pParty->WizardEyeActive())
+    {
+      IconFrame* icon = pIconsFrameTable->GetFrame((signed __int16)pUIAnim_WizardEye->uIconID, pEventTimer->Time());
+      pRenderer->DrawTextureTransparent(pUIAnim_WizardEye->x, pUIAnim_WizardEye->y, pIcons_LOD->GetTexture(icon->uTextureID));
+    }
+  }
+}
+// 4E28F8: using guessed type int pCurrentScreen;
+
+
+//----- (00491F87) --------------------------------------------------------
+void GameUI_DrawHiredNPCs()
+{
+  unsigned int v13; // eax@23
+  char pContainer[20]; // [sp+Ch] [bp-30h]@18
+  signed int uFrameID; // [sp+24h] [bp-18h]@19
+  int v22; // [sp+34h] [bp-8h]@2
+  unsigned __int8 pNPC_limit_ID; // [sp+3Bh] [bp-1h]@2
+
+  if ( bNoNPCHiring != 1 )
+  {
+    pNPC_limit_ID = 0;
+    v22 = 0;
+    if (pParty->pHirelings[0].pName)
+      pTmpBuf[v22++] = 0;
+    if (pParty->pHirelings[1].pName)
+      pTmpBuf[v22++] = 1;
+
+    for (uint i = 0; i < pNPCStats->uNumNewNPCs; ++i)
+    {
+      if (pNPCStats->pNewNPCData[i].uFlags & 128)
+      {
+        if (!pParty->pHirelings[0].pName || strcmp(pNPCStats->pNewNPCData[i].pName, pParty->pHirelings[0].pName))
+        {
+          if (!pParty->pHirelings[1].pName || strcmp(pNPCStats->pNewNPCData[i].pName, pParty->pHirelings[1].pName))
+            pTmpBuf[v22++] = i + 2;
+        }
+      }
+    }
+
+    for ( int i = pParty->hirelingScrollPosition; i < v22 && pNPC_limit_ID < 2; i++ )
+    {
+      if ( (unsigned __int8)pTmpBuf[i] >= 2 )
+      {
+        sprintf(pContainer, "NPC%03d", pNPCStats->pNPCData[(unsigned __int8)pTmpBuf[i] + 499].uPortraitID);
+        pRenderer->DrawTextureIndexed(pHiredNPCsIconsOffsetsX[pNPC_limit_ID], pHiredNPCsIconsOffsetsY[pNPC_limit_ID],
+                      pIcons_LOD->GetTexture(pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE)));
+      }
+      else
+      {
+        sprintf(pContainer, "NPC%03d", pParty->pHirelings[(unsigned __int8)pTmpBuf[i]].uPortraitID);
+        pRenderer->DrawTextureIndexed(pHiredNPCsIconsOffsetsX[pNPC_limit_ID], pHiredNPCsIconsOffsetsY[pNPC_limit_ID],
+                   pIcons_LOD->GetTexture(pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE)));
+        if ( pParty->pHirelings[(unsigned __int8)pTmpBuf[i]].evt_A == 1 )
+        {
+          uFrameID = pParty->pHirelings[(unsigned __int8)pTmpBuf[i]].evt_B;
+          v13 = 0;
+          if (pIconsFrameTable->uNumIcons)
+          {
+            for ( v13 = 0; v13 < pIconsFrameTable->uNumIcons; ++v13 )
+            {
+              if ( !_stricmp("spell96", pIconsFrameTable->pIcons[v13].pAnimationName) )
+                break;
+            }
+          }
+          pRenderer->DrawTextureTransparent(pHiredNPCsIconsOffsetsX[pNPC_limit_ID], pHiredNPCsIconsOffsetsY[pNPC_limit_ID],
+                        &pIcons_LOD->pTextures[pIconsFrameTable->GetFrame(v13, uFrameID)->uTextureID]);
+        }
+      }
+      ++pNPC_limit_ID;
+    }
+  }
+}
+
+//----- (004178FE) --------------------------------------------------------
+unsigned int UI_GetHealthManaAndOtherQualitiesStringColor(signed int current_pos, signed int base_pos)
+{
+  unsigned __int16 R, G, B;
+
+  if ( current_pos <= base_pos )
+  {
+    if ( current_pos == base_pos )//White
+      return 0;
+    if ( 100 * current_pos / base_pos >= 25 )//Yellow( current_pos > 1/4 )
+      R = 255, G = 255, B = 100;
+    else//Red( current_pos < 1/4 )
+      R = 255, G = 0, B = 0;
+  }
+  else//Green
+    R = 0, G = 255, B = 0;
+  return Color16(R, G, B);
+}
+
+//----- (00417939) --------------------------------------------------------
+int GetConditionDrawColor(unsigned int uConditionIdx)
+{
+  switch (uConditionIdx)
+  {
+    case Condition_Zombie:
+    case Condition_Good:
+      return ui_character_condition_normal_color;
+
+    case Condition_Cursed:
+    case Condition_Weak:
+    case Condition_Fear:
+    case Condition_Drunk:
+    case Condition_Insane:
+    case Condition_Poison_Weak:
+    case Condition_Disease_Weak:
+      return ui_character_condition_light_color;
+
+    case Condition_Sleep:
+    case Condition_Poison_Medium:
+    case Condition_Disease_Medium:
+    case Condition_Paralyzed:
+    case Condition_Unconcious:
+      return ui_character_condition_moderate_color;
+
+    case Condition_Poison_Severe:
+    case Condition_Disease_Severe:
+    case Condition_Dead:
+    case Condition_Pertified:
+    case Condition_Eradicated:
+      return ui_character_condition_severe_color;
+  }
+  Error("Invalid condition (%u)", uConditionIdx);
+}
+
+//----- (00495430) --------------------------------------------------------
+const char * GetReputationString(signed int a1)
+{
+	if (a1 >= 25)
+		return pGlobalTXT_LocalizationStrings[379]; // Hated
+	else if (a1 >= 6)
+		return pGlobalTXT_LocalizationStrings[392]; // Unfriendly
+	else if (a1 >= -5)
+		return pGlobalTXT_LocalizationStrings[399]; // Neutral;
+	else if (a1 >= -24)
+		return pGlobalTXT_LocalizationStrings[402]; // Friendly
+	else
+		return pGlobalTXT_LocalizationStrings[434]; // Respected;
+}
+
+//----- (00441A4E) --------------------------------------------------------
+__int16 __fastcall sub_441A4E(int a1)//for blessing
+{
+	__int16 result; // ax@1
+	int v2; // ebx@1
+	//  char *v3; // esi@1
+	//  int v4; // edi@4
+	bool v5; // ecx@4
+	SpriteFrame *pFrame; // eax@6
+	//SpriteFrame *v7; // edi@6
+	int v8; // eax@6
+	//  unsigned __int16 v9; // ax@6
+	RenderBillboardTransform_local0 v10; // [sp+Ch] [bp-5Ch]@1
+	int v11; // [sp+5Ch] [bp-Ch]@6
+	int v12; // [sp+60h] [bp-8h]@1
+	//int v13; // [sp+64h] [bp-4h]@6
+
+	v10.sParentBillboardID = -1;
+	v10.pTarget = pRenderer->pTargetSurface;
+	v10.pTargetZ = pRenderer->pActiveZBuffer;
+	v10.uTargetPitch = pRenderer->GetRenderWidth();
+	result = 0;
+	v2 = a1;
+	v10.uViewportX = 0;
+	v10.uViewportY = 0;
+	v10.uViewportZ = window->GetWidth() - 1;
+	v10.uViewportW = window->GetHeight() - 1;
+	v12 = 0;
+	//v3 = (char *)&pOtherOverlayList->pOverlays[0].field_C;
+	//do
+	for (uint i = 0; i < 50; ++i)
+	{
+		if (pOtherOverlayList->pOverlays[i].field_6 > 0)
+		{
+			result = pOtherOverlayList->pOverlays[i].field_0;
+			if (pOtherOverlayList->pOverlays[i].field_0 >= 300)
+			{
+				//v4 = result;
+				v5 = pOtherOverlayList->pOverlays[i].field_0 == v2 + 320
+					|| pOtherOverlayList->pOverlays[i].field_0 == v2 + 330
+					|| pOtherOverlayList->pOverlays[i].field_0 == v2 + 340
+					|| pOtherOverlayList->pOverlays[i].field_0 == v2 + 350;
+				pOtherOverlayList->pOverlays[i].field_0 = v2 + 310;
+				if (pOtherOverlayList->pOverlays[i].field_0 == v2 + 310 || v5)
+				{
+					if (!pOtherOverlayList->pOverlays[i].field_0)
+					{
+						pFrame = pSpriteFrameTable->GetFrame(pOverlayList->pOverlays[pOtherOverlayList->pOverlays[i].field_2].uSpriteFramesetID,
+							pOtherOverlayList->pOverlays[i].field_4);
+						//v7 = v6;
+						v11 = pOtherOverlayList->pOverlays[i].field_E;
+						//v13 = pFrame->scale;
+						//v13 = fixpoint_mul(v11, pFrame->scale);
+						v10.uScreenSpaceX = pOtherOverlayList->pOverlays[i].field_8;
+						v10.uScreenSpaceY = pOtherOverlayList->pOverlays[i].field_A;
+						v10._screenspace_x_scaler_packedfloat = fixpoint_mul(v11, pFrame->scale);
+						v10._screenspace_y_scaler_packedfloat = fixpoint_mul(v11, pFrame->scale);
+						v10.pPalette = PaletteManager::Get_Dark_or_Red_LUT(pFrame->uPaletteIndex, 0, 1);
+						v8 = pOtherOverlayList->pOverlays[i].field_2;
+						v10.sZValue = 0;
+						v10.uFlags = 0;
+						//v9 = pOverlayList->pOverlays[v8].uOverlayType;
+						if (!pOverlayList->pOverlays[v8].uOverlayType || pOverlayList->pOverlays[v8].uOverlayType == 2)
+							v10.uScreenSpaceY += pSprites_LOD->pSpriteHeaders[pFrame->pHwSpriteIDs[0]].uHeight / 2;
+						result = pSprites_LOD->pSpriteHeaders[pFrame->pHwSpriteIDs[0]]._4AD2D1(&v10, 0);
+						++v12;
+						if (v12 == 5)
+							break;
+					}
+				}
+			}
+		}
+		//v3 += 20;
+	}
+	//while ( (signed int)v3 < (signed int)&pOverlayList->pOverlays );
+	return result;
+}