view mm7_2.cpp @ 1205:8c02e6f74b29

arrays to std::arrays phase 2 - mm7_data.h converted
author Grumpy7
date Sun, 09 Jun 2013 00:30:48 +0200
parents 1eed3e0ab666
children fd3bea473c0c 0d6c7ff3cddd
line wrap: on
line source

#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif

#include <io.h>
#include <direct.h>
#include <assert.h>
#include <windows.h>


#include "VideoPlayer.h"
#include "Sprites.h"
#include "BSPModel.h"
#include "OutdoorCamera.h"

#include "LightmapBuilder.h"
#include "DecalBuilder.h"
#include "ParticleEngine.h"
#include "Mouse.h"
#include "Keyboard.h"
#include "CShow.h"
#include "GammaControl.h"
#include "stru6.h"

#include "Vis.h"
#include "MapInfo.h"
#include "Game.h"
#include "GUIWindow.h"
#include "GUIFont.h"
#include "Party.h"
#include "AudioPlayer.h"
#include "Outdoor.h"
#include "IndoorCamera.h"
#include "Overlays.h"
#include "Arcomage.h"
#include "LOD.h"
#include "Actor.h"
#include "Allocator.h"
#include "Events.h"
#include "Viewport.h"
#include "FrameTableInc.h"
#include "Math.h"
#include "SpriteObject.h"
#include "ObjectList.h"
#include "Chest.h"
#include "PaletteManager.h"
#include "DecorationList.h"
#include "SaveLoad.h"
#include "stru123.h"
#include "stru176.h"
#include "Time.h"
#include "IconFrameTable.h"
#include "GUIProgressBar.h"
#include "Bink_Smacker.h"
#include "PlayerFrameTable.h"
#include "TurnEngine.h"
#include "FactionTable.h"
#include "StorylineTextTable.h"
#include "Random.h"
#include "CastSpellInfo.h"
#include "stru298.h"
#include "Events2D.h"
#include "Log.h"
#include "UIHouses.h"
#include "texts.h"
#include "mm7_data.h"
#include "MM7.h"

//----- (004BB756) --------------------------------------------------------
signed int __fastcall sub_4BB756(signed int a1)
{
  unsigned int v1; // esi@8
  unsigned int v3; // ecx@10
  Player *v4; // esi@15
  int v5; // ebx@16
  int v6; // ST38_4@16
  Player *v7; // esi@18
  int v8; // ebx@19
  int v9; // ST30_4@19
  int v10; // ST44_4@19
  int v11; // ST48_4@19
  int v12; // ST4C_4@19
  int v13; // ST50_4@19
  int v14; // ST3C_4@19
  int v15; // ST40_4@19
  int v16; // ST34_4@19
  int v17; // ST38_4@19
  Player *v18; // esi@21
  int v19; // eax@26
  int v20; // eax@39
  SoundID v21; // [sp-20h] [bp-54h]@25
  signed int v22; // [sp-1Ch] [bp-50h]@25
  unsigned int v23; // [sp-18h] [bp-4Ch]@25
  signed int v24; // [sp-14h] [bp-48h]@25
  signed int v25; // [sp-10h] [bp-44h]@25
  int v26; // [sp-10h] [bp-44h]@32
  int v27; // [sp-Ch] [bp-40h]@25
  unsigned int v28; // [sp-Ch] [bp-40h]@32
  unsigned int v29; // [sp-8h] [bp-3Ch]@25
  __int16 v30; // [sp-8h] [bp-3Ch]@32
  int v31; // [sp-4h] [bp-38h]@25
  int v32; // [sp-4h] [bp-38h]@32

  if ( a1 > 39 )
  {
    if ( a1 != 40 )
    {
      if ( a1 == 41 )
      {
        pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 0, 0);
        /*if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
        {
          pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = UIMSG_Escape;
          pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 0;
          *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
          ++pMessageQueue_50CBD0->uNumMessages;
        }*/
        dword_50C9DC = 195;
        ptr_50C9E0 = GetNPCData(sDialogue_SpeakingActorNPC_ID);
        return 0;
      }
      if ( a1 == 42 )
      {
        v32 = 0;
        v30 = 0;
        v28 = 133;
        v26 = 46;
      }
      else
      {
        if ( a1 == 43 )
        {
          v32 = 0;
          v30 = 0;
          v28 = 133;
          v26 = 51;
        }
        else
        {
          if ( a1 != 52 )
            return 0;
          v32 = 0;
          v30 = 0;
          v28 = 133;
          v26 = 86;
        }
      }
      _42777D_CastSpell_UseWand_ShootArrow(v26, 0, v28, v30, v32);
      return 0;
    }
    v20 = pOtherOverlayList->_4418B1(10005, 201, 0, 65536);
    pParty->pPartyBuffs[PARTY_BUFF_WATER_WALK].Apply(pParty->uTimePlayed + 46080, 3u, 0, v20, 0);
    pParty->pPartyBuffs[PARTY_BUFF_WATER_WALK].uFlags |= 1u;
    v31 = 0;
    v29 = 0;
    v27 = 0;
    v25 = 0;
    v24 = -1;
    v23 = 0;
    v22 = 0;
    v21 = (SoundID)12040;
LABEL_40:
    pAudioPlayer->PlaySound(v21, v22, v23, v24, v25, v27, v29, v31);
    return 0;
  }
  if ( a1 == 39 )
  {
    if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
    {
      ShowStatusBarString(pGlobalTXT_LocalizationStrings[494], 2u);
      v31 = 0;
      v29 = 0;
      v27 = 0;
      v25 = 0;
      v24 = -1;
      v23 = 0;
      v22 = 0;
      v21 = (SoundID)203;
    }
    else
    {
      v19 = pOtherOverlayList->_4418B1(10008, 203, 0, 65536);
      pParty->pPartyBuffs[PARTY_BUFF_FLY].Apply(pParty->uTimePlayed + 30720, 3u, 1u, v19, 0);
      pParty->pPartyBuffs[PARTY_BUFF_FLY].uFlags |= 1u;
      v31 = 0;
      v29 = 0;
      v27 = 0;
      v25 = 0;
      v24 = -1;
      v23 = 0;
      v22 = 0;
      v21 = (SoundID)11090;
    }
    pAudioPlayer->PlaySound(v21, v22, v23, v24, v25, v27, v29, v31);
    return 0;
  }
  if ( a1 == 10 )
  {
    v18 = pParty->pPlayers;
    do
    {
      v18->sHealth = v18->GetMaxHealth();
      ++v18;
    }
    while ( (signed int)v18 < (signed int)pParty->pHirelings );
    return 0;
  }
  if ( a1 == 11 )
  {
    v7 = pParty->pPlayers;//(char *)&pParty->pPlayers[0].pConditions[15];
    do
    {
      /*v8 = *((int *)v7 - 2);
      v9 = *((int *)v7 - 1);
      v10 = *(int *)v7;
      v11 = *((int *)v7 + 1);
      v12 = *((int *)v7 + 2);
      v13 = *((int *)v7 + 3);
      v14 = *((int *)v7 + 8);
      v15 = *((int *)v7 + 9);
      v16 = *((int *)v7 + 4);
      v17 = *((int *)v7 + 5);*/
	  v8 = LODWORD(v7->pConditions[14]);
	  v9 = HIDWORD(v7->pConditions[14]);
	  v10 = LODWORD(v7->pConditions[15]);
      v11 = HIDWORD(v7->pConditions[15]);
      v12 = LODWORD(v7->pConditions[16]);
      v13 = HIDWORD(v7->pConditions[16]);
      v14 = LODWORD(v7->pConditions[19]);
      v15 = HIDWORD(v7->pConditions[19]);
      v16 = LODWORD(v7->pConditions[17]);
      v17 = HIDWORD(v7->pConditions[17]);
      memset(v7, 0, 0xA0u);
      LODWORD(v7->pConditions[16]) = v12;
      HIDWORD(v7->pConditions[16]) = v13;
      LODWORD(v7->pConditions[15]) = v10;
      HIDWORD(v7->pConditions[15]) = v11;
      HIDWORD(v7->pConditions[14]) = v9;
      LODWORD(v7->pConditions[19]) = v14;
      HIDWORD(v7->pConditions[19]) = v15;
      LODWORD(v7->pConditions[17]) = v16;
      LODWORD(v7->pConditions[14]) = v8;
      HIDWORD(v7->pConditions[17]) = v17;
	  v7->sHealth = v7->GetMaxHealth();
      ++v7;
    }
    while ( v7 <= pPlayers[3] );
    return 0;
  }
  if ( a1 == 12 )
  {
	  v4 = pParty->pPlayers;//(char *)&pParty->pPlayers[0].pActiveSkills[8];
    do
    {
	  v5 = LODWORD(v4->pConditions[19]);//*((int *)v4 - 32);
      v6 = HIDWORD(v4->pConditions[19]);//*((int *)v4 - 31);
	  memset(v4->pConditions, 0, 0xA0u);
	  v4->pActiveSkills[8] = v5;
      v4->pActiveSkills[10] = v6;
	  v4->sHealth = v4->GetMaxHealth();
      ++v4;
    }
    while ( v4 <= pPlayers[3] );
    return 0;
  }
  if ( a1 == 33 )
  {
    v1 = 14;
    if ( pParty->uNumFoodRations >= 0xE )
      return 1;
    v3 = 1;
LABEL_13:
    Party::GiveFood(v3);
    if ( pParty->uNumFoodRations > v1 )
      pParty->uNumFoodRations = v1;
    return 0;
  }
  if ( a1 == 34 )
  {
    v1 = 14;
    if ( pParty->uNumFoodRations >= 0xE )
      return 1;
    v3 = 2;
    goto LABEL_13;
  }
  return 0;
}
// 50C9DC: using guessed type int dword_50C9DC;

//----- (004BBA85) --------------------------------------------------------
const char *sub_4BBA85_bounties()
{
  int v0; // edi@1
  signed __int64 v1; // qax@2
  int i; // eax@2
  int v3; // edx@3
  int v4; // edi@14
  __int16 v5; // ax@14
  char v6; // zf@14
  Player *v7; // ebx@16
  const char *result; // eax@19

  uDialogueType = 83;
  pDialogueWindow->Release();
  pDialogueWindow = GUIWindow::Create(0, 0, 640, 350, WINDOW_MainMenu, 0, 0);
  pBtn_ExitCancel = pDialogueWindow->CreateButton(471u, 445u, 169u, 35u, 1, 0, UIMSG_Escape, 0, 0, pGlobalTXT_LocalizationStrings[34],// "Cancel"
                 pIcons_LOD->GetTexture(uExitCancelTextureId), 0);
  pDialogueWindow->CreateButton(0, 0, 0, 0, 1, 0, UIMSG_BuyInShop_Identify_Repair, 0, 0, "", 0);
  pDialogueWindow->CreateButton(480u, 160u, 140u, 30u, 1, 0, UIMSG_0, 0x53u, 0, "", 0);
  pDialogueWindow->_41D08F_set_keyboard_control_group(1, 1, 0, 2);
  dialog_menu_id = HOUSE_DIALOGUE_OTHER;
  v0 = (int)((char *)window_SpeakInHouse->ptr_1C - 102);
  if ( (signed __int64)__PAIR__(pParty->field_3C.field_0[2 * v0 + 1], pParty->field_3C.field_0[2 * v0]) < (signed __int64)pParty->uTimePlayed )
  {
    pParty->field_75A[v0] = 0;
    __debugbreak(); // starting year-related constant here;
    v1 = (signed __int64)((double)(0x12750000 * (pParty->uCurrentMonth + 12i64 * pParty->uCurrentYear - 14015))
                        * 0.033333335);
    pParty->field_3C.field_0[2 * v0] = v1;
    pParty->field_3C.field_0[2 * v0 + 1] = HIDWORD(v1);
    for ( i = rand(); ; i = rand() )
    {
      v3 = i % 258 + 1;
      pParty->field_750[v0] = v3;
      if ( (unsigned __int16)v3 < 0x73u || (unsigned __int16)v3 > 0x84u )
      {
        if ( ((unsigned __int16)v3 < 0xEBu || (unsigned __int16)v3 > 0xFCu)
          && ((unsigned __int16)v3 < 0x85u || (unsigned __int16)v3 > 0x96u)
          && ((unsigned __int16)v3 < 0x97u || (unsigned __int16)v3 > 0xBAu)
          && ((unsigned __int16)v3 < 0xC4u || (unsigned __int16)v3 > 0xC6u) )
          break;
      }
    }
  }
  v4 = v0;
  v5 = pParty->field_750[v4];
  v6 = pParty->field_75A[v4] == 0;
  word_F8B1A0 = pParty->field_750[v4];
  if ( v6 )
  {
    v6 = v5 == 0;
    result = pNPCTopics[351].pText;
    if ( v6 )
      result = pNPCTopics[353].pText;
  }
  else
  {
    if ( v5 )
    {
      party_finds_gold(100 * pMonsterStats->pInfos[(unsigned __int16)v5].uLevel, 0);
      v7 = pParty->pPlayers;
      do
      {
        v7->SetVariable(VAR_Award, 86);
        ++v7;
      }
      while ( (signed int)v7 < (signed int)pParty->pHirelings );
      pParty->uNumBountiesCollected += 100 * pMonsterStats->pInfos[pParty->field_750[v4]].uLevel;
      pParty->field_750[v4] = 0;
      pParty->field_75A[v4] = 0;
    }
    result = pNPCTopics[352].pText;
  }
  dword_F8B1A4 = (char *)result;
  return result;
}

//----- (004BBCDD) --------------------------------------------------------
void __cdecl sub_4BBCDD()
{
  signed int v0; // ebp@3
  Actor *v1; // eax@4
  __int16 v2; // cx@5
  int v3; // esi@8
  Player *v4; // esi@14
  GUIButton *v5; // eax@18
  GUIButton *v6; // esi@19
  size_t v7; // [sp+10h] [bp-4h]@4

  if ( pParty->field_7B5_in_arena_quest )
  {
    if ( pParty->field_7B5_in_arena_quest == -1 )
    {
      uDialogueType = 92;
    }
    else
    {
      v0 = 0;
      if ( (signed int)uNumActors > 0 )
	  {
      v1 = pActors.data();//[0].uAIState;
		  v7 = uNumActors;
		  do
		  {
			v2 = v1->uAIState;
			if ( v1->uAIState == Dead || v2 == Removed || v2 == Disabled || (v3 = v1->uSummonerID) != 0 && PID_TYPE(v3) == OBJECT_Player)
			  ++v0;
			++v1;
			--v7;
		  }
		  while ( v7 );
	  }
      if ( v0 >= (signed int)uNumActors || (signed int)uNumActors <= 0)
      {
        uDialogueType = 91;
        v4 = pParty->pPlayers;
        ++*((char *)&pParty->field_75A[3] + (unsigned __int8)pParty->field_7B5_in_arena_quest + 1);
        do
        {
          v4->SetVariable(VAR_Award, (unsigned __int8)pParty->field_7B5_in_arena_quest + 3);
          ++v4;
        }
        while ( (signed int)v4 < (signed int)pParty->pHirelings );
        party_finds_gold(gold_transaction_amount, 0);
        pAudioPlayer->PlaySound((SoundID)14060, 0, 0, -1, 0, 0, 0, 0);
        pParty->field_7B5_in_arena_quest = -1;
      }
      else
      {
        uDialogueType = 90;
        pParty->vPosition.x = 3849;
        pParty->vPosition.y = 5770;
        pParty->vPosition.z = 1;
        pParty->uFallStartY = 1;
        pParty->sRotationY = 512;
        pParty->sRotationX = 0;
        pParty->uFallSpeed = 0;
        pAudioPlayer->PlaySound((SoundID)14060, 0, 0, -1, 0, 0, 0, 0);
      }
    }
  }
  else
  {
    uDialogueType = 89;
    v5 = pDialogueWindow->pControlsHead;
    if ( v5 )
    {
      do
      {
        v6 = v5->pNext;
        pAllocator->FreeChunk(v5);
        v5 = v6;
      }
      while ( v6 );
    }
    pDialogueWindow->pControlsHead = 0;
    pDialogueWindow->pControlsTail = 0;
    pDialogueWindow->uNumControls = 0;
    pBtn_ExitCancel = pDialogueWindow->CreateButton(0x1D7u, 0x1BDu, 0xA9u, 0x23u, 1, 0, UIMSG_Escape, 0, 0, pGlobalTXT_LocalizationStrings[79],
                   pIcons_LOD->GetTexture(uExitCancelTextureId), 0);
    pDialogueWindow->CreateButton(0x1E0u, 0xA0u, 0x8Cu, 0x1Eu, 1, 0, UIMSG_SelectNPCDialogueOption, 0x55u, 0, "", 0);
    pDialogueWindow->CreateButton(0x1E0u, 0xBEu, 0x8Cu, 0x1Eu, 1, 0, UIMSG_SelectNPCDialogueOption, 0x56u, 0, "", 0);
    pDialogueWindow->CreateButton(0x1E0u, 0xDCu, 0x8Cu, 0x1Eu, 1, 0, UIMSG_SelectNPCDialogueOption, 0x57u, 0, "", 0);
    pDialogueWindow->CreateButton(0x1E0u, 0xFAu, 0x8Cu, 0x1Eu, 1, 0, UIMSG_SelectNPCDialogueOption, 0x58u, 0, "", 0);
    pDialogueWindow->_41D08F_set_keyboard_control_group(4, 1, 0, 1);
  }
}
// F8B1B4: using guessed type int dword_F8B1B4;

//----- (004BBF61) --------------------------------------------------------
void __fastcall _4BBF61_summon_actor(int a1, __int16 x, int y, int z)
{
  size_t v4; // esi@1
  int monster_id; // edi@1
  __int16 v6; // ax@4
  Actor *v7; // esi@5
  int v8; // eax@5
  MonsterInfo *v9; // edi@5
  MonsterDesc *v10; // ebx@5
  unsigned __int16 *v11; // ebx@5
  int v12; // ebx@7
  int v13; // eax@8
  __int16 x_; // [sp+8h] [bp-Ch]@1
  __int16 v15; // [sp+Ch] [bp-8h]@1
  __int16 v16; // [sp+10h] [bp-4h]@3
  signed int ya; // [sp+1Ch] [bp+8h]@5

  v4 = uNumActors;
  monster_id = a1;
  x_ = x;
  v15 = a1;
  if ( (signed int)uNumActors < 500
    && ((signed int)pAllocator->uBigBufferSizeAligned >> 10) - ((signed int)pAllocator->uNextFreeOffsetInBigBuffer >> 10) >= 2000 )
  {
    v16 = 0;
    if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
    {
      v6 = pIndoor->GetSector(x, y, z);
      v4 = uNumActors;
      v16 = v6;
    }
    v7 = &pActors[v4];
    v7->Reset();
    v8 = monster_id;
    v9 = &pMonsterStats->pInfos[monster_id];
    v10 = &pMonsterList->pMonsters[v8 - 1];
    strcpy(v7->pActorName, v9->pName);
    v7->sCurrentHP = LOWORD(v9->uHP);
    memcpy(&v7->pMonsterInfo, v9, 0x58u);
    v7->word_000086_some_monster_id = v15;
    v7->uActorRadius = v10->uMonsterRadius;
    v7->uActorHeight = v10->uMonsterHeight;
    v7->uMovementSpeed = v10->uMovementSpeed;
    v7->vInitialPosition.x = x_;
    v7->vPosition.x = x_;
    BYTE2(v7->uAttributes) |= 8u;
    v7->pMonsterInfo.uTreasureType = 0;
    v7->pMonsterInfo.uTreasureLevel = 0;
    v7->pMonsterInfo.uTreasureDiceSides = 0;
    v7->pMonsterInfo.uTreasureDiceRolls = 0;
    v7->pMonsterInfo.uTreasureDropChance = 0;
    v7->vInitialPosition.y = y;
    v7->vPosition.y = y;
    v7->vInitialPosition.z = z;
    v7->vPosition.z = z;
    v7->uTetherDistance = 256;
    v7->uSectorID = v16;
    v7->uGroup = 1;
    v7->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Long;
    v7->PrepareSprites(0);
    v11 = v10->pSoundSampleIDs;
    ya = 4;
    do
    {
      pSoundList->LoadSound((signed __int16)*v11, 0);
      ++v11;
      --ya;
    }
    while ( ya );
    v12 = 0;
    do
      LOWORD(v13) = pSoundList->LoadSound(v12++ + word_4EE088_sound_ids[v9->uSpell1ID], 1u);
    while ( v13 );
    ++uNumActors;
  }
}
// 4EE088: using guessed type __int16 word_4EE088_sound_ids[];

//----- (004BC109) --------------------------------------------------------
void __cdecl ArenaFight()
{
  int v0; // edi@1
  char *v1; // eax@7
  Player *v2; // edi@9
  int v3; // eax@10
  signed int v4; // esi@10
  signed __int64 v5; // qax@18
  signed int v6; // ebx@34
  char *v7; // edi@34
  int v8; // eax@37
  int v9; // esi@43
  int v10; // eax@44
  unsigned __int8 v11; // sf@44
  unsigned __int8 v12; // of@44
  signed int v13; // eax@49
  int v14; // esi@49
  int v15; // edx@50
  int v16; // eax@51
  signed int v17; // ecx@51
  int v18; // edx@53
  int i; // edi@55
  int monster_y; // ST18_4@56
  int v21; // eax@56
  signed int v22; // [sp-4h] [bp-144h]@51
  __int16 v23[100]; // [sp+Ch] [bp-134h]@39
  GUIWindow window; // [sp+D4h] [bp-6Ch]@1
  __int16 monster_ids[6]; // [sp+128h] [bp-18h]@56
  int v26; // [sp+134h] [bp-Ch]@1
  int v27; // [sp+138h] [bp-8h]@23
  int num_monsters; // [sp+13Ch] [bp-4h]@17

  v26 = 0;
  pParty->field_7B5_in_arena_quest = uDialogueType;
  memcpy(&window, pDialogueWindow, sizeof(window));
  window.uFrameWidth = game_viewport_width;
  window.uFrameZ = 452;
  v0 = pFontArrus->CalcTextHeight(pGlobalTXT_LocalizationStrings[575], &window, 13, 0) + 7;
  pRenderer->BeginSceneD3D();

  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
    pIndoor->Draw();
  else if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
      pOutdoor->Draw();

  pRenderer->DrawBillboards_And_MaybeRenderSpecialEffects_And_EndScene();
  pRenderer->BeginScene();
  if ( pRenderer->pRenderD3D )
    pRenderer->FillRectFast(
      pViewport->uViewportTL_X,
      pViewport->uViewportTL_Y,
      pViewport->uViewportBR_X - pViewport->uViewportTL_X,
      pViewport->uViewportBR_Y - pViewport->uViewportTL_Y + 1,
      pRenderer->uTargetGMask | pRenderer->uTargetBMask);

  auto pTex = pIcons_LOD->GetTexture(uTextureID_Leather);
  pRenderer->_4A6A68(8, 352 - v0, pTex, pTex->uTextureHeight - v0);

  pRenderer->DrawTextureIndexed(8u, 347 - v0, pTexture_591428);
  v1 = FitTextInAWindow(pGlobalTXT_LocalizationStrings[575], pFontArrus, &window, 0xDu, 0);
  pDialogueWindow->DrawText(pFontArrus, 13, 354 - v0, 0, v1, 0, 0, 0);
  pRenderer->EndScene();
  pRenderer->Present();
  pParty->vPosition.x = 3849;
  pParty->vPosition.y = 5770;
  pParty->vPosition.z = 1;
  pParty->uFallStartY = 1;
  pParty->sRotationY = 512;
  pParty->sRotationX = 0;
  pParty->uFallSpeed = 0;
  /*if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
  {
    pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = UIMSG_Escape;
    pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 1;
    *(&pMessageQueue_50CBD0->uNumMessages + 3 * pMessageQueue_50CBD0->uNumMessages + 3) = 0;
    ++pMessageQueue_50CBD0->uNumMessages;
  }*/
  pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 1, 0);
  v2 = pParty->pPlayers;
  do
  {
    v3 = v2->GetActualLevel();
    v4 = v26;
    if ( v3 > v26 )
    {
      v26 = v2->GetActualLevel();
      v4 = v26;
    }
    ++v2;
  }
  while ( (signed int)v2 < (signed int)pParty->pHirelings );
  if ( uDialogueType == 85 )
  {
    num_monsters = v4;
    goto LABEL_22;
  }
  if ( uDialogueType == 86 )
  {
    v5 = (signed __int64)((double)v26 * 1.5);
    goto LABEL_20;
  }
  if ( uDialogueType == 87 )
  {
    LODWORD(v5) = 2 * v4;
LABEL_20:
    num_monsters = v5;
LABEL_22:
    v4 /= 2;
    goto LABEL_24;
  }
  if ( uDialogueType == 88 )
    num_monsters = 2 * v4;
  else
    v4 = v27;
LABEL_24:
  if ( v4 < 1 )
    v4 = 1;
  if ( v4 > 100 )
    v4 = 100;
  if ( num_monsters > 100 )
    num_monsters = 100;
  if ( v4 < 2 )
    v4 = 2;
  if ( num_monsters < 2 )
    num_monsters = 2;
  v6 = 0;
  v27 = 1;
  v7 = (char *)&pMonsterStats->pInfos[1].uLevel;
  do
  {
    if ( v7[8] != 1 )
    {
      if ( !MonsterStats::BelongsToSupertype(*((short *)v7 + 22), MONSTER_SUPERTYPE_8) )
      {
        v8 = (unsigned __int8)*v7;
        if ( v8 >= v4 )
        {
          if ( v8 <= num_monsters )
            v23[v6++] = v27;
        }
      }
    }
    ++v27;
    v7 += 88;
  }
  while ( (signed int)v7 <= (signed int)&pMonsterStats->pInfos[258].uLevel );
  num_monsters = 6;
  if ( v6 < 6 )
    num_monsters = v6;
  v9 = 0;
  if ( num_monsters > 0 )
  {
    do
    {
      v10 = rand();
      ++v9;
      v12 = __OFSUB__(v9, num_monsters);
      v11 = v9 - num_monsters < 0;
      *((short *)&window.pControlsTail + v9 + 1) = v23[v10 % v6];
    }
    while ( v11 ^ v12 );
  }
  if ( uDialogueType == 85 )
  {
    v16 = rand();
    v17 = 3;
    v22 = 50;
    goto LABEL_53;
  }
  if ( uDialogueType == 86 )
  {
    v16 = rand();
    v17 = 7;
    v22 = 100;
LABEL_53:
    v18 = v16 % v17;
    v13 = v22;
    v14 = v18 + 6;
    goto LABEL_55;
  }
  if ( uDialogueType == 87 )
  {
    v15 = rand() % 11;
    v13 = 200;
    v14 = v15 + 10;
  }
  else
  {
    if ( uDialogueType == 88 )
    {
      v13 = 500;
      v14 = 20;
    }
    else
    {
      v14 = v27;
      v13 = gold_transaction_amount;
    }
  }
LABEL_55:
  i = 0;
  for ( gold_transaction_amount = v26 * v13; i < v14; ++i )
  {
    monster_y = pMonsterArenaPlacements[i].y;
    v21 = rand();
    _4BBF61_summon_actor((unsigned __int16)monster_ids[v21 % num_monsters], pMonsterArenaPlacements[i].x, monster_y, 1);
  }
  pAudioPlayer->PlaySound((SoundID)14060, 0, 0, -1, 0, 0, 0, 0);
}

//----- (004BC8D5) --------------------------------------------------------
void SpellBookGenerator()//for GuildDialogs
{
  int pItemNum; // esi@1
  int v4; // esi@7

  for( int i = 0; i < 12; ++i )
  {
    if ( p2DEvents[window_SpeakInHouse->par1C - 1].uType >= 5 )
    {
      if ( p2DEvents[window_SpeakInHouse->par1C - 1].uType <= 13 )
        pItemNum = rand() % word_4F0F30[(signed int)window_SpeakInHouse->par1C - 139] + 11 * p2DEvents[(unsigned int)window_SpeakInHouse->ptr_1C - 1].uType + 345;
      else
      {
        if ( p2DEvents[window_SpeakInHouse->par1C - 1].uType == 14 )
          v4 = rand() % 4;
        else if ( p2DEvents[window_SpeakInHouse->par1C - 1].uType == 15 )
          v4 = rand() % 3 + 4;
        else if ( p2DEvents[window_SpeakInHouse->par1C - 1].uType == 16 )
          v4 = rand() % 2 + 7;
        if( p2DEvents[window_SpeakInHouse->par1C - 1].uType <= 16 )
          pItemNum = rand() % word_4F0F30[(signed int)window_SpeakInHouse->par1C - 139] + 11 * v4 + 400;
      }
    }
    if ( pItemNum == 487 )
    {
      if ( !(unsigned __int16)_449B57_test_bit(pParty->_quest_bits, 239) )
        pItemNum = 486;
    }
    ItemGen * item_spellbook = &pParty->SpellBooksInGuilds[window_SpeakInHouse->par1C-139][i];
    item_spellbook->Reset();
    pParty->SpellBooksInGuilds[window_SpeakInHouse->par1C-139][i].uItemID = pItemNum;
    pParty->SpellBooksInGuilds[window_SpeakInHouse->par1C-139][i].Identified();
    ItemsInShopTexture[i] = pIcons_LOD->LoadTexturePtr(pItemsTable->pItems[pItemNum].pIconName, TEXTURE_16BIT_PALETTE);
  }
  return;
}

//----- (004BCA33) --------------------------------------------------------
void UI_CreateEndConversationButton()
{
  pDialogueWindow->Release();
  pDialogueWindow = GUIWindow::Create(0, 0, 640, 345, WINDOW_MainMenu, 0, 0);
  pBtn_ExitCancel = pDialogueWindow->CreateButton( 471, 445,  169, 35, 1, 0, UIMSG_Escape,  0,  0,
                 pGlobalTXT_LocalizationStrings[74],  //"End Conversation"
                 pIcons_LOD->GetTexture(uExitCancelTextureId), 0);
  pDialogueWindow->CreateButton(8, 8, 450, 320, 1, 0, UIMSG_BuyInShop_Identify_Repair, 0, 0, "", 0);
}

//----- (004BD8B5) --------------------------------------------------------
signed int __cdecl sub_4BD8B5()
{
  int v0; // eax@4
  int v1; // eax@29
  unsigned int v2; // esi@30
  //const char *v3; // ebx@31

  if ( pMessageQueue_50CBD0->uNumMessages )
    pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
  pKeyActionMap->SetWindowInputStatus(3);
  pKeyActionMap->ResetKeys();
  activeLevelDecoration = NULL;
  current_npc_text = 0;
  if ( pDialogueNPCCount )
  {
    v0 = dialog_menu_id;
    if ( dialog_menu_id != HOUSE_DIALOGUE_SHOP_BUY_STANDARD
      && dialog_menu_id != HOUSE_DIALOGUE_SHOP_SELL
      && dialog_menu_id != HOUSE_DIALOGUE_97
      && dialog_menu_id != HOUSE_DIALOGUE_SHOP_REPAIR
      && dialog_menu_id != HOUSE_DIALOGUE_SHOP_IDENTIFY
      && ShopTexture )
    {
      ShopTexture->Release();
      v0 = dialog_menu_id;
      ShopTexture = 0;
    }
    if ( v0 && v0 != 1 )
    {
      if ( v0 == -1 )
      {
        _4B4224_UpdateNPCTopics((int)((char *)pDialogueNPCCount - 1));
//LABEL_33:
        pVideoPlayer->_4BF5B2();
        return 1;
      }
      if ( v0 != 94 && v0 != 96 && v0 != 101 )
      {
        if ( v0 == 3 || v0 == 5 || v0 == 4 )
        {
          UI_CreateEndConversationButton();
          dialog_menu_id = HOUSE_DIALOGUE_SHOP_DISPLAY_EQUIPMENT;
          sub_4B3AD4(in_current_building_type);
        }
        else
        {
          if ( v0 != 102 && v0 != 103 && v0 != 104 )
          {
            pVideoPlayer->_4BF5B2();
//LABEL_28:
            dialog_menu_id = HOUSE_DIALOGUE_MAIN;
            sub_4B3B42(in_current_building_type);
            return 1;
          }
          pVideoPlayer->_4BF5B2();
          UI_CreateEndConversationButton();
          dialog_menu_id = HOUSE_DIALOGUE_TAVERN_ARCOMAGE_MAIN;
          sub_4B3A72(in_current_building_type);
        }
        return 1;
      }
      pVideoPlayer->_4BF5B2();
      UI_CreateEndConversationButton();
	  dialog_menu_id = HOUSE_DIALOGUE_MAIN;
	  sub_4B3B42(in_current_building_type);
	  return 1;
    }
    pDialogueNPCCount = 0;
    pDialogueWindow->Release();
    dialog_menu_id = HOUSE_DIALOGUE_NULL;
    pDialogueWindow = 0;
    pIcons_LOD->SyncLoadedFilesCount();
    v1 = uNumDialogueNPCPortraits;
    if ( uNumDialogueNPCPortraits != 1 )
    {
      v2 = 0;
      pBtn_ExitCancel = window_SpeakInHouse->pControlsHead;
      if ( uNumDialogueNPCPortraits > 0 )
      {
        //v3 = byte_591180;
        do
        {
          HouseNPCData[v2 + 7] = (NPCData *)window_SpeakInHouse->CreateButton(pNPCPortraits_x[v1 - 1][v2], pNPCPortraits_y[v1 - 1][v2],
                                              0x3Fu, 0x49u, 1, 0, UIMSG_ClickHouseNPCPortrait, v2, 0, byte_591180[v2].data(), 0, 0, 0);
          v1 = uNumDialogueNPCPortraits;
          ++v2;
          //v3 += 100;
        }
        while ( (signed int)v2 < uNumDialogueNPCPortraits );
      }
      pVideoPlayer->_4BF5B2();
      return 1;
    }
  }
  return 0;
}

//----- (004BDB56) --------------------------------------------------------
void __cdecl UIShop_Buy_Identify_Repair()
{
  int v8; // eax@15
  unsigned int pItemID; // esi@20
  ItemGen *item; // esi@21
  unsigned int v15; // eax@33
  POINT *pCursorPos; // esi@37
  int v18; // ecx@37
  float pPriceMultiplier; // ST1C_4@38
  int taken_item; // eax@40
  ItemGen *bought_item; // esi@51
  int party_reputation; // eax@55
  int v39; // eax@63
  int v42; // esi@74
  signed int v43; // ebx@74
  unsigned __int16 *pSkill; // esi@77
  int v55; // [sp+0h] [bp-B4h]@26
  POINT cursor; // [sp+40h] [bp-74h]@37
  int a6; // [sp+98h] [bp-1Ch]@57
  int a3; // [sp+9Ch] [bp-18h]@53
  unsigned int uNumSeconds; // [sp+A4h] [bp-10h]@53
  unsigned int v79; // [sp+A8h] [bp-Ch]@9
  int uPriceItemService; // [sp+ACh] [bp-8h]@12

  if ( pCurrentScreen == SCREEN_E )
  {
    OnInventoryLeftClick();
    return;
  }
  if ( !sub_4B1784_check_if_player_concious__draw_warning_else_mess_with_dlg_win() )
  {
    pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
    return;
  }

  switch(dialog_menu_id)
  {
    case HOUSE_DIALOGUE_SHOP_DISPLAY_EQUIPMENT:
    {
      pWindowList_at_506F50_minus1_indexing_buttons____and_an_int_[0] = 103;
      OnInventoryLeftClick();
      break;
    }
    case HOUSE_DIALOGUE_GUILD_BUY_BOOKS:
    {
      pCursorPos = pMouse->GetCursorPos(&cursor);
      v18 = pRenderer->pActiveZBuffer[pCursorPos->x + pSRZBufferLineOffsets[pMouse->GetCursorPos(&cursor)->y]] & 0xFFFF;
      if ( !v18 )
        return;
      bought_item = (ItemGen *)(&pParty->pPlayers[1].uExpressionTimeLength + 18 * (v18 + 12 * (int)window_SpeakInHouse->ptr_1C));
      pPriceMultiplier = p2DEvents[(signed int)window_SpeakInHouse->ptr_1C - 1].fPriceMultiplier;
      uPriceItemService = pPlayers[uActiveCharacter]->GetBuyingPrice(bought_item->GetValue(), pPriceMultiplier);
      GetAsyncKeyState(VK_CONTROL);
      if ( pParty->uNumGold < uPriceItemService )
      {
        PlayHouseSound((unsigned int)window_SpeakInHouse->ptr_1C, (HouseSoundID)2);
        ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2);
        return;
      }
      taken_item = pPlayers[uActiveCharacter]->AddItem(-1, bought_item->uItemID);
      if ( taken_item )
      {
        bought_item->SetIdentified();
        memcpy(&pPlayers[uActiveCharacter]->pInventoryItems[taken_item - 1], bought_item, 0x24u);
        dword_F8B1E4 = 1;
        Party::TakeGold(uPriceItemService);
        viewparams->bRedrawGameUI = 1;
        bought_item->Reset();
        pRenderer->ClearZBuffer(0, 479);
        pPlayers[uActiveCharacter]->PlaySound((PlayerSpeech)SPEECH_75, 0);
        return;
      }
      pPlayers[uActiveCharacter]->PlaySound(SPEECH_NoRoom, 0);
      ShowStatusBarString(pGlobalTXT_LocalizationStrings[563], 5);  // "Pack is Full!"
      break;
    }
    case HOUSE_DIALOGUE_SHOP_SELL:
    {
      v79 = ((pMouse->GetCursorPos(&cursor)->x - 14) >> 5) + 14 * ((pMouse->GetCursorPos(&cursor)->y - 17) >> 5);
      if ( pMouse->GetCursorPos(&cursor)->x <= 13
        || pMouse->GetCursorPos(&cursor)->x >= 462
        || (v15 = pPlayers[uActiveCharacter]->GetItemIDAtInventoryIndex((int *)&v79), !v15) )
          return;
      if ( MerchandiseTest(&pPlayers[uActiveCharacter]->pInventoryItems[v15 - 1], (int)window_SpeakInHouse->ptr_1C) )
      {
        dword_F8B1E4 = 1;
        pPlayers[uActiveCharacter]->SalesProcess(v79, v15 - 1, (int)window_SpeakInHouse->ptr_1C);
        viewparams->bRedrawGameUI = 1;
        pRenderer->ClearZBuffer(0, 479);
        pPlayers[uActiveCharacter]->PlaySound((PlayerSpeech)77, 0);
        return;
      }
      pPlayers[uActiveCharacter]->PlaySound(SPEECH_79, 0);
      pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
      break;
    }
    case HOUSE_DIALOGUE_SHOP_IDENTIFY:
    {
      pMouse->GetCursorPos(&cursor);
      v79 = ((cursor.x - 14) >> 5) + 14 * ((cursor.y - 17) >> 5);
      if (cursor.x > 13  && cursor.x < 462)
      {
        pItemID = pPlayers[uActiveCharacter]->GetItemIDAtInventoryIndex((int *)&v79);
        if ( pItemID )
        {
          uPriceItemService = pPlayers[uActiveCharacter]->GetPriceIdentification(p2DEvents[(unsigned int)window_SpeakInHouse->ptr_1C - 1].fPriceMultiplier);
          item = &pPlayers[uActiveCharacter]->pInventoryItems[pItemID - 1];
          if ( !(item->uAttributes & 1) )
          {
            if ( MerchandiseTest(item, (int)window_SpeakInHouse->ptr_1C) )
            {
              if ( pParty->uNumGold >= uPriceItemService )
              {
                dword_F8B1E4 = 1;
                Party::TakeGold(uPriceItemService);
                item->uAttributes |= 1;
                pPlayers[uActiveCharacter]->PlaySound(SPEECH_73, 0);
                ShowStatusBarString(pGlobalTXT_LocalizationStrings[569], 2);
                return;
              }
              PlayHouseSound((unsigned int)window_SpeakInHouse->ptr_1C, (HouseSoundID)2);
              return;
            }
            pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
            pPlayers[uActiveCharacter]->PlaySound((PlayerSpeech)79, 0);
            return;
          }
          pPlayers[uActiveCharacter]->PlaySound((PlayerSpeech)76, 0);
          return;
        }
      }
      break;
    }
    case HOUSE_DIALOGUE_SHOP_REPAIR:
    {
      v79 = ((pMouse->GetCursorPos(&cursor)->x - 14) >> 5) + 14 * ((pMouse->GetCursorPos(&cursor)->y - 17) >> 5);
      if ( pMouse->GetCursorPos(&cursor)->x > 13 )
      {
        if ( pMouse->GetCursorPos(&cursor)->x < 462 )
        {
          pItemID = pPlayers[uActiveCharacter]->GetItemIDAtInventoryIndex((int *)&v79);
          if ( pItemID )
          {
            item = &pPlayers[uActiveCharacter]->pInventoryItems[pItemID - 1];
            pPriceMultiplier = p2DEvents[(unsigned int)window_SpeakInHouse->ptr_1C - 1].fPriceMultiplier;
            auto _v = (ItemGen *)&pPlayers[uActiveCharacter]->pInventoryItems[pItemID - 1];
            uPriceItemService = pPlayers[uActiveCharacter]->GetPriceRepair(_v->GetValue(), pPriceMultiplier);
            if ( item->uAttributes & 2 )
            {
              if ( MerchandiseTest(item, (int)window_SpeakInHouse->ptr_1C) )
              {
                if ( pParty->uNumGold >= uPriceItemService )
                {
                  dword_F8B1E4 = 1;
                  Party::TakeGold(uPriceItemService);
                  v8 = item->uAttributes;
                  LOBYTE(v8) = v8 & 0xFD;
                  item->uAttributes = v8 | 1;
                  pPlayers[uActiveCharacter]->PlaySound(SPEECH_74, 0);
                  ShowStatusBarString(pGlobalTXT_LocalizationStrings[570], 2);
                  return;
                }
                PlayHouseSound((unsigned int)window_SpeakInHouse->ptr_1C, (HouseSoundID)2);
                return;
              }
              pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
              pPlayers[uActiveCharacter]->PlaySound((PlayerSpeech)79, 0);
              return;
            }
            pPlayers[uActiveCharacter]->PlaySound((PlayerSpeech)76, 0);
            return;
          }
        }
      }
      break;
    }
    case HOUSE_DIALOGUE_SHOP_BUY_STANDARD:
    case HOUSE_DIALOGUE_SHOP_BUY_SPECIAL:
    {
      pCursorPos = pMouse->GetCursorPos(&cursor);
      v18 = pRenderer->pActiveZBuffer[pCursorPos->x + pSRZBufferLineOffsets[pCursorPos->y]] & 0xFFFF;
      if ( !v18 )
        return;
      if ( dialog_menu_id == HOUSE_DIALOGUE_SHOP_BUY_STANDARD)
        bought_item = (ItemGen *)&pParty->StandartItemsInShops[(int)window_SpeakInHouse->ptr_1C][v18 - 1];
      else
        bought_item = &pParty->SpecialItemsInShops[(int)window_SpeakInHouse->ptr_1C][v18 - 1];//(ItemGen *)&pParty->field_C59C[v31 + 724];
      uPriceItemService = pPlayers[uActiveCharacter]->GetBuyingPrice(bought_item->GetValue(), p2DEvents[(unsigned int)window_SpeakInHouse->ptr_1C - 1].fPriceMultiplier);
      uNumSeconds = 0;
      a3 = 0;
      if ( pMapStats->GetMapInfo(pCurrentMapName.data()) )
        a3 = pMapStats->pInfos[pMapStats->GetMapInfo(pCurrentMapName.data())]._steal_perm;
      party_reputation = GetPartyReputation();
      if (pPlayers[uActiveCharacter]->CanSteal())
      {
        if ( GetAsyncKeyState(VK_CONTROL) )
        {
          uNumSeconds = pPlayers[uActiveCharacter]->StealFromShop(bought_item, a3, party_reputation, 0, &a6);
          if ( !uNumSeconds )
          {
            sub_4B1447_party_fine((int)window_SpeakInHouse->ptr_1C, 0, a6);
            return;
          }
        }
      }
      if ( pParty->uNumGold < uPriceItemService )
      {
        if ( uNumSeconds != 2 )
        {
          if ( uNumSeconds != 1 )
          {
            PlayHouseSound((unsigned int)window_SpeakInHouse->ptr_1C, (HouseSoundID)2);
            ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2);// "You don't have enough gold"
            return;
          }
        }
      }
      v39 = pPlayers[uActiveCharacter]->AddItem(-1, bought_item->uItemID);
      if ( v39 )
      {
        bought_item->SetIdentified();
        memcpy(&pPlayers[uActiveCharacter]->pInventoryItems[v39 - 1], bought_item, sizeof(ItemGen));
        if ( pPlayers[uActiveCharacter]->CanSteal() )
        {
          if ( GetAsyncKeyState(VK_CONTROL) )
          {
            if ( uNumSeconds == 1 || uNumSeconds == 2 )
            {
              pPlayers[uActiveCharacter]->pInventoryItems[v39 - 1].SetStolen();
              sub_4B1447_party_fine((int)window_SpeakInHouse->ptr_1C, uNumSeconds, a6);
              viewparams->bRedrawGameUI = 1;
              bought_item->Reset();
              pRenderer->ClearZBuffer(0, 479);
              pPlayers[uActiveCharacter]->PlaySound((PlayerSpeech)SPEECH_75, 0);
              return;
            }
          }
        }
        dword_F8B1E4 = 1;
        Party::TakeGold(uPriceItemService);
        viewparams->bRedrawGameUI = 1;
        bought_item->Reset();
        pRenderer->ClearZBuffer(0, 479);
        pPlayers[uActiveCharacter]->PlaySound((PlayerSpeech)SPEECH_75, 0);
        return;
      }
      pPlayers[uActiveCharacter]->PlaySound(SPEECH_NoRoom, 0);
      ShowStatusBarString(pGlobalTXT_LocalizationStrings[563], 2); // "Pack is Full!"
      break;
    }
    default:// if click video screen in shop
    {
      __debugbreak(); // please do record these dialogue ids to the HOUSE_DIALOGUE_MENU  enum
      if( dialog_menu_id >= 36 && dialog_menu_id <= 72 )
      {
        v42 = dialog_menu_id - 36;
        //v43 = (signed __int64)(*(float *)&p2DEvents_minus1__24[13 * (unsigned int)ptr_507BC0->ptr_1C] * 500.0);
        v43 = (signed __int64)(p2DEvents[(unsigned int)window_SpeakInHouse->ptr_1C - 1].flt_24 * 500.0);
        uPriceItemService = v43 * (100 - pPlayers[uActiveCharacter]->GetMerchant()) / 100;
        if ( uPriceItemService < v43 / 3 )
          uPriceItemService = v43 / 3;
        if ( byte_4ED970_skill_learn_ability_by_class_table[pPlayers[uActiveCharacter]->classType][v42] )
        {
          pSkill = &pPlayers[uActiveCharacter]->pActiveSkills[v42];
          if ( !*pSkill )
          {
            if ( pParty->uNumGold < uPriceItemService )
            {
              ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2);// "You don't have enough gold"
              if ( in_current_building_type == BildingType_Training )
                v55 = 4;
              else
                v55 = 2;
              PlayHouseSound((unsigned int)window_SpeakInHouse->ptr_1C, (HouseSoundID)v55);
              return;
            }
            Party::TakeGold(uPriceItemService);
            dword_F8B1E4 = 1;
           *pSkill = 1;
            pPlayers[uActiveCharacter]->PlaySound((PlayerSpeech)78, 0);
            return;
          }
        }
      }
      break;
    }
  }
}
//----- (004BE386) --------------------------------------------------------
void __fastcall log_error(const char *pMessage)
{
  const char *v1; // edi@1
  FILE *f; // eax@1
  FILE *v3; // esi@1

  v1 = pMessage;
  f = fopen("errorlog.txt", "a");
  v3 = f;
  if ( f )
  {
    fprintf(f, "%s\n", v1);
    fclose(v3);
    fflush(v3);
  }
}

//----- (004BF91E) --------------------------------------------------------
unsigned int __thiscall GameOverMenu(void *ecx0)
{
  char *v1; // eax@2
  unsigned int result; // eax@3
  Player *v3; // eax@7
  char *v4; // ST24_4@9
  int v5; // eax@9
  char *v6; // eax@10
  char *v7; // edx@10
  char *v8; // ecx@12
  char *v9; // eax@14
  unsigned int v10; // eax@25
  GUIWindow pWindow; // [sp+34h] [bp-9Ch]@1
  MSG Msg; // [sp+88h] [bp-48h]@22
  unsigned int v14; // [sp+A4h] [bp-2Ch]@5
  void *v15; // [sp+A8h] [bp-28h]@1
  char *pInString; // [sp+ACh] [bp-24h]@5
  unsigned int v17; // [sp+B0h] [bp-20h]@5
  unsigned int v18; // [sp+B4h] [bp-1Ch]@5
  unsigned int v19; // [sp+B8h] [bp-18h]@5
  int v20; // [sp+BCh] [bp-14h]@7
  Player *i; // [sp+C0h] [bp-10h]@7
  GUIFont *pFont; // [sp+C4h] [bp-Ch]@1
  unsigned __int64 v23; // [sp+C8h] [bp-8h]@5

  v15 = ecx0;

  RGBTexture _this; // [sp+Ch] [bp-C4h]@1
  //RGBTexture::RGBTexture(&this);

  BYTE1(dword_6BE364_game_settings_1) &= 0xBFu;
  bGameoverLoop = 1;
  pVideoPlayer->bStopBeforeSchedule = 0;
  pAudioPlayer->StopChannels(-1, -1);
  pRenderer->BeginScene();
  pRenderer->ClearBlack();
  pRenderer->EndScene();
  pRenderer->Present();
  pVideoPlayer->pResetflag = 0;
  _449B57_test_bit(pParty->_quest_bits, 99);
  _this.Load("winbg.pcx", 2);
  pRenderer->BeginScene();
  pRenderer->DrawTextureRGB(0, 0, &_this);
  pRenderer->EndScene();
  free(_this.pPixels);
  _this.pPixels = 0;
  window_SpeakInHouse = GUIWindow::Create(0, 0, 640, 480, WINDOW_MainMenu, 0, 0);
  pWindow.uFrameX = 75;
  pWindow.uFrameY = 60;
  pWindow.uFrameWidth = 469;
  pWindow.uFrameHeight = 338;
  pWindow.uFrameZ = 543;
  pWindow.uFrameW = 397;
  pFont = LoadFont("endgame.fnt", "FONTPAL", NULL);
  if ( (unsigned __int16)_449B57_test_bit(pParty->_quest_bits, 99) )
  {
    v1 = pGlobalTXT_LocalizationStrings[675];
  }
  else
  {
    result = _449B57_test_bit(pParty->_quest_bits, 100);
    if ( !(short)result )
      return result;
    v1 = pGlobalTXT_LocalizationStrings[676];
  }
  pInString = v1;
  v23 = pParty->uTimePlayed - 138240;
  v19 = (unsigned int)((signed __int64)((double)(pParty->uTimePlayed - 138240) * 0.234375) / 60 / 60) / 0x18;
  v14 = (unsigned int)((signed __int64)((double)(pParty->uTimePlayed - 138240) * 0.234375) / 60 / 60) / 0x18 / 0x1C / 0xC;
  v18 = (unsigned int)((signed __int64)((double)(pParty->uTimePlayed - 138240) * 0.234375) / 60 / 60) / 0x18 / 0x1C % 0xC;
  v17 = v19 % 0x1C;
  if ( !v19 )
    v19 = 1;
  pRenderer->BeginScene();
  pWindow.DrawTitleText(pFont, 1u, 0x23u, 1u, pGlobalTXT_LocalizationStrings[9], 3u);
  v3 = pParty->pPlayers;//[0].pName;
  v23 = 0i64;
  v20 = 0;
  //for ( i = (int)pParty->pPlayers[0].pName; ; v3 = (char *)i )
  for ( i = pParty->pPlayers; ; v3 = i )
  {
	v4 = pClassNames[v3->classType];
    v5 = v3->GetBaseLevel();
	sprintf(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[129], i->pName, v5, v4);
    pWindow.DrawTitleText(
      pFont,
      1u,
      v20 * (LOBYTE(pFont->uFontHeight) - 2) + LOBYTE(pFont->uFontHeight) + 46,
      1u,
      pTmpBuf.data(),
      3u);
	v23 += i->uExperience;//__PAIR__(*(int *)(i - 4), *(int *)(i - 8));
    ++v20;
    ++i;
	if ( i > &pParty->pPlayers[3] )
      break;
  }
  v23 = (signed __int64)v23 / v19;
  v6 = FitTextInAWindow(pInString, pFont, &pWindow, 0xCu, 0);
  pWindow.DrawTitleText(pFont, 1u, 5 * (LOBYTE(pFont->uFontHeight) + 11), 1u, v6, 0);
  strcpy(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[37]);
  v7 = pGlobalTXT_LocalizationStrings[56];
  if ( v17 != 1 )
    v7 = pGlobalTXT_LocalizationStrings[57];
  v8 = pGlobalTXT_LocalizationStrings[146];
  if ( v18 != 1 )
    v8 = pGlobalTXT_LocalizationStrings[148];
  v9 = pGlobalTXT_LocalizationStrings[245];
  if ( v14 != 1 )
    v9 = pGlobalTXT_LocalizationStrings[132];
  sprintf(pTmpBuf2.data(), " %lu %s, %lu %s, %lu %s ", v14, v9, v18, v8, v17, v7);
  strcat(pTmpBuf.data(), pTmpBuf2.data());
  pWindow.DrawTitleText(pFont, 1u, pWindow.uFrameHeight - 2 * LOBYTE(pFont->uFontHeight) - 5, 1u, pTmpBuf.data(), 3u);
  sprintf(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[94], v23);
  pWindow.DrawTitleText(pFont, 1u, pWindow.uFrameHeight, 1u, pTmpBuf.data(), 3u);
  BYTE1(dword_6BE364_game_settings_1) |= 0x40u;
  pRenderer->EndScene();
  pRenderer->Present();
  if ( pRenderer->pRenderD3D )
    pRenderer->pBeforePresentFunction();
  pRenderer->_49F1BC("MM7_Win.Pcx");
  pAllocator->FreeChunk(pFont);
  window_SpeakInHouse->Release();
  window_SpeakInHouse = 0;
  if ( v15 == (void *)2 )
  {
    result = pMessageQueue_50CBD0->uNumMessages;
  }
  else
  {
    LODWORD(v23) = GetTickCount() + 5000;
    while ( (unsigned int)v23 > GetTickCount() )
      ;
    while ( 1 )
    {
      v10 = PeekMessageA(&Msg, 0, 0, 0, 1u);
      if ( !v10 )
        break;
      if ( Msg.message == 18 )
        Game_DeinitializeAndTerminate(0);
      TranslateMessage(&Msg);
      DispatchMessageA(&Msg);
    }
    if ( pMessageQueue_50CBD0->uNumMessages )
    {
      LOBYTE(v10) = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
      pMessageQueue_50CBD0->uNumMessages = v10;
    }
    pKeyActionMap->ResetKeys();
    pKeyActionMap->uLastKeyPressed = 0;
    do
    {
      while ( PeekMessageA(&Msg, 0, 0, 0, 1u) )
      {
        if ( Msg.message == 18 )
          Game_DeinitializeAndTerminate(0);
        TranslateMessage(&Msg);
        DispatchMessageA(&Msg);
      }
    }
    while ( !pKeyActionMap->uLastKeyPressed );
    result = pMessageQueue_50CBD0->uNumMessages;
    if ( pMessageQueue_50CBD0->uNumMessages )
    {
      result = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
      pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
    }
  }
  if ( v15 )
  {
    /*if ( (signed int)result < 40 )
    {
      pMessageQueue_50CBD0->pMessages[result].eType = UIMSG_Quit;
      goto LABEL_42;
    }*/
    pMessageQueue_50CBD0->AddMessage(UIMSG_Quit, 1, 0);
    goto LABEL_43;
  }
  else
  {
    pMessageQueue_50CBD0->AddMessage(UIMSG_ShowFinalWindow, 1, 0);
    goto LABEL_43;
    /*if ( (signed int)result < 40 )
    {
      pMessageQueue_50CBD0->pMessages[result].eType = UIMSG_C5;
LABEL_42:
      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 1;
      result = 3 * pMessageQueue_50CBD0->uNumMessages + 3;
      *(&pMessageQueue_50CBD0->uNumMessages + result) = 0;
      ++pMessageQueue_50CBD0->uNumMessages;
      goto LABEL_43;
    }*/
  }
LABEL_43:
  bGameoverLoop = 0;
  return result;
}

//----- (004D6FB0) --------------------------------------------------------
int /*__usercall*/ sr_sub_4D6FB0/*<eax>*/(stru315 *a1/*<ebp>*/)
{
  int v1; // ebp@1
  unsigned int v2; // esi@1
  unsigned int v3; // edi@1
  int result; // eax@1
  int v5; // ebx@2
  int v6; // edx@2
  int v7; // ebx@3
  __int16 v8; // cx@3
  int v9; // ebx@4
  unsigned __int8 v10; // sf@5
  unsigned __int8 v11; // of@5

  v1 = a1->field_8;
  v2 = *(int *)(v1 + 48);
  v3 = *(int *)(v1 + 44);
  result = *(int *)(v1 + 64);
  if ( !(*(int *)(v1 + 40) & 1) )
    goto LABEL_5;
  --*(int *)(v1 + 40);
  result -= 2;
  v5 = *(int *)(v1 + 60);
  v6 = *(int *)(v1 + 36);
  *(int *)(v1 + 60) += 4;
  while ( 1 )
  {
    *(int *)v5 = v6;
    v9 = *(char *)(*(int *)(v1 + 56)
                  + (*(int *)(v1 + 12) & (v2 >> 16))
                  + ((*(int *)(v1 + 8) & v3) >> *(char *)(v1 + 16)));
    result += 4;
    v2 += *(int *)(v1 + 4);
    v3 += *(int *)v1;
    *(short *)(result - 2) = *(short *)(*(int *)(v1 + 52) + 2 * v9);
LABEL_5:
    v11 = __OFSUB__(*(int *)(v1 + 40), 2);
    v10 = *(int *)(v1 + 40) - 2 < 0;
    *(int *)(v1 + 40) -= 2;
    if ( v10 ^ v11 )
      break;
    v7 = *(char *)(*(int *)(v1 + 56)
                  + (*(int *)(v1 + 12) & (v2 >> 16))
                  + ((*(int *)(v1 + 8) & v3) >> *(char *)(v1 + 16)));
    v2 += *(int *)(v1 + 4);
    v8 = *(short *)(*(int *)(v1 + 52) + 2 * v7);
    v3 += *(int *)v1;
    v5 = *(int *)(v1 + 60);
    v6 = *(int *)(v1 + 36);
    *(short *)result = v8;
    *(int *)(v1 + 60) += 8;
    *(int *)(v5 + 4) = v6;
  }
  *(int *)(v1 + 64) = result;
  *(int *)(v1 + 48) = v2;
  *(int *)(v1 + 44) = v3;
  return result;
}

//----- (004D705A) --------------------------------------------------------
int /*__usercall*/ sr_sub_4D705A/*<eax>*/(stru315 *a1/*<ebp>*/)
{
  int v1; // ebp@1
  unsigned int v2; // esi@1
  unsigned int v3; // edi@1
  int result; // eax@1
  int v5; // ebx@2
  int v6; // edx@2
  unsigned int v7; // ebx@3
  unsigned int v8; // edx@3
  __int16 v9; // cx@11
  unsigned int v10; // ebx@12
  unsigned int v11; // edx@12
  unsigned __int8 v12; // sf@21
  unsigned __int8 v13; // of@21

  v1 = a1->field_8;
  v2 = *(int *)(v1 + 48);
  v3 = *(int *)(v1 + 44);
  result = *(int *)(v1 + 64);
  if ( !(*(int *)(v1 + 40) & 1) )
    goto LABEL_21;
  --*(int *)(v1 + 40);
  result -= 2;
  v5 = *(int *)(v1 + 60);
  v6 = *(int *)(v1 + 36);
  *(int *)(v1 + 60) += 4;
  while ( 1 )
  {
    *(int *)v5 = v6;
    v10 = v3;
    v11 = v2;
    if ( (signed int)v2 < *(int *)(v1 + 20) )
      v11 = *(int *)(v1 + 20);
    if ( (signed int)v3 < *(int *)(v1 + 28) )
      v10 = *(int *)(v1 + 28);
    if ( (signed int)v11 > *(int *)(v1 + 24) )
      v11 = *(int *)(v1 + 24);
    if ( (signed int)v10 > *(int *)(v1 + 32) )
      v10 = *(int *)(v1 + 32);
    result += 4;
    v2 += *(int *)(v1 + 4);
    v3 += *(int *)v1;
    *(short *)(result - 2) = *(short *)(*(int *)(v1 + 52)
                                      + 2
                                      * *(char *)(*(int *)(v1 + 56)
                                                 + (*(int *)(v1 + 12) & (v11 >> 16))
                                                 + ((*(int *)(v1 + 8) & v10) >> *(char *)(v1 + 16))));
LABEL_21:
    v13 = __OFSUB__(*(int *)(v1 + 40), 2);
    v12 = *(int *)(v1 + 40) - 2 < 0;
    *(int *)(v1 + 40) -= 2;
    if ( v12 ^ v13 )
      break;
    v7 = v3;
    v8 = v2;
    if ( (signed int)v2 < *(int *)(v1 + 20) )
      v8 = *(int *)(v1 + 20);
    if ( (signed int)v3 < *(int *)(v1 + 28) )
      v7 = *(int *)(v1 + 28);
    if ( (signed int)v8 > *(int *)(v1 + 24) )
      v8 = *(int *)(v1 + 24);
    if ( (signed int)v7 > *(int *)(v1 + 32) )
      v7 = *(int *)(v1 + 32);
    v2 += *(int *)(v1 + 4);
    v9 = *(short *)(*(int *)(v1 + 52)
                  + 2
                  * *(char *)(*(int *)(v1 + 56)
                             + (*(int *)(v1 + 12) & (v8 >> 16))
                             + ((*(int *)(v1 + 8) & v7) >> *(char *)(v1 + 16))));
    v3 += *(int *)v1;
    v5 = *(int *)(v1 + 60);
    v6 = *(int *)(v1 + 36);
    *(short *)result = v9;
    *(int *)(v1 + 60) += 8;
    *(int *)(v5 + 4) = v6;
  }
  *(int *)(v1 + 64) = result;
  *(int *)(v1 + 48) = v2;
  *(int *)(v1 + 44) = v3;
  return result;
}

//----- (004D714C) --------------------------------------------------------
int __cdecl sr_sub_4D714C(stru315 *a1)
{
  stru315 *v1; // ebp@0
  stru315 *v2; // ebp@1
  unsigned int v3; // esi@1
  int v4; // edi@1
  int result; // eax@1
  unsigned int *v6; // ebx@2
  int v7; // edx@2
  int v8; // ebx@3
  unsigned __int16 v9; // cx@3
  unsigned int *v10; // ebx@3
  int v11; // edx@3
  int v12; // ebx@4
  unsigned __int8 v13; // sf@5
  unsigned __int8 v14; // of@5

  v2 = (stru315 *)v1->field_8;
  v3 = v2->field_30;
  v4 = v2->field_2C;
  result = (int)v2->pColorBuffer;
  if ( !(v2->field_28 & 1) )
    goto LABEL_5;
  --v2->field_28;
  result += 2;
  v6 = v2->pDepthBuffer;
  v7 = v2->field_24;
  --v2->pDepthBuffer;
  *v6 = v7;
  while ( 1 )
  {
    v12 = *((char *)v2->pTextureLOD
          + (v2->field_C & (v3 >> 16))
          + ((v2->field_8 & (unsigned int)v4) >> LOBYTE(v2->field_10)));
    result -= 4;
    v3 += v2->field_4;
    v4 += v2->field_0;
    *(short *)(result + 2) = v2->field_34_palette[v12];
LABEL_5:
    v14 = __OFSUB__(v2->field_28, 2);
    v13 = v2->field_28 - 2 < 0;
    v2->field_28 -= 2;
    if ( v13 ^ v14 )
      break;
    v8 = *((char *)v2->pTextureLOD
         + (v2->field_C & (v3 >> 16))
         + ((v2->field_8 & (unsigned int)v4) >> LOBYTE(v2->field_10)));
    v3 += v2->field_4;
    v9 = v2->field_34_palette[v8];
    v4 += v2->field_0;
    v10 = v2->pDepthBuffer;
    v11 = v2->field_24;
    *(short *)result = v9;
    v2->pDepthBuffer -= 2;
    *v10 = v11;
    *(v10 - 1) = v11;
  }
  v2->pColorBuffer = (unsigned __int16 *)result;
  v2->field_30 = v3;
  v2->field_2C = v4;
  return result;
}
// 4D714C: inconsistent function type and number of purged bytes

//----- (004D71F8) --------------------------------------------------------
int __cdecl sr_sub_4D71F8(stru315 *a1)
{
  stru315 *v1; // ebp@0
  stru315 *v2; // ebp@1
  int v3; // esi@1
  int v4; // edi@1
  int result; // eax@1
  unsigned int *v6; // ebx@2
  int v7; // edx@2
  int v8; // ebx@3
  unsigned int v9; // edx@3
  unsigned __int16 v10; // cx@11
  unsigned int *v11; // ebx@11
  int v12; // edx@11
  int v13; // ebx@12
  unsigned int v14; // edx@12
  unsigned __int8 v15; // sf@21
  unsigned __int8 v16; // of@21

  v2 = (stru315 *)v1->field_8;
  v3 = v2->field_30;
  v4 = v2->field_2C;
  result = (int)v2->pColorBuffer;
  if ( !(v2->field_28 & 1) )
    goto LABEL_21;
  --v2->field_28;
  result += 2;
  v6 = v2->pDepthBuffer;
  v7 = v2->field_24;
  --v2->pDepthBuffer;
  *v6 = v7;
  while ( 1 )
  {
    v13 = v4;
    v14 = v3;
    if ( v3 < v2->field_14 )
      v14 = v2->field_14;
    if ( v4 < v2->field_1C )
      v13 = v2->field_1C;
    if ( (signed int)v14 > v2->field_18 )
      v14 = v2->field_18;
    if ( v13 > v2->field_20 )
      v13 = v2->field_20;
    result -= 4;
    v3 += v2->field_4;
    v4 += v2->field_0;
    *(short *)(result + 2) = v2->field_34_palette[*((char *)v2->pTextureLOD
                                                  + (v2->field_C & (v14 >> 16))
                                                  + ((v2->field_8 & (unsigned int)v13) >> LOBYTE(v2->field_10)))];
LABEL_21:
    v16 = __OFSUB__(v2->field_28, 2);
    v15 = v2->field_28 - 2 < 0;
    v2->field_28 -= 2;
    if ( v15 ^ v16 )
      break;
    v8 = v4;
    v9 = v3;
    if ( v3 < v2->field_14 )
      v9 = v2->field_14;
    if ( v4 < v2->field_1C )
      v8 = v2->field_1C;
    if ( (signed int)v9 > v2->field_18 )
      v9 = v2->field_18;
    if ( v8 > v2->field_20 )
      v8 = v2->field_20;
    v3 += v2->field_4;
    v10 = v2->field_34_palette[*((char *)v2->pTextureLOD
                               + (v2->field_C & (v9 >> 16))
                               + ((v2->field_8 & (unsigned int)v8) >> LOBYTE(v2->field_10)))];
    v4 += v2->field_0;
    v11 = v2->pDepthBuffer;
    v12 = v2->field_24;
    *(short *)result = v10;
    v2->pDepthBuffer -= 2;
    *v11 = v12;
    *(v11 - 1) = v12;
  }
  v2->pColorBuffer = (unsigned __int16 *)result;
  v2->field_30 = v3;
  v2->field_2C = v4;
  return result;
}
// 4D71F8: inconsistent function type and number of purged bytes

//----- (004D72EC) --------------------------------------------------------
int /*__usercall*/ sr_sub_4D72EC/*<eax>*/(int a1/*<ebp>*/)
{
  int v1; // ebp@1
  unsigned int v2; // esi@1
  unsigned int v3; // edi@1
  int result; // eax@1
  int v5; // ebx@2
  int v6; // edx@2
  unsigned int v7; // edx@3
  unsigned int v8; // ebx@3
  int v9; // ebx@11
  unsigned int v10; // edx@14
  unsigned int v11; // ebx@14
  int v12; // ebx@22
  unsigned __int8 v13; // sf@25
  unsigned __int8 v14; // of@25

  v1 = *(int *)(a1 + 8);
  v2 = *(int *)(v1 + 48);
  v3 = *(int *)(v1 + 44);
  result = *(int *)(v1 + 64);
  if ( !(*(int *)(v1 + 40) & 1) )
    goto LABEL_25;
  --*(int *)(v1 + 40);
  result -= 2;
  v5 = *(int *)(v1 + 60);
  v6 = *(int *)(v1 + 36);
  *(int *)(v1 + 60) += 4;
  while ( 1 )
  {
    *(int *)v5 = v6;
    v10 = v2;
    v11 = v3;
    if ( (signed int)v2 < *(int *)(v1 + 20) )
      v10 = *(int *)(v1 + 20);
    if ( (signed int)v3 < *(int *)(v1 + 28) )
      v11 = *(int *)(v1 + 28);
    if ( (signed int)v10 > *(int *)(v1 + 24) )
      v10 = *(int *)(v1 + 24);
    if ( (signed int)v11 > *(int *)(v1 + 32) )
      v11 = *(int *)(v1 + 32);
    v12 = *(char *)(*(int *)(v1 + 56)
                   + (*(int *)(v1 + 12) & (v10 >> 16))
                   + ((*(int *)(v1 + 8) & v11) >> *(char *)(v1 + 16)));
    result += 4;
    v2 += *(int *)(v1 + 4);
    if ( v12 )
      *(short *)(result - 2) = *(short *)(*(int *)(v1 + 52) + 2 * v12);
    v3 += *(int *)v1;
LABEL_25:
    v14 = __OFSUB__(*(int *)(v1 + 40), 2);
    v13 = *(int *)(v1 + 40) - 2 < 0;
    *(int *)(v1 + 40) -= 2;
    if ( v13 ^ v14 )
      break;
    v7 = v2;
    v8 = v3;
    if ( (signed int)v2 < *(int *)(v1 + 20) )
      v7 = *(int *)(v1 + 20);
    if ( (signed int)v3 < *(int *)(v1 + 28) )
      v8 = *(int *)(v1 + 28);
    if ( (signed int)v7 > *(int *)(v1 + 24) )
      v7 = *(int *)(v1 + 24);
    if ( (signed int)v8 > *(int *)(v1 + 32) )
      v8 = *(int *)(v1 + 32);
    v9 = *(char *)(*(int *)(v1 + 56)
                  + (*(int *)(v1 + 12) & (v7 >> 16))
                  + ((*(int *)(v1 + 8) & v8) >> *(char *)(v1 + 16)));
    v2 += *(int *)(v1 + 4);
    if ( v9 )
      *(short *)result = *(short *)(*(int *)(v1 + 52) + 2 * v9);
    v3 += *(int *)v1;
    v5 = *(int *)(v1 + 60);
    v6 = *(int *)(v1 + 36);
    *(int *)(v1 + 60) += 8;
    *(int *)(v5 + 4) = v6;
  }
  return result;
}

//----- (004D73DF) --------------------------------------------------------
int /*__usercall*/ sr_sub_4D73DF/*<eax>*/(int a1/*<ebp>*/)
{
  int v1; // ebp@1
  unsigned int v2; // esi@1
  unsigned int v3; // edi@1
  int result; // eax@1
  int v5; // ebx@2
  int v6; // edx@2
  int v7; // edx@3
  int v8; // edx@6
  unsigned __int8 v9; // sf@9
  unsigned __int8 v10; // of@9

  v1 = *(int *)(a1 + 8);
  v2 = *(int *)(v1 + 48);
  v3 = *(int *)(v1 + 44);
  result = *(int *)(v1 + 64);
  if ( !(*(int *)(v1 + 40) & 1) )
    goto LABEL_9;
  --*(int *)(v1 + 40);
  result -= 2;
  v5 = *(int *)(v1 + 60);
  v6 = *(int *)(v1 + 36);
  *(int *)(v1 + 60) += 4;
  while ( 1 )
  {
    *(int *)v5 = v6;
    v8 = *(int *)(v1 + 12) & (v2 >> 16);
    result += 4;
    v2 += *(int *)(v1 + 4);
    if ( *(char *)(*(int *)(v1 + 56) + v8 + ((*(int *)(v1 + 8) & v3) >> *(char *)(v1 + 16))) )
      *(short *)(result - 2) = *(short *)(*(int *)(v1 + 52)
                                        + 2
                                        * *(char *)(*(int *)(v1 + 56)
                                                   + v8
                                                   + ((*(int *)(v1 + 8) & v3) >> *(char *)(v1 + 16))));
    v3 += *(int *)v1;
LABEL_9:
    v10 = __OFSUB__(*(int *)(v1 + 40), 2);
    v9 = *(int *)(v1 + 40) - 2 < 0;
    *(int *)(v1 + 40) -= 2;
    if ( v9 ^ v10 )
      break;
    v7 = *(int *)(v1 + 12) & (v2 >> 16);
    v2 += *(int *)(v1 + 4);
    if ( *(char *)(*(int *)(v1 + 56) + v7 + ((*(int *)(v1 + 8) & v3) >> *(char *)(v1 + 16))) )
      *(short *)result = *(short *)(*(int *)(v1 + 52)
                                  + 2
                                  * *(char *)(*(int *)(v1 + 56)
                                             + v7
                                             + ((*(int *)(v1 + 8) & v3) >> *(char *)(v1 + 16))));
    v3 += *(int *)v1;
    v5 = *(int *)(v1 + 60);
    v6 = *(int *)(v1 + 36);
    *(int *)(v1 + 60) += 8;
    *(int *)(v5 + 4) = v6;
  }
  return result;
}

//----- (004D754B) --------------------------------------------------------
void __cdecl sr_sub_4D754B(stru315 *a1, stru316 *a2)
{
  int v2; // ecx@1
  unsigned int v3; // eax@2
  int v4; // ecx@2
  int v5; // eax@10
  unsigned __int16 *v6; // edx@10
  int v7; // ebx@11
  int v8; // ecx@13
  unsigned __int16 v9; // bx@16
  int v10; // ecx@16
  unsigned __int16 *v11; // eax@16
  unsigned int *v12; // edx@16
  int v13; // ecx@16
  int v14; // eax@16
  int v15; // ebx@16
  int v16; // [sp-4h] [bp-Ch]@2

  v2 = a1->field_28;
  if ( v2 )
  {
    do
    {
      v16 = v2;
      v3 = a1->field_30;
      v4 = a1->field_2C;
      if ( (signed int)v3 >= a1->field_18 )
        v3 = a1->field_18;
      if ( (signed int)v3 <= a1->field_14 )
        v3 = a1->field_14;
      if ( v4 >= a1->field_20 )
        v4 = a1->field_20;
      if ( v4 <= a1->field_1C )
        v4 = a1->field_1C;
      v5 = *((char *)a1->pTextureLOD + (a1->field_C & (v3 >> 16)) + (((unsigned int)v4 & a1->field_8) >> a1->field_10));
      v6 = a1->field_34_palette;
      if ( a2->field_20 )
      {
        v7 = (unsigned int)a2->field_10 >> 16;
        if ( v7 >= a2->field_C )
          v7 = a2->field_C;
        v8 = 0;
        if ( a2->field_8 - v7 >= 0 )
          v8 = a2->field_8 - v7;
        v5 += v8 << 8;
        v6 = a2->field_24_palette;
      }
      v9 = v6[v5];
      v10 = a1->field_24;
      v11 = a1->pColorBuffer;
      v12 = a1->pDepthBuffer;
      *v11 = v9;
      *v12 = v10;
      a1->pColorBuffer = v11 + 1;
      a1->pDepthBuffer = v12 + 1;
      v13 = a1->field_30;
      a2->field_10 += a2->field_18;
      v14 = a1->field_2C;
      v15 = a1->field_0;
      a1->field_30 = a1->field_4 + v13;
      a1->field_2C = v15 + v14;
      v2 = v16 - 1;
    }
    while ( v16 != 1 );
  }
}

//----- (004D7630) --------------------------------------------------------
void __cdecl sr_sub_4D7630(stru315 *a1, stru316 *a2)
{
  int v2; // ecx@1
  int v3; // eax@2
  unsigned __int16 *v4; // edx@2
  int v5; // ebx@3
  int v6; // ecx@5
  unsigned __int16 v7; // bx@8
  int v8; // ecx@8
  unsigned __int16 *v9; // eax@8
  unsigned int *v10; // edx@8
  int v11; // ecx@8
  int v12; // eax@8
  int v13; // ebx@8
  int v14; // [sp-4h] [bp-Ch]@2

  v2 = a1->field_28;
  if ( v2 )
  {
    do
    {
      v14 = v2;
      v3 = *((char *)a1->pTextureLOD
           + (a1->field_C & ((unsigned int)a1->field_30 >> 16))
           + ((unsigned int)(a1->field_2C & a1->field_8) >> a1->field_10));
      v4 = a1->field_34_palette;
      if ( a2->field_20 )
      {
        v5 = (unsigned int)a2->field_14 >> 16;
        if ( v5 >= a2->field_C )
          v5 = a2->field_C;
        v6 = 0;
        if ( a2->field_8 - v5 >= 0 )
          v6 = a2->field_8 - v5;
        v3 += v6 << 8;
        v4 = a2->field_24_palette;
      }
      v7 = v4[v3];
      v8 = a1->field_24;
      v9 = a1->pColorBuffer;
      v10 = a1->pDepthBuffer;
      *v9 = v7;
      *v10 = v8;
      a1->pColorBuffer = v9 - 1;
      a1->pDepthBuffer = v10 - 1;
      v11 = a1->field_30;
      a2->field_14 -= a2->field_18;
      v12 = a1->field_2C;
      v13 = a1->field_0;
      a1->field_30 = a1->field_4 + v11;
      a1->field_2C = v13 + v12;
      v2 = v14 - 1;
    }
    while ( v14 != 1 );
  }
}

//----- (004D76ED) --------------------------------------------------------
void __cdecl sr_sub_4D76ED(stru315 *a1, stru316 *a2)
{
  int v2; // ecx@1
  unsigned int v3; // eax@2
  int v4; // ecx@2
  int v5; // eax@10
  unsigned __int16 *v6; // edx@10
  int v7; // ebx@11
  int v8; // ecx@13
  unsigned __int16 v9; // bx@16
  int v10; // ecx@16
  unsigned __int16 *v11; // eax@16
  unsigned int *v12; // edx@16
  int v13; // ecx@16
  int v14; // eax@16
  int v15; // ebx@16
  int v16; // [sp-4h] [bp-Ch]@2

  v2 = a1->field_28;
  if ( v2 )
  {
    do
    {
      v16 = v2;
      v3 = a1->field_30;
      v4 = a1->field_2C;
      if ( (signed int)v3 >= a1->field_18 )
        v3 = a1->field_18;
      if ( (signed int)v3 <= a1->field_14 )
        v3 = a1->field_14;
      if ( v4 >= a1->field_20 )
        v4 = a1->field_20;
      if ( v4 <= a1->field_1C )
        v4 = a1->field_1C;
      v5 = *((char *)a1->pTextureLOD + (a1->field_C & (v3 >> 16)) + (((unsigned int)v4 & a1->field_8) >> a1->field_10));
      v6 = a1->field_34_palette;
      if ( a2->field_20 )
      {
        v7 = (unsigned int)a2->field_14 >> 16;
        if ( v7 >= a2->field_C )
          v7 = a2->field_C;
        v8 = 0;
        if ( a2->field_8 - v7 >= 0 )
          v8 = a2->field_8 - v7;
        v5 += v8 << 8;
        v6 = a2->field_24_palette;
      }
      v9 = v6[v5];
      v10 = a1->field_24;
      v11 = a1->pColorBuffer;
      v12 = a1->pDepthBuffer;
      *v11 = v9;
      *v12 = v10;
      a1->pColorBuffer = v11 - 1;
      a1->pDepthBuffer = v12 - 1;
      v13 = a1->field_30;
      a2->field_14 -= a2->field_18;
      v14 = a1->field_2C;
      v15 = a1->field_0;
      a1->field_30 = a1->field_4 + v13;
      a1->field_2C = v15 + v14;
      v2 = v16 - 1;
    }
    while ( v16 != 1 );
  }
}

//----- (004D77D2) --------------------------------------------------------
void __cdecl sr_sub_4D77D2(stru315 *a1, stru316 *a2)
{
  int v2; // ecx@1
  unsigned __int16 *v3; // ebx@2
  int v4; // eax@2
  unsigned __int16 *v5; // edx@2
  int v6; // ebx@4
  int v7; // ecx@6
  unsigned __int16 v8; // bx@9
  int v9; // ecx@9
  unsigned int *v10; // edx@9
  unsigned int *v11; // edx@10
  int v12; // ecx@10
  int v13; // eax@10
  int v14; // ebx@10
  int v15; // [sp-4h] [bp-Ch]@2

  v2 = a1->field_28;
  if ( v2 )
  {
    do
    {
      v15 = v2;
      v3 = a1->pTextureLOD;
      v4 = *((char *)v3
           + (a1->field_C & ((unsigned int)a1->field_30 >> 16))
           + ((unsigned int)(a1->field_2C & a1->field_8) >> a1->field_10));
      v5 = a1->field_34_palette;
      if ( *((char *)v3
           + (a1->field_C & ((unsigned int)a1->field_30 >> 16))
           + ((unsigned int)(a1->field_2C & a1->field_8) >> a1->field_10)) )
      {
        if ( a2->field_20 )
        {
          v6 = (unsigned int)a2->field_10 >> 16;
          if ( v6 >= a2->field_C )
            v6 = a2->field_C;
          v7 = 0;
          if ( a2->field_8 - v6 >= 0 )
            v7 = a2->field_8 - v6;
          v4 += v7 << 8;
          v5 = a2->field_24_palette;
        }
        v8 = v5[v4];
        v9 = a1->field_24;
        v10 = a1->pDepthBuffer;
        *a1->pColorBuffer = v8;
        *v10 = v9;
      }
      v11 = a1->pDepthBuffer + 1;
      ++a1->pColorBuffer;
      a1->pDepthBuffer = v11;
      v12 = a1->field_30;
      a2->field_10 += a2->field_18;
      v13 = a1->field_2C;
      v14 = a1->field_0;
      a1->field_30 = a1->field_4 + v12;
      a1->field_2C = v14 + v13;
      v2 = v15 - 1;
    }
    while ( v15 != 1 );
  }
}

//----- (004D789A) --------------------------------------------------------
void __cdecl sr_sub_4D789A(stru315 *a1, stru316 *a2)
{
  int v2; // ecx@1
  unsigned int v3; // eax@2
  int v4; // ecx@2
  int v5; // eax@10
  unsigned __int16 *v6; // edx@10
  int v7; // ebx@12
  int v8; // ecx@14
  unsigned __int16 v9; // bx@17
  int v10; // ecx@17
  unsigned int *v11; // edx@17
  unsigned int *v12; // edx@18
  int v13; // ecx@18
  int v14; // eax@18
  int v15; // ebx@18
  int v16; // [sp-4h] [bp-Ch]@2

  v2 = a1->field_28;
  if ( v2 )
  {
    do
    {
      v16 = v2;
      v3 = a1->field_30;
      v4 = a1->field_2C;
      if ( (signed int)v3 >= a1->field_18 )
        v3 = a1->field_18;
      if ( (signed int)v3 <= a1->field_14 )
        v3 = a1->field_14;
      if ( v4 >= a1->field_20 )
        v4 = a1->field_20;
      if ( v4 <= a1->field_1C )
        v4 = a1->field_1C;
      v5 = *((char *)a1->pTextureLOD + (a1->field_C & (v3 >> 16)) + (((unsigned int)v4 & a1->field_8) >> a1->field_10));
      v6 = a1->field_34_palette;
      if ( v5 )
      {
        if ( a2->field_20 )
        {
          v7 = (unsigned int)a2->field_10 >> 16;
          if ( v7 >= a2->field_C )
            v7 = a2->field_C;
          v8 = 0;
          if ( a2->field_8 - v7 >= 0 )
            v8 = a2->field_8 - v7;
          v5 += v8 << 8;
          v6 = a2->field_24_palette;
        }
        v9 = v6[v5];
        v10 = a1->field_24;
        v11 = a1->pDepthBuffer;
        *a1->pColorBuffer = v9;
        *v11 = v10;
      }
      v12 = a1->pDepthBuffer + 1;
      ++a1->pColorBuffer;
      a1->pDepthBuffer = v12;
      v13 = a1->field_30;
      a2->field_10 += a2->field_18;
      v14 = a1->field_2C;
      v15 = a1->field_0;
      a1->field_30 = a1->field_4 + v13;
      a1->field_2C = v15 + v14;
      v2 = v16 - 1;
    }
    while ( v16 != 1 );
  }
}

//----- (00451007) --------------------------------------------------------
int stru350::sub_451007_scale_image_bicubic(unsigned short *pSrc, int srcWidth, int srcHeight, int srcPitch,          //changing this to some library function might be a good idea
                                            unsigned short *pDst, int dstWidth, int dstHeight, int dstPitch,
                                            int a10, int a11)
{
  int result; // eax@1
  float v17; // ST3C_4@12
  float v18; // ST38_4@12
  unsigned int v19; // esi@12
  int v21; // eax@18
  unsigned int v22; // ecx@25
  unsigned int v23; // eax@29
  unsigned int heightRatioPlusOne; // [sp+Ch] [bp-7Ch]@12
  unsigned int widthRatio; // [sp+Ch] [bp-7Ch]@218
  unsigned int heightRatio; // [sp+14h] [bp-74h]@12
  unsigned int widthRatioPlusOne; // [sp+14h] [bp-74h]@218
  int v160; // [sp+3Ch] [bp-4Ch]@13
  unsigned __int16 *v175; // [sp+4Ch] [bp-3Ch]@13
  unsigned __int16 *v193; // [sp+5Ch] [bp-2Ch]@7
  signed int v231; // [sp+78h] [bp-10h]@7
  __int64 v240; // [sp+7Ch] [bp-Ch]@12
  unsigned int v251; // [sp+80h] [bp-8h]@218
  unsigned int v252; // [sp+84h] [bp-4h]@218
  float a6s; // [sp+A0h] [bp+18h]@218
  float a6t; // [sp+A0h] [bp+18h]@218
  unsigned int a6b; // [sp+A0h] [bp+18h]@218
  int field_0_bits;
  int field_20_bits;
  
  int field0value = this->field_0.field_C;
  switch(field0value)
  {
  case 8: field_0_bits = 1;
    break;
  case 16: field_0_bits = 2;
    break;
  case 32: field_0_bits = 4;
    break;
  default:
    return field0value;
  }
  int field20value = this->field_20.field_C;
  switch(field20value)
  {
  case 8: field_20_bits = 1;
    break;
  case 16: field_20_bits = 2;
    break;
  case 32: field_20_bits = 4;
    break;
  default:
    return field20value;
  }

  result = (int)pDst;
  v193 = pDst;
  v231 = 0;
  if ( dstHeight <= 0 )
    return result;
  do
  {
    for (int counter = 0; counter < dstWidth; counter++)
    {
      a6s = (double)counter / (double)dstWidth * (double)srcWidth;
      widthRatio = bankersRounding(a6s);
      a6t = (double)(counter + 1) / (double)dstWidth * (double)srcWidth;
      widthRatioPlusOne = bankersRounding(a6t);
      v17 = (double)v231 / (double)dstHeight * (double)srcHeight;
      heightRatio = bankersRounding(v17);
      v18 = (double)(v231 + 1) / (double)dstHeight * (double)srcHeight;
      heightRatioPlusOne = bankersRounding(v18);
      v251 = 0;
      v19 = (heightRatioPlusOne - heightRatio) * (widthRatioPlusOne - widthRatio);
      v252 = 0;
      a6b = 0;
      v240 = 0i64;

      v175 = (unsigned short*)((char *)pSrc + field_0_bits * (widthRatio + srcPitch * heightRatio));
      for (int heightDiff = 0; heightDiff < heightRatioPlusOne - heightRatio; heightDiff++)
      {
        int ratioDiff = widthRatioPlusOne - widthRatio;
        for(int i = 0; i < ratioDiff; i++)
        {
          if(field0value == 32)
            v21 = _450FB1((int)v175[i]);
          else if(field0value == 16)
            v21 = _450FB1((_WORD)v175[i]);
          else
            v21 = _450FB1((unsigned __int8)v175[i]);
          v240 += ((unsigned int)v21 >> 24);
          a6b += BYTE2(v21);
          v252 += BYTE1(v21);
          v251 += (unsigned __int8)v21;
        }
        if(field0value == 32)
          v175 += 2 * srcPitch;
        else if(field0value == 16)
          v175 += srcPitch;   
        else
          v175 = (unsigned short*)((char *)v175 + 2 * srcPitch);
      }
      v22 = (unsigned int)v240 / ((heightRatioPlusOne - heightRatio) * (widthRatioPlusOne - widthRatio));
      if ( v19 )
      {
        a6b /= v19;
        v252 /= v19;
        v251 /= v19;
      }
      if ( v22 != 255 )
        v22 &= 0x7FFFFFFFu;
      v23 = _450F55(v251 | ((v252 | ((a6b | (v22 << 8)) << 8)) << 8));
      *(_DWORD *)v193 = v23;
      v193 = (unsigned __int16 *)((char *)v193 + field_20_bits);
    }
    v193 = (unsigned __int16 *)((char *)v193 + field_20_bits * (dstPitch - dstWidth));
    ++v231;
    result = v231;
  }
  while(v231 < dstHeight);
  return result;
}

//----- (0044E1EC) --------------------------------------------------------
int TextureFrameTable::FromFileTxt(const char *Args)
{
  TextureFrameTable *v2; // ebx@1
  FILE *v3; // eax@1
  int v4; // esi@3
  const void *v5; // ST0C_4@10
  void *v6; // eax@10
  FILE *v7; // ST0C_4@12
  char *i; // eax@12
  signed int v9; // esi@15
  int v10; // eax@17
  int v11; // edx@22
  int v12; // ecx@23
  int v13; // eax@24
  signed int j; // eax@27
  TextureFrame *v15; // edx@28
  int v16; // esi@28
  int k; // ecx@29
  char Buf; // [sp+Ch] [bp-2F8h]@3
  FrameTableTxtLine v20; // [sp+200h] [bp-104h]@4
  int v21; // [sp+27Ch] [bp-88h]@4
  char *Str1; // [sp+280h] [bp-84h]@5
  char *Str; // [sp+284h] [bp-80h]@15
  int v24; // [sp+2F8h] [bp-Ch]@3
  int v25; // [sp+2FCh] [bp-8h]@3
  FILE *File; // [sp+300h] [bp-4h]@1
  int Argsa; // [sp+30Ch] [bp+8h]@28

  v2 = this;
  v3 = fopen(Args, "r");
  File = v3;
  if ( !v3 )
    Abortf("CTextureFrameTable::load - Unable to open file: %s.", Args);
  v4 = 0;
  v24 = 0;
  v25 = 1;
  if ( fgets(&Buf, 490, v3) )
  {
    do
    {
      *strchr(&Buf, 10) = 0;
      memcpy(&v21, txt_file_frametable_parser(&Buf, &v20), 0x7Cu);
      if ( v21 && *Str1 != 47 )
      {
        if ( v21 < 2 )
          Abortf("CTextureFrameTable::load, too few arguments, %s line %i.", Args, v25);
        ++v24;
      }
      ++v25;
    }
    while ( fgets(&Buf, 490, File) );
    v4 = v24;
  }
  v5 = v2->pTextures;
  v2->sNumTextures = v4;
  v6 = pAllocator->AllocNamedChunk(v5, 20 * v4, "Txt Frames");
  v2->pTextures = (TextureFrame *)v6;
  if ( !v6 )
    Abortf("CTextureFrameTable::load - Out of Memory!");
  v7 = File;
  v2->sNumTextures = 0;
  fseek(v7, 0, 0);
  for ( i = fgets(&Buf, 490, File); i; i = fgets(&Buf, 490, File) )
  {
    *strchr(&Buf, 10) = 0;
    memcpy(&v21, txt_file_frametable_parser(&Buf, &v20), 0x7Cu);
    if ( v21 && *Str1 != 47 )
    {
      strcpy(v2->pTextures[v2->sNumTextures].pTextureName, Str1);
      v2->pTextures[v2->sNumTextures].uAnimTime = atoi(Str);
      v9 = 2;
      for ( v2->pTextures[v2->sNumTextures].uFlags = 0; v9 < v21; ++v9 )
      {
        if ( !_stricmp((&Str1)[4 * v9], "New") )
        {
          v10 = (int)&v2->pTextures[v2->sNumTextures].uFlags;
          *(char *)v10 |= 2u;
        }
      }
      ++v2->sNumTextures;
    }
  }
  fclose(File);
  v11 = 0;
  if ( (signed int)(v2->sNumTextures - 1) > 0 )
  {
    v12 = 0;
    do
    {
      v13 = (int)&v2->pTextures[v12];
      if ( !(*(char *)(v13 + 38) & 2) )
        *(char *)(v13 + 18) |= 1u;
      ++v11;
      ++v12;
    }
    while ( v11 < (signed int)(v2->sNumTextures - 1) );
  }
  for ( j = 0; j < (signed int)v2->sNumTextures; *(short *)(Argsa + 16) = v16 )
  {
    v15 = v2->pTextures;
    Argsa = (int)&v15[j];
    v16 = *(short *)(Argsa + 14);
    if ( *(char *)(Argsa + 18) & 1 )
    {
      ++j;
      for ( k = (int)&v15[j]; *(char *)(k + 18) & 1; k += 20 )
      {
        v16 += *(short *)(k + 14);
        ++j;
      }
      LOWORD(v16) = v15[j].uAnimTime + v16;
    }
    ++j;
  }
  return 1;
}

//----- (0044F57C) --------------------------------------------------------
void SpawnEncounter(MapInfo *pMapInfo, SpawnPointMM7 *spawn, int a3, int a4, int a5)
{
  //MapInfo *v5; // esi@1
  //SpawnPointMM7 *v6; // ebx@1
  int v7; // eax@2
  char v8; // zf@5
  int v9; // edi@9
  int v10; // eax@9
  int v11; // ecx@9
  int v12; // edx@9
  int v13; // eax@9
  int v14; // eax@14
  int v15; // ecx@14
  int v16; // eax@19
  int v17; // ecx@19
  int v18; // esi@31
  //int pPosX; // ecx@32
  //int v20; // edx@32
  //int v21; // eax@32
  Actor *pMonster; // esi@35
  int v23; // edx@36
  signed int v24; // edi@36
  int v25; // ecx@36
  unsigned __int16 v26; // ax@47
  MonsterDesc *v27; // edi@48
  signed int v28; // eax@48
  __int16 v29; // cx@50
  __int16 v30; // ax@50
  __int16 v31; // ax@50
  int v32; // eax@50
  int v33; // edi@50
  int v34; // eax@50
  int v35; // eax@50
  int v36; // eax@50
  int v37; // eax@51
  int v38; // eax@52
  int v39; // edi@52
  std::string v40; // [sp-18h] [bp-100h]@60
  void *v41; // [sp-14h] [bp-FCh]@50
  //void *v42; // [sp-10h] [bp-F8h]@50
  //size_t v43; // [sp-Ch] [bp-F4h]@50
  const char *v44; // [sp-8h] [bp-F0h]@13
  char *pTexture; // [sp-4h] [bp-ECh]@9
  char Str[32]; // [sp+Ch] [bp-DCh]@60
  char Str2[120]; // [sp+2Ch] [bp-BCh]@29
  unsigned int uFaceID; // [sp+A4h] [bp-44h]@52
  MonsterInfo *Src; // [sp+A8h] [bp-40h]@50
  int v50; // [sp+ACh] [bp-3Ch]@47
  char Source[32]; // [sp+B0h] [bp-38h]@20
  int v52; // [sp+D0h] [bp-18h]@34
  int v53; // [sp+D4h] [bp-14h]@34
  int pSector; // [sp+D8h] [bp-10h]@32
  int pPosX; // [sp+DCh] [bp-Ch]@32
  int v56; // [sp+E0h] [bp-8h]@8
  int v57; // [sp+E4h] [bp-4h]@1

  //auto a2 = spawn;
  v57 = 0;
  //v5 = pMapInfo;
  //v6 = spawn;
  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
    v7 = pOutdoor->ddm.field_C_alert;
  else if (uCurrentlyLoadedLevelType == LEVEL_Outdoor)
    v7 = pIndoor->dlv.field_C_alert;
  else
    v7 = 0;
  if (v7)
    v8 = (spawn->uAttributes & 1) == 0;
  else
    v8 = (spawn->uAttributes & 1) == 1;
  if (v8)
    return;
    //result = (void *)(spawn->uIndex - 1);
  v56 = 1;
  switch (spawn->uIndex - 1)
  {
    case 0u:
        v9 = pMapInfo->uEncounterMonster1AtLeast;
        v10 = rand();
        v11 = pMapInfo->uEncounterMonster1AtMost;
        pTexture = pMapInfo->pEncounterMonster1Texture;
        v12 = v10 % (v11 - v9 + 1);
        v13 = pMapInfo->Dif_M1;
        goto LABEL_20;
    case 3u:
        pTexture = pMapInfo->pEncounterMonster1Texture;
        v44 = "%s A";
        goto LABEL_25;
    case 4u:
        pTexture = pMapInfo->pEncounterMonster2Texture;
        v44 = "%s A";
        goto LABEL_25;
    case 5u:
        pTexture = pMapInfo->pEncounterMonster3Texture;
        v44 = "%s A";
        goto LABEL_25;
    case 1u:
        v9 = pMapInfo->uEncounterMonster2AtLeast;
        v14 = rand();
        v15 = pMapInfo->uEncounterMonster2AtMost;
        pTexture = pMapInfo->pEncounterMonster2Texture;
        v12 = v14 % (v15 - v9 + 1);
        v13 = pMapInfo->Dif_M2;
        goto LABEL_20;
    case 6u:
        pTexture = pMapInfo->pEncounterMonster1Texture;
        v44 = "%s B";
        goto LABEL_25;
    case 7u:
        pTexture = pMapInfo->pEncounterMonster2Texture;
        v44 = "%s B";
        goto LABEL_25;
    case 8u:
        pTexture = pMapInfo->pEncounterMonster3Texture;
        v44 = "%s B";
        goto LABEL_25;
    case 2u:
        v9 = pMapInfo->uEncounterMonster3AtLeast;
        v16 = rand();
        v17 = pMapInfo->uEncounterMonster3AtMost;
        pTexture = pMapInfo->pEncounterMonster3Texture;
        v12 = v16 % (v17 - v9 + 1);
        v13 = pMapInfo->Dif_M3;
LABEL_20:
        v57 = v13;
        v56 = v9 + v12;
        strcpy(Source, pTexture);
        goto LABEL_26;
    case 9u:
        pTexture = pMapInfo->pEncounterMonster1Texture;
        v44 = "%s C";
        goto LABEL_25;
    case 0xAu:
        pTexture = pMapInfo->pEncounterMonster2Texture;
        v44 = "%s C";
        goto LABEL_25;
    case 0xBu:
        pTexture = pMapInfo->pEncounterMonster3Texture;
        v44 = "%s C";
LABEL_25:
        sprintf(Source, v44, pTexture);
LABEL_26:
        if (Source[0] == '0')
          return;
        v57 += a3;
        if ( v57 > 4 )
          v57 = 4;
        strcpy(Str2, Source);
        if ( a4 )
          v56 = a4;
        v18 = v56;
        if ( (signed int)(v56 + uNumActors) >= 500 )
          return;
        pSector = 0;
        pPosX = spawn->vPosition.x;
        a4 = spawn->vPosition.y;
        a3 = spawn->vPosition.z;
        if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
          pSector = pIndoor->GetSector(spawn->vPosition.x, spawn->vPosition.y, spawn->vPosition.z);
        v53 = 0;
        v52 = (((uCurrentlyLoadedLevelType != LEVEL_Outdoor) - 1) & 0x40) + 64;
        if ( v18 <= 0 )
          return;
        break;
      default:
        return;
  }
  for (uint i = v53; i < v56; ++i)
  {
      pMonster = &pActors[uNumActors];
      pActors[uNumActors].Reset();
      if ( v57 )
      {
        v23 = rand() % 100;
        v24 = 3;
        v25 = (unsigned __int16)word_4E8152[3 * v57];
        if ( v23 >= v25 )
        {
          if ( v23 < v25 + (unsigned __int16)word_4E8152[3 * v57 + 1] )
            v24 = 2;
        }
        else
        {
          v24 = 1;
        }
        if ( v24 == 1 )
        {
          pTexture = Source;
          v44 = "%s A";
        }
        else
        {
          if ( v24 == 2 )
          {
            pTexture = Source;
            v44 = "%s B";
          }
          else
          {
            if ( v24 != 3 )
              goto LABEL_58;
            pTexture = Source;
            v44 = "%s C";
          }
        }
        sprintf(Str2, v44, pTexture);
      }
      v50 = pMonsterList->GetMonsterIDByName(Str2);
      pTexture = Str2;
      if ( (signed __int16)v50 == -1 )
      {
        sprintf(Str, "Can't create random monster: '%s'! See MapStats.txt and Monsters.txt!", pTexture);
        MessageBoxA(nullptr, Str, nullptr, 0);
        ExitProcess(0);
      }
      v27 = &pMonsterList->pMonsters[(signed __int16)v50];
      v28 = pMonsterStats->FindMonsterByTextureName(pTexture);
      if ( !v28 )
        v28 = 1;
      Src = &pMonsterStats->pInfos[v28];
      strcpy(pMonster->pActorName, Src->pName);
      pMonster->sCurrentHP = Src->uHP;
      assert(sizeof(MonsterInfo) == 88);
      memcpy(&pMonster->pMonsterInfo, Src, sizeof(MonsterInfo));
      pMonster->word_000086_some_monster_id = v50 + 1;
      pMonster->uActorRadius = v27->uMonsterRadius;
      pMonster->uActorHeight = v27->uMonsterHeight;
      pMonster->uMovementSpeed = v27->uMovementSpeed;
      pMonster->vInitialPosition.x = spawn->vPosition.x;
      pMonster->vPosition.x = spawn->vPosition.x;
      pMonster->uTetherDistance = 256;
      pMonster->vInitialPosition.y = a4;
      pMonster->vPosition.y = a4;
      pTexture = 0;
      pMonster->vInitialPosition.z = a3;
      pMonster->vPosition.z = a3;
      pMonster->uSectorID = pSector;
      pMonster->uGroup = spawn->uGroup;
      pMonster->PrepareSprites((char)pTexture);
      pMonster->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Friendly;
      v32 = rand();
      v33 = v32 % 2048;
      v34 = stru_5C6E00->Cos(v32 % 2048);
      a4 = v34;
      a3 = (unsigned __int64)(v34 * (signed __int64)v52) >> 16;
      pPosX = a3 + spawn->vPosition.x;
      v35 = stru_5C6E00->Sin(v33);
      a4 = v35;
      a3 = (unsigned __int64)(v35 * (signed __int64)v52) >> 16;
      a4 = a3 + spawn->vPosition.y;
      v36 = spawn->vPosition.z;
      a3 = spawn->vPosition.z;
      if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
        goto LABEL_55;
      v37 = pIndoor->GetSector(pPosX, a4, v36);
      if ( v37 == pSector )
      {
        v38 = BLV_GetFloorLevel(pPosX, a4, a3, v37, &uFaceID);
        v39 = v38;
        if ( v38 != -30000 )
        {
          if ( abs(v38 - a3) <= 1024 )
          {
            a3 = v39;
LABEL_55:
            if ( a5 )
              pMonster->uAttributes |= 0x080000;
            ++uNumActors;
            goto LABEL_58;
          }
        }
      }
LABEL_58:
      ;
      //v53 = (char *)v53 + 1;
      //result = v53;
    }
    //while ( (signed int)v53 < v56 );
}

//----- (0044FA4C) --------------------------------------------------------
signed int __fastcall sub_44FA4C_spawn_light_elemental(int a1, int a2, int a3)
{
  signed int v3; // ecx@6
  Actor *v4; // edx@7
  signed int result; // eax@13
  Actor *v6; // esi@16
  char *v7; // ebx@16
  MonsterDesc *v8; // edi@16
  unsigned __int16 v9; // ax@16
  int v10; // ebx@16
  //int v11; // edi@16
  //int v12; // eax@16
  //int v13; // ecx@16
  //int v14; // ebx@16
  const char *v15; // [sp-4h] [bp-24h]@2
  //unsigned __int16 v16; // [sp+0h] [bp-20h]@1
  //int v17; // [sp+4h] [bp-1Ch]@1
  unsigned int uFaceID; // [sp+8h] [bp-18h]@16
  int v19; // [sp+Ch] [bp-14h]@16
  size_t v20; // [sp+10h] [bp-10h]@6
  int v21; // [sp+14h] [bp-Ch]@14
  //int v22; // [sp+18h] [bp-8h]@14
  unsigned int v23; // [sp+1Ch] [bp-4h]@6

  //v16 = a2;
  //v17 = a1;
  if ( a2 == 4 )
  {
    v15 = "Elemental Light C";
  }
  else if ( a2 == 3 )
      v15 = "Elemental Light B";
    else
      v15 = "Elemental Light A";

  v23 = pMonsterList->GetMonsterIDByName(v15);
  v3 = 0;
  v20 = uNumActors;
  if ( (signed int)uNumActors > 0 )
  {
    v4 = pActors.data();//[0].uAIState;
    while ( v4->uAIState != Removed )
    {
      ++v3; 
      ++v4;
      if ( v3 >= (signed int)uNumActors )
        break;
    }
	if( v3 < (signed int)uNumActors )
		v20 = v3;
  }
  if ( v20 != uNumActors || (result = uNumActors + 1, (signed int)(uNumActors + 1) < 500) )
  {
    v21 = 0;
    //v22 = pParty->vPosition.z;
    if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
      v21 = pIndoor->GetSector(pParty->vPosition.x, pParty->vPosition.y, pParty->vPosition.z);
    v6 = &pActors[v20];
    v7 = (char *)&pMonsterStats->pInfos[v23 + 1];
    v19 = (((uCurrentlyLoadedLevelType != LEVEL_Outdoor) - 1) & 0x40) + 64;
    v6->Reset();
    v8 = &pMonsterList->pMonsters[v23];
    strcpy(v6->pActorName, *(const char **)v7);
    v6->sCurrentHP = *((short *)v7 + 32);
    memcpy(&v6->pMonsterInfo, v7, 0x58u);
    v6->word_000086_some_monster_id = v23 + 1;
    v6->uActorRadius = v8->uMonsterRadius;
    v6->uActorHeight = v8->uMonsterHeight;
    v9 = v8->uMovementSpeed;
    v6->pMonsterInfo.uTreasureDiceRolls = 0;
    v6->pMonsterInfo.uTreasureType = 0;
    v6->pMonsterInfo.uExp = 0;
    v6->uMovementSpeed = v9;
    v10 = rand() % 2048;
    //v11 = pParty->vPosition.x + fixpoint_sub0(stru_5C6E00->Cos(v10), v19);
    uFaceID = stru_5C6E00->Sin(v10);
    //v12 = pParty->vPosition.y;
    //v13 = fixpoint_sub0(uFaceID, v19);
    //v14 = pParty->vPosition.y + fixpoint_sub0(uFaceID, v19);
    //LOWORD(v12) = v22;
    v6->vInitialPosition.x = pParty->vPosition.x + fixpoint_sub0(stru_5C6E00->Cos(v10), v19);
    v6->vPosition.x = v6->vInitialPosition.x;
    v6->vInitialPosition.y = pParty->vPosition.y + fixpoint_sub0(uFaceID, v19);
    v6->vPosition.y = v6->vInitialPosition.y;
    v6->vInitialPosition.z = pParty->vPosition.z;
    v6->vPosition.z = v6->vInitialPosition.z;
    //LOWORD(v12) = v21;
    v6->uTetherDistance = 256;
    v6->uSectorID = v21;
    v6->PrepareSprites(0);
    v6->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Friendly;
    v6->uAlly = 9999;
    v6->uGroup = 0;
    v6->uCurrentActionTime = 0;
    v6->uAIState = Summoned;
    v6->uCurrentActionLength = 256;
    v6->UpdateAnimation();
    if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor
      || (result = pIndoor->GetSector(v6->vPosition.x, v6->vPosition.y, v6->vPosition.z),
          result == v21)
      && (result = BLV_GetFloorLevel(v6->vPosition.x, v6->vPosition.y, v6->vPosition.z, result, &uFaceID), result != -30000)
      && (result = abs(result - pParty->vPosition.z), result <= 1024) )
    {
      if ( v20 == uNumActors )
        ++uNumActors;
      v6->uSummonerID = PID(OBJECT_Player, a1);
      result = v6->pActorBuffs[2].Apply(pParty->uTimePlayed + (a3 * 128) / 30.0f,
                 a2,
                 a1,
                 0,
                 0);
    }
  }
  return result;
}

//----- (0044FFD8) --------------------------------------------------------
int MapInfo::SpawnRandomTreasure(SpawnPointMM7 *a2)
{
  //MapInfo *v2; // ebx@1
  //SpawnPointMM7 *v3; // esi@1
  //int v4; // eax@1
  int v5; // edx@1
  int v6; // eax@1
  int v7; // ecx@1
  int v8; // ebx@1
  int v9; // eax@1
  signed int v10; // ebx@1
  signed int result; // eax@1
  signed __int64 v12; // qtt@1
  int v13; // ebx@1
  int v14; // edx@10
  signed int v15; // ebx@20
  unsigned __int16 v16; // dx@20
  char *v17; // ecx@21
  unsigned __int16 v18; // ax@24
  int v19; // ST0C_4@27
  int v20; // ST08_4@27
  int v21; // ST04_4@27
  int v22; // eax@27
  signed int v23; // ebx@29
  unsigned __int16 v24; // dx@29
  char *v25; // ecx@30
  unsigned __int16 v26; // ax@33
  //int v27; // ecx@35
  //int v28; // eax@35
  //int v29; // esi@35
  //__int16 v30; // ax@35
  SpriteObject a1a; // [sp+Ch] [bp-7Ch]@1
  //int v32; // [sp+7Ch] [bp-Ch]@1
  //int v33; // [sp+80h] [bp-8h]@1
  int v34; // [sp+84h] [bp-4h]@1

  //auto a1 = this;
  //v2 = a1;
  //v3 = a2;
  //v4 = rand();
  v34 = 0;
  v5 = rand() % 100;
 // v6 = 2 * (v2->Treasure_prob + 7 * v3->uIndex) - 14;
  v7 = (unsigned __int8)byte_4E8168[a2->uIndex - 1][2 * Treasure_prob];
  v8 = (unsigned __int8)byte_4E8168[a2->uIndex - 1][2 * Treasure_prob + 1];
  //v32 = v5;
  //v33 = v7;
  v9 = rand();
  v10 = v8 - v7 + 1;
  v12 = v9;
  result = v9 / v10;
  v13 = v7 + (unsigned __int64)(v12 % v10);
  if ( v13 < 7 )
  {
    if ( v5 < 20 )
      return result;
    if ( v5 >= 60 )
    {
      v19 = a2->vPosition.z;
      v20 = a2->vPosition.y;
      v21 = a2->vPosition.x;
      v22 = rand();
      return sub_450521_ProllyDropItemAt(v13, v22 % 27 + 20, v21, v20, v19, 0);
    }
    if ( a2->uIndex == 1 )
    {
      v14 = rand() % 51 + 50;
    }
    else
    {
      if ( a2->uIndex != 2 )
      {
        if ( a2->uIndex == 3 )
        {
          v14 = rand() % 301 + 200;
        }
        else
        {
          if ( a2->uIndex != 4 )
          {
            if ( a2->uIndex == 5 )
            {
              v14 = rand() % 1001 + 1000;
            }
            else
            {
              if ( a2->uIndex != 6 )
              {
LABEL_20:
                v15 = 0;
                v16 = pItemsTable->pItems[a1a.stru_24.uItemID].uSpriteID;
                a1a.uType = pItemsTable->pItems[a1a.stru_24.uItemID].uSpriteID;
                if ( (signed int)pObjectList->uNumObjects <= 0 )
                {
LABEL_24:
                  v18 = 0;
                }
                else
                {
                  v17 = (char *)&pObjectList->pObjects->uObjectID;
                  while ( v16 != *(short *)v17 )
                  {
                    ++v15;
                    v17 += 56;
                    if ( v15 >= (signed int)pObjectList->uNumObjects )
                      goto LABEL_24;
                  }
                  v18 = v15;
                }
                a1a.stru_24.SetIdentified();
                a1a.uObjectDescID = v18;
                a1a.stru_24.uSpecEnchantmentType = v34;
                goto LABEL_35;
              }
              v14 = rand() % 3001 + 2000;
            }
            a1a.stru_24.uItemID = 199;
LABEL_19:
            v34 = v14;
            goto LABEL_20;
          }
          v14 = rand() % 501 + 500;
        }
        a1a.stru_24.uItemID = 198;
        goto LABEL_19;
      }
      v14 = rand() % 101 + 100;
    }
    a1a.stru_24.uItemID = 197;
    goto LABEL_19;
  }
  result = a1a.stru_24.GenerateArtifact();
  if ( !result )
    return result;
  v23 = 0;
  v24 = pItemsTable->pItems[a1a.stru_24.uItemID].uSpriteID;
  a1a.uType = pItemsTable->pItems[a1a.stru_24.uItemID].uSpriteID;
  if ( (signed int)pObjectList->uNumObjects <= 0 )
  {
LABEL_33:
    v26 = 0;
  }
  else
  {
    v25 = (char *)&pObjectList->pObjects->uObjectID;
    while ( v24 != *(short *)v25 )
    {
      ++v23;
      v25 += 56;
      if ( v23 >= (signed int)pObjectList->uNumObjects )
        goto LABEL_33;
    }
    v26 = v23;
  }
  a1a.uObjectDescID = v26;
  a1a.stru_24.Reset();

LABEL_35:
  a1a.vPosition.y = a2->vPosition.y;
  a1a.uAttributes = 0;
  a1a.uSoundID = 0;
  a1a.uFacing = 0;
  a1a.vPosition.z = a2->vPosition.z;
  a1a.vPosition.x = a2->vPosition.x;
  a1a.spell_skill = 0;
  a1a.spell_level = 0;
  a1a.spell_id = 0;
  a1a.spell_target_pid = 0;
  a1a.spell_caster_pid = 0;
  a1a.uSpriteFrameID = 0;
  a1a.uSectorID = pIndoor->GetSector(a2->vPosition.x, a2->vPosition.y, a2->vPosition.z);;
  return a1a.Create(0, 0, 0, 0);
}

//----- (00450521) --------------------------------------------------------
signed int __fastcall sub_450521_ProllyDropItemAt(int ecx0, signed int a2, int a3, int a4, int a5, unsigned __int16 a6)
{
  int v6; // edi@1
  int v7; // esi@1
  signed int v8; // edi@1
  unsigned __int16 v9; // cx@1
  char *v10; // edx@2
  unsigned __int16 v11; // ax@5
  SpriteObject a1; // [sp+8h] [bp-70h]@1

  v6 = ecx0;
  v7 = a2;
  pItemsTable->GenerateItem(v6, v7, &a1.stru_24);
  v8 = 0;
  v9 = pItemsTable->pItems[a1.stru_24.uItemID].uSpriteID;
  a1.uType = pItemsTable->pItems[a1.stru_24.uItemID].uSpriteID;
  if ( (signed int)pObjectList->uNumObjects <= 0 )
  {
LABEL_5:
    v11 = 0;
  }
  else
  {
    v10 = (char *)&pObjectList->pObjects->uObjectID;
    while ( v9 != *(short *)v10 )
    {
      ++v8;
      v10 += 56;
      if ( v8 >= (signed int)pObjectList->uNumObjects )
        goto LABEL_5;
    }
    v11 = v8;
  }
  a1.uObjectDescID = v11;
  a1.vPosition.y = a4;
  a1.vPosition.x = a3;
  a1.vPosition.z = a5;
  a1.uFacing = a6;
  a1.uAttributes = 0;
  a1.uSectorID = pIndoor->GetSector(a3, a4, a5);
  a1.uSpriteFrameID = 0;
  return a1.Create(0, 0, 0, 0);
}

//----- (0045063B) --------------------------------------------------------
int __fastcall sub_45063B(MapInfo *a1, int a2)
{
  signed int v2; // edi@1
  Actor *v3; // esi@2
  signed __int64 v4; // qax@3
  int result; // eax@8
  int v6; // edi@11
  int v7; // ebx@11
  int v8; // edi@11
  int v9; // ebx@12
  int v10; // eax@12
  char v11; // zf@16
  int v12; // edi@20
  int v13; // eax@20
  int v14; // ebx@20
  int v15; // eax@20
  int v16; // eax@20
  int v17; // eax@20
  int v18; // eax@21
  SpawnPointMM7 v19; // [sp+Ch] [bp-38h]@1
  int v20; // [sp+24h] [bp-20h]@11
  MapInfo *v21; // [sp+28h] [bp-1Ch]@1
  int v22; // [sp+2Ch] [bp-18h]@3
  int v23; // [sp+30h] [bp-14h]@11
  int v24; // [sp+34h] [bp-10h]@1
  unsigned int uFaceID; // [sp+38h] [bp-Ch]@10
  int v26; // [sp+3Ch] [bp-8h]@11
  int v27; // [sp+40h] [bp-4h]@11

  v21 = a1;
  v24 = a2;
  v2 = 0;
  if ( (signed int)uNumActors <= 0 )
    goto LABEL_8;
  v3 = pActors.data();
  while ( 1 )
  {
    v22 = v3->pMonsterInfo.uID - 1;
    v4 = (signed __int64)((double)v22 * 0.3333333333333333);
    if ( (int)v4 != 40 )
    {
      if ( (int)v4 != 41 && (int)v4 != 44 && v3->CanAct() )
        break;
    }
    ++v2;
    ++v3;
    if ( v2 >= (signed int)uNumActors )
      goto LABEL_8;
  }
  if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
  {
    v22 = 0;
    uFaceID = 0;
    while ( 1 )
    {
      ++uFaceID;
      v6 = rand() % 1024 + 512;
      v7 = rand() % (signed int)stru_5C6E00->uIntegerDoublePi;
      v20 = stru_5C6E00->Cos(v7);
      v23 = (unsigned __int64)(v20 * (signed __int64)v6) >> 16;
      v19.vPosition.x = pParty->vPosition.x + v23;
      v20 = stru_5C6E00->Sin(v7);
      v23 = (unsigned __int64)(v20 * (signed __int64)v6) >> 16;
      v8 = 0;
      v19.uIndex = v24;
      v19.vPosition.y = v23 + pParty->vPosition.y;
      v19.vPosition.z = pParty->vPosition.z;
      v26 = 0;
      v27 = 0;
      v19.vPosition.z = ODM_GetFloorLevel(
                          v19.vPosition.x,
                          v23 + pParty->vPosition.y,
                          pParty->vPosition.z,
                          0,
                          &v26,
                          &v27,
                          0);
      v23 = 0;
      if ( (signed int)pOutdoor->uNumBModels > 0 )
      {
        while ( 1 )
        {
          v9 = abs(v19.vPosition.y - pOutdoor->pBModels[v8].vBoundingCenter.y);
          v10 = abs(v19.vPosition.x - pOutdoor->pBModels[v8].vBoundingCenter.x);
          if ( int_get_vector_length(v10, v9, 0) < pOutdoor->pBModels[v8].sBoundingRadius + 256 )
            break;
          ++v23;
          ++v8;
          if ( v23 >= (signed int)pOutdoor->uNumBModels )
            goto LABEL_16;
        }
        v22 = 1;
      }
LABEL_16:
      v11 = uFaceID == 100;
      if ( uFaceID >= 100 )
        break;
      if ( v22 )
      {
        v11 = uFaceID == 100;
        break;
      }
    }
  }
  else
  {
    v26 = 0;
    v22 = pIndoor->GetSector(pParty->vPosition.x, pParty->vPosition.y, pParty->vPosition.z);
    do
    {
      ++v26;
      v12 = rand() % 512 + 256;
      v13 = rand();
      v14 = v13 % (signed int)stru_5C6E00->uIntegerDoublePi;
      v15 = stru_5C6E00->Cos(v13 % (signed int)stru_5C6E00->uIntegerDoublePi);
      v20 = v15;
      v23 = (unsigned __int64)(v15 * (signed __int64)v12) >> 16;
      v19.vPosition.x = pParty->vPosition.x + v23;
      v16 = stru_5C6E00->Sin(v13 % (signed int)stru_5C6E00->uIntegerDoublePi);
      v20 = v16;
      v23 = (unsigned __int64)(v16 * (signed __int64)v12) >> 16;
      v19.vPosition.y = v23 + pParty->vPosition.y;
      v19.vPosition.z = pParty->vPosition.z;
      v19.uIndex = v24;
      v17 = pIndoor->GetSector(v19.vPosition.x, v23 + pParty->vPosition.y, pParty->vPosition.z);
      if ( v17 == v22 )
      {
        v18 = BLV_GetFloorLevel(v19.vPosition.x, v19.vPosition.y, v19.vPosition.z, v17, &uFaceID);
        v19.vPosition.z = v18;
        if ( v18 != -30000 )
        {
          if ( abs(v18 - pParty->vPosition.z) <= 1024 )
            break;
        }
      }
    }
    while ( v26 < 100 );
    v11 = v26 == 100;
  }
  if ( v11 )
  {
LABEL_8:
    result = 0;
  }
  else
  {
    SpawnEncounter(v21, &v19, 0, 0, 1);
    result = v24;
  }
  return result;
}

//----- (00450929) --------------------------------------------------------
int LevelDecoration::GetGlobalEvent()
{
  LevelDecoration *v1; // esi@1
  signed int v2; // eax@1
  int v3; // eax@5
  int v4; // eax@6
  int v5; // eax@7
  int v6; // eax@8
  int v7; // eax@9
  int result; // eax@14
  int v9; // eax@18
  int v10; // eax@19
  int v11; // eax@20
  int v12; // eax@21
  int v13; // eax@22

  v1 = this;
  rand();
  v2 = v1->uDecorationDescID;
  if ( v2 > 208 )
  {
    switch ( v2 )
    {
      case 209:
        result = rand() % 7 + 183;
        break;
      case 210:
        result = 150;
        break;
      case 211:
        result = 151;
        break;
      case 212:
        result = 152;
        break;
      case 213:
        result = 153;
        break;
      case 214:
        result = 154;
        break;
      case 215:
        result = 155;
        break;
      case 216:
        result = 156;
        break;
      case 217:
        result = 157;
        break;
      case 218:
        result = 158;
        break;
      case 219:
        result = 159;
        break;
      case 220:
        result = 160;
        break;
      case 221:
        result = 161;
        break;
      default:
        goto LABEL_45;
    }
  }
  else
  {
    if ( v2 == 208 )
    {
      result = rand() % 7 + 176;
    }
    else
    {
      if ( v2 > 24 )
      {
        v9 = v2 - 34;
        if ( !v9 )
          return rand() % 6 + 4;
        v10 = v9 - 150;
        if ( !v10 )
          return 33;
        v11 = v10 - 3;
        if ( !v11 || (v12 = v11 - 3) == 0 )
          return 37;
        v13 = v12 - 16;
        if ( !v13 )
          return rand() % 7 + 162;
        if ( v13 == 1 )
          return rand() % 7 + 169;
      }
      else
      {
        if ( v2 == 24 )
          return 36;
        v3 = v2 - 4;
        if ( !v3 )
          return 16;
        v4 = v3 - 1;
        if ( !v4 )
          return 32;
        v5 = v4 - 1;
        if ( !v5 )
          return rand() % 4 + 12;
        v6 = v5 - 5;
        if ( !v6 )
          return 34;
        v7 = v6 - 2;
        if ( !v7 )
          return 17;
        if ( v7 == 1 )
          return 18;
      }
LABEL_45:
      result = 0;
    }
  }
  return result;
}

//----- (00450AAA) --------------------------------------------------------
void RespawnGlobalDecorations()
{
  memset(stru_5E4C90._decor_events, 0, 125);

  uint decorEventIdx = 0;
  for (uint i = 0; i < uNumLevelDecorations; ++i)
  {
    auto decor = &pLevelDecorations[i];

    if (!decor->field_16_event_id)
    {
      if (decor->IsInteractive())
      {
        if (decorEventIdx < 124)
        {
          decor->_idx_in_stru123 = decorEventIdx + 75;
          stru_5E4C90._decor_events[decorEventIdx++] = decor->GetGlobalEvent();
        }
      }
    }
  }
}

//----- (00450B0A) --------------------------------------------------------
bool __fastcall SpawnActor(unsigned int uMonsterID)
{
  unsigned int v1; // ebx@1
  bool result; // eax@2
  MonsterDesc *v3; // esi@5
  MonsterInfo *v4; // edi@5
  Vec3_int_ v5; // ST08_12@5
  unsigned int v6; // ecx@5
  Actor *v7; // eax@7
  Actor actor; // [sp+4h] [bp-350h]@5
  Vec3_int_ pOut; // [sp+348h] [bp-Ch]@5

  v1 = uMonsterID;
  if ( uNumActors == 499 )
  {
    result = 0;
  }
  else
  {
    if ( (signed int)uMonsterID >= (signed int)pMonsterList->uNumMonsters )
      v1 = 0;
    v3 = &pMonsterList->pMonsters[v1];
    v4 = &pMonsterStats->pInfos[v1 + 1];
    memset(&actor, 0, 0x344u);
    strcpy(actor.pActorName, v4->pName);
    actor.sCurrentHP = LOWORD(v4->uHP);
    memcpy(&actor.pMonsterInfo, &pMonsterStats->pInfos[v1 + 1], 0x58u);
    actor.word_000086_some_monster_id = v1 + 1;
    actor.uActorRadius = v3->uMonsterRadius;
    actor.uActorHeight = v3->uMonsterHeight;
    actor.uMovementSpeed = v3->uMovementSpeed;
    v5 = pParty->vPosition;
    Vec3_int_::Rotate(200, pParty->sRotationY, 0, v5, &pOut.x, &pOut.z, &pOut.y);
    actor.vInitialPosition.x = pOut.x;
    actor.vPosition.x = pOut.x;
    actor.uTetherDistance = 256;
    actor.vInitialPosition.y = LOWORD(pOut.z);
    actor.vPosition.y = LOWORD(pOut.z);
    actor.vInitialPosition.z = LOWORD(pOut.y);
    actor.vPosition.z = LOWORD(pOut.y);
    pSprites_LOD->DeleteSomeSprites();
    pPaletteManager->ResetNonTestLocked();
    v6 = uNumActors - 1;
    if ( dword_5C6DF8 == 1 )
    {
      dword_5C6DF8 = 0;
      v6 = uNumActors++;
    }
    v7 = &pActors[v6];
    memcpy(v7, &actor, 0x344u);
    v7->PrepareSprites(1);
    result = 1;
  }
  return result;
}
// 5C6DF8: using guessed type int dword_5C6DF8;

//----- (00450DA3) --------------------------------------------------------
int __cdecl GetAlertStatus()
{
  int result; // eax@2

  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
    result = pOutdoor->ddm.field_C_alert;
  else
    result = uCurrentlyLoadedLevelType == LEVEL_Outdoor ? pIndoor->dlv.field_C_alert : 0;
  return result;
}

//----- (00450DDE) --------------------------------------------------------
stru350 *stru350::_450DDE()
{
  _450DF1(&stru_4E82A4, &stru_4E82A4);
  return this;
}

//----- (00450DF1) --------------------------------------------------------
bool stru350::_450DF1(const stru355 *p1, const stru355 *p2)
{
  //stru350 *v3; // esi@1
  //void *result; // eax@1
  unsigned int v5; // ecx@2
  int v6; // edi@2
  int v7; // edx@2
  unsigned int v8; // ecx@8
  int v9; // edi@8
  int v10; // edx@8
  int v11; // ecx@12
  int v12; // edi@12
  unsigned int v13; // ecx@12
  int v14; // edx@12
  int v15; // ecx@16
  unsigned int v16; // edx@16
  int v17; // ecx@16
  int v18; // edi@16
  char v19; // zf@20
  unsigned int v20; // ecx@21
  int v21; // edi@21
  int v22; // edx@21
  unsigned int v23; // ecx@27
  int v24; // edi@27
  int v25; // edx@27
  int v26; // ecx@31
  int v27; // edi@31
  unsigned int v28; // ecx@31
  int v29; // edx@31
  int v30; // ebx@35
  int v31; // ecx@35
  int v32; // edi@35
  int v33; // edx@35
  unsigned int i; // ecx@35
  int v35; // ecx@39
  unsigned int v36; // edx@39
  int v37; // ecx@39
  int v38; // ebx@39

  //v3 = this;
  memcpy(&field_0, p1, sizeof(stru355));
  memcpy(&field_20, p2, sizeof(stru355));
  //result = memcpy(&v3->field_20, p2, 0x20u);
  //LOBYTE(result) = 1;
  if (field_0.field_4 & 1)
  {
    v5 = field_0.field_1C;
    v6 = 0;
    v7 = 0;
    while ( !(v5 & 1) )
    {
      ++v6;
      v5 >>= 1;
    }
    do
    {
      v5 >>= 1;
      ++v7;
    }
    while ( v5 & 1 );
    field_40 = 32 - v7 - v6;
  }
  else
  {
    field_40 = 0;
  }
  v8 = field_0.field_10;
  v9 = 0;
  v10 = 0;
  while ( !(v8 & 1) )
  {
    ++v9;
    v8 >>= 1;
  }
  do
  {
    v8 >>= 1;
    ++v10;
  }
  while ( v8 & 1 );
  v11 = 24 - v10 - v9;
  v12 = 0;
  field_48 = v11;
  v13 = field_0.field_14;
  v14 = 0;
  while ( !(v13 & 1) )
  {
    ++v12;
    v13 >>= 1;
  }
  do
  {
    v13 >>= 1;
    ++v14;
  }
  while ( v13 & 1 );
  v15 = 16 - v14;
  v16 = field_0.field_18;
  field_50 = v15 - v12;
  v17 = 0;
  v18 = 0;
  while ( !(v16 & 1) )
  {
    ++v17;
    v16 >>= 1;
  }
  do
  {
    v16 >>= 1;
    ++v18;
  }
  while ( v16 & 1 );
  v19 = (field_20.field_4 & 1) == 0;
  field_58 = v17 - v18 + 8;
  if ( v19 )
  {
    field_44 = 0;
  }
  else
  {
    v20 = field_20.field_1C;
    v21 = 0;
    v22 = 0;
    while ( !(v20 & 1) )
    {
      ++v21;
      v20 >>= 1;
    }
    do
    {
      v20 >>= 1;
      ++v22;
    }
    while ( v20 & 1 );
    field_44 = 32 - v22 - v21;
  }
  v23 = field_20.field_10;
  v24 = 0;
  v25 = 0;
  while ( !(v23 & 1) )
  {
    ++v24;
    v23 >>= 1;
  }
  do
  {
    v23 >>= 1;
    ++v25;
  }
  while ( v23 & 1 );
  v26 = 24 - v25 - v24;
  v27 = 0;
  field_4C = v26;
  v28 = field_20.field_14;
  v29 = 0;
  while ( !(v28 & 1) )
  {
    ++v27;
    v28 >>= 1;
  }
  do
  {
    v28 >>= 1;
    ++v29;
  }
  while ( v28 & 1 );
  v30 = 0;
  v31 = 16 - v29 - v27;
  v32 = field_20.field_18;
  field_54 = v31;
  v33 = 0;
  for ( i = v32; !(i & 1); i >>= 1 )
    ++v30;
  do
  {
    i >>= 1;
    ++v33;
  }
  while ( i & 1 );
  v35 = 32 - v33;
  v36 = v32;
  field_5C = v35 - v30;
  v37 = 0;
  v38 = 0;
  while ( !(v36 & 1) )
  {
    ++v37;
    v36 >>= 1;
  }
  do
  {
    v36 >>= 1;
    ++v38;
  }
  while ( v36 & 1 );
  field_5C = v37 - v38 + 8;
  return true;
}

//----- (00450F55) --------------------------------------------------------
unsigned int stru350::_450F55(int a2)
{
  int v2 = a2 & stru_4E82A4.field_1C;
  if (field_20.field_4 & 1)
    v2 = (unsigned int)v2 >> this->field_44;
  return v2 & field_20.field_1C |
         field_20.field_10 & ((a2 & (unsigned int)stru_4E82A4.field_10) >> field_4C) |
         field_20.field_14 & ((a2 & (unsigned int)stru_4E82A4.field_14) >> field_54) |
         field_20.field_18 & ((a2 & (unsigned int)stru_4E82A4.field_18) >> field_5C);
}

//----- (00450FB1) --------------------------------------------------------
int stru350::_450FB1(int a2)
{
  int v2 = 0;
  int v4 = field_0.field_4 & 1;
  if ( v4 )
    v2 = a2 & field_0.field_1C;
  if ( v4 )
    v2 <<= field_40;
  return v2 | ((a2 & field_0.field_10) << field_48) | ((a2 & field_0.field_14) << field_50) | ((a2 & field_0.field_18) << field_58);
}

//----- (00452442) --------------------------------------------------------
unsigned int __fastcall sub_452442(unsigned __int16 a1, unsigned __int16 a2, int a3, int a4)
{
  int v4; // ebx@0
  __int16 v5; // ST14_2@1
  __int16 v6; // dx@1
  int v7; // ecx@1
  __int16 v8; // ST10_2@1
  int v9; // edi@1
  unsigned __int16 v10; // dh@1@1
  int v11; // ebx@1
  int v12; // ebx@1
  __int16 a3a; // [sp+1Ch] [bp+8h]@1

  v5 = a2 >> 2;
  v6 = (unsigned __int16)a4 >> 2;
  v8 = a1 >> 2;
  a3a = (unsigned __int16)a3 >> 2;
  LOWORD(v7) = a3a;
  v9 = v7;
  LOWORD(v4) = ((unsigned __int16)a4 >> 2) & 0xE0;
  LOWORD(v7) = a3a & 0xE0;
  LOWORD(v9) = v9 & 0x1C00;
  v11 = v7 + v4;
  LOWORD(v7) = v5 & 0xE0;
  v12 = v7 + v11;
  LOWORD(v7) = v8 & 0xE0;
  return (PID_TYPE(v8) + PID_TYPE(v5) + PID_TYPE(a3a) + PID_TYPE(v6)) | (v7 + v12) | ((v8 & 0x1C00)
                                                                    + (v5 & 0x1C00)
                                                                    + v9
                                                                    + (__PAIR__(v10, (unsigned __int16)a4 >> 2) & 0x1C00));
}

//----- (0045281E) --------------------------------------------------------
//    Calculates atan2(y/x)
// return value: angle in integer format (multiplier of Pi/1024)  
unsigned int stru193_math::Atan2(int x, int y)
{
  signed int quadrant;
  __int64 dividend;
  int quotient;
  int lowIdx;
  int highIdx;
  int angle;

  auto X = x;
  auto Y = y;

  if ( abs(X) < 65536 )
  {
    if ( (abs(Y) >> 15) >= abs(X) )
      X = 0;
  }

  if ( !X )
  {
    if ( Y > 0 )
    {
      return uIntegerHalfPi;   //Pi/2
    }
    else
    {
      return uIntegerHalfPi + uIntegerPi; //3*(Pi/2)
    }
  }

  if ( Y )
  {
    if ( X < 0 )
    {
      X = -X;
      if ( Y > 0 )
      {
        quadrant = 4;        
      }
      else
      {
        quadrant = 3;        
      }      
    }
    else
    {
      if ( Y > 0 )
      {
        quadrant = 1;       
      }
      else
      {
        quadrant = 2;
      }      
    }

    if ( Y < 0 )
      Y = -Y;

    LODWORD(dividend) = Y << 16;
    HIDWORD(dividend) = Y >> 16;
    quotient = dividend / X;        

    //looks like binary search
    {
      int i;
      highIdx = uIntegerHalfPi;
      lowIdx = 0;

      for (i = 0; i < 6; ++i)
      {        
        if (quotient <= pTanTable[(lowIdx + highIdx) / 2])      
          highIdx = (lowIdx + highIdx) / 2;
        else
          lowIdx = (lowIdx + highIdx) / 2;    
      }
    }

    angle = lowIdx + 1;
    while ( angle < (highIdx - 1) && quotient >= pTanTable[angle] )
      ++angle;

    switch (quadrant)
    {
    case 1: //X > 0, Y > 0
      return angle;        

    case 2: //X > 0, Y < 0
      return uIntegerDoublePi - angle;   //2*Pi - angle

    case 3: //X > 0, Y < 0
      return uIntegerPi + angle;        //Pi + angle 

    case 4: //X < 0, Y > 0
      return uIntegerPi - angle;        //Pi - angle  
    }

    //should newer get here
    return 0;
  }

  if ( X < 0 )    //Y == 0, X < 0
    return uIntegerPi;  

  return 0;
}

//----- (00452969) --------------------------------------------------------
stru193_math::stru193_math()
{
  stru193_math *v1; // esi@1
  char *v2; // edi@1
  double v3; // ST18_8@2
  signed int v4; // edx@3
  int v5; // eax@4
  int v6; // ecx@4
  signed int v7; // [sp+20h] [bp-4h]@1

  v1 = this;
  this->uIntegerDoublePi = 2048;
  this->uIntegerPi = 1024;
  this->uIntegerHalfPi = 512;
  this->uDoublePiMask = 2047;
  this->uPiMask = 1023;
  this->uHalfPiMask = 511;
  this->pTanTable[0] = 0;
  this->pCosTable[0] = 65536;
  this->pInvCosTable[0] = 65536;
  v7 = 1;
  v2 = (char *)&this->pInvCosTable[1];
  do
  {
    v3 = (double)v7 * 3.141592653589793 * 0.0009765625;
    *((int *)v2 - 1040) = (signed __int64)(tan(v3) * (double)v1->pCosTable[0] + 0.5);
    *((int *)v2 - 520) = (signed __int64)(cos(v3) * (double)v1->pCosTable[0] + 0.5);
    ++v7;
    *(int *)v2 = (signed __int64)(1.0 / cos(v3) * (double)v1->pCosTable[0] + 0.5);
    v2 += 4;
  }
  while ( v7 < (signed int)v1->uIntegerHalfPi );
  v4 = v1->uIntegerHalfPi;
  if ( v4 < 520 )
  {
    v5 = (int)&v1->pCosTable[v4];
    v6 = 520 - v4;
    do
    {
      *(int *)v5 = 0;
      *(int *)(v5 + 2080) = 0xEFFFFFFFu;
      *(int *)(v5 - 2080) = 0xEFFFFFFFu;
      v5 += 4;
      --v6;
    }
    while ( v6 );
  }
}

//----- (00452A9E) --------------------------------------------------------
int integer_sqrt(int val)
{
  signed int result; // eax@2
  unsigned int v2; // edx@3
  unsigned int v3; // edi@3
  //signed int v4; // ebx@3
  int v5; // esi@4

  if (val < 1)
    return val;


    v2 = 0;
    v3 = val;
    result = 0;
    //v4 = 16;
  for (uint i = 0; i < 16; ++i)
  {
      result *= 2;
      v2 = (v3 >> 30) | 4 * v2;
      v5 = 2 * result + 1;
      v3 *= 4;
      if ( v2 >= v5 )
      {
        ++result;
        v2 -= v5;
      }
      //--v4;
  }
    //while ( v4 );
    if ( val - result * result >= (unsigned int)(result - 1) )
      ++result;
    return result;
}

//----- (00452AE2) --------------------------------------------------------
int __fastcall MakeColorMaskFromBitDepth(int a1)
{
  signed __int64 v1; // qax@1

  v1 = 4294967296i64;
  if ( a1 > 0 )
  {
    do
    {
      LODWORD(v1) = HIDWORD(v1) + v1;
      HIDWORD(v1) *= 2;
      --a1;
    }
    while ( a1 );
  }
  return v1;
}

//----- (00452AF3) --------------------------------------------------------
void __fastcall fill_pixels_fast(unsigned int a1, unsigned __int16 *pPixels, unsigned int uNumPixels)
{
  void *v3; // edi@1
  unsigned int v4; // eax@1
  unsigned __int16 *v5; // edi@3
  unsigned int i; // ecx@3

  v3 = pPixels;
  v4 = a1 | (a1 << 16);
  if ( (unsigned __int8)pPixels & 2 )           // first 2 pixels
  {
    *pPixels = v4;
    v3 = pPixels + 1;
    --uNumPixels;
  }
  memset32(v3, v4, uNumPixels >> 1);            // 4 pixels at once
  v5 = (unsigned __int16 *)((char *)v3 + 4 * (uNumPixels >> 1));
  for ( i = uNumPixels & 1; i; --i )            // leftover pixels
  {
    *v5 = v4;
    ++v5;
  }
}

//----- (00452B2E) --------------------------------------------------------
int __fastcall GetDiceResult(unsigned int uNumDice, unsigned int uDiceSides)
{
  signed int v2; // edi@1
  int v3; // esi@1
  int result; // eax@2
  unsigned int v5; // ebx@4

  v2 = uDiceSides;
  v3 = 0;
  if ( uDiceSides )
  {
    if ( (signed int)uNumDice > 0 )
    {
      v5 = uNumDice;
      do
      {
        --v5;
        v3 += rand() % v2 + 1;
      }
      while ( v5 );
    }
    result = v3;
  }
  else
  {
    result = 0;
  }
  return result;
}

//----- (00453F62) --------------------------------------------------------
void MapStats::Initialize()
{
  char work_str[32]; // [sp+Ch] [bp-34h]@3
  int work_str_pos;
  int work_str_len;
  int i;
  char* test_string;
  unsigned char c;
  bool break_loop;
  unsigned int temp_str_len;
  char* tmp_pos;
  int decode_step;
  int item_counter;

  if ( pMapStatsTXT_Raw )
    pAllocator->FreeChunk(pMapStatsTXT_Raw);
  pMapStatsTXT_Raw = NULL;
  pMapStatsTXT_Raw = (char *)pEvents_LOD->LoadRaw("MapStats.txt", 0);
  strtok(pMapStatsTXT_Raw, "\r");
  strtok(NULL, "\r");
  strtok(NULL, "\r");

 for (i=1; i<77; ++i)
	  {
	  test_string = strtok(NULL, "\r") + 1;
	  break_loop = false;
	  decode_step=0;
	  do 
		  {
		  c = *(unsigned char*)test_string;
		  temp_str_len = 0;
		  while((c!='\t')&&(c>0))
			  {
			  ++temp_str_len;
			  c=test_string[temp_str_len];
			  }		
		  tmp_pos=test_string+temp_str_len;
		  if (*tmp_pos == 0)
			  break_loop = true;
		  *tmp_pos = 0;
		  if (temp_str_len)
			  {
			  switch (decode_step)
				  {
				  case 1:
					  pInfos[i].pName = RemoveQuotes(test_string);
					  break;
				  case 2:
					  pInfos[i].pFilename = RemoveQuotes(test_string);
					  break;
				  case 3:
					  pInfos[i].uNumResets = atoi(test_string);
					  break;
				  case 4:
					  pInfos[i].uFirstVisitedAt = atoi(test_string);
					  break;
				  case 5:
					  pInfos[i]._per = atoi(test_string);
					  break;
				  case 6:
					  pInfos[i].uRespawnIntervalDays = atoi(test_string);
					  break;
				  case 7:
					  pInfos[i]._alert_days = atoi(test_string);
					  break;
				  case 8:
					  pInfos[i]._steal_perm = atoi(test_string);
					  break;
				  case 9:
					  pInfos[i].LockX5 = atoi(test_string);
					  break;
				  case 10:
					  pInfos[i].Trap_D20 = atoi(test_string);
					  break;
				  case 11:
					  pInfos[i].Treasure_prob = atoi(test_string);
					  break;
				  case 12:
					  pInfos[i].Encounter_percent = atoi(test_string);
					  break;
				  case 13:
					  pInfos[i].EncM1percent = atoi(test_string);
					  break;
				  case 14:
					  pInfos[i].EncM2percent = atoi(test_string);
					  break;
				  case 15:
					  pInfos[i].EncM3percent = atoi(test_string);
					  break;
				  case 16:
					  pInfos[i].pEncounterMonster1Texture = RemoveQuotes(test_string);
					  break;
				  case 18:
					  pInfos[i].Dif_M1 = atoi(test_string);
					  break;
				  case 19:
					  pInfos[i].uEncounterMonster1AtLeast = 1;
					  pInfos[i].uEncounterMonster1AtMost = 1;
					  strcpy(work_str, test_string);
					  work_str_pos = 0;
					  work_str_len=strlen(work_str);
					  if (work_str_len )
						  {
						  while (work_str[work_str_pos] != '-' )
							  {
							  ++work_str_pos;
							  if (work_str_pos >= work_str_len )
								  break;
							  }
						  work_str[work_str_pos] = 0;
						  pInfos[i].uEncounterMonster1AtLeast = atoi(work_str);
						  if ( work_str_pos < work_str_len )
							  pInfos[i].uEncounterMonster1AtMost = atoi(&work_str[work_str_pos + 1]);
						  else
							  pInfos[i].uEncounterMonster1AtMost = pInfos[i].uEncounterMonster1AtLeast;
						  }
					  break;
				  case 20:
					  pInfos[i].pEncounterMonster2Texture = RemoveQuotes(test_string);
					  break;
				  case 22:
					  pInfos[i].Dif_M2 = atoi(test_string);
					  break;
				  case 23:
					  pInfos[i].uEncounterMonster2AtLeast = 1;
					  pInfos[i].uEncounterMonster2AtMost = 1;
					  strcpy(work_str, test_string);
					  work_str_pos = 0;
					  work_str_len=strlen(work_str);
					  if (work_str_len )
						  {
						  while (work_str[work_str_pos] != '-' )
							  {
							  ++work_str_pos;
							  if (work_str_pos >= work_str_len )
								  break;
							  }
						  work_str[work_str_pos] = 0;
						  pInfos[i].uEncounterMonster2AtLeast = atoi(work_str);
						  if ( work_str_pos < work_str_len )
							  pInfos[i].uEncounterMonster2AtMost = atoi(&work_str[work_str_pos + 1]);
						  else
							  pInfos[i].uEncounterMonster2AtMost = pInfos[i].uEncounterMonster2AtLeast;
						  }
					  break;
				  case 24:
					  pInfos[i].pEncounterMonster3Texture = RemoveQuotes(test_string);
					  break;
				  case 26:
					  pInfos[i].Dif_M3 = atoi(test_string);
					  break;
				  case 27:
					  pInfos[i].uEncounterMonster3AtLeast = 1;
					  pInfos[i].uEncounterMonster3AtMost = 1;
					  strcpy(work_str, test_string);
					  work_str_pos = 0;
					  work_str_len=strlen(work_str);
					  if (work_str_len )
						  {
						  while (work_str[work_str_pos] != '-' )
							  {
							  ++work_str_pos;
							  if (work_str_pos >= work_str_len )
								  break;
							  }
						  work_str[work_str_pos] = 0;
						  pInfos[i].uEncounterMonster3AtLeast = atoi(work_str);
						  if ( work_str_pos < work_str_len )
							  pInfos[i].uEncounterMonster3AtMost = atoi(&work_str[work_str_pos + 1]);
						  else
							  pInfos[i].uEncounterMonster3AtMost = pInfos[i].uEncounterMonster3AtLeast;
						  }
					  break;
				  case 28:
					  pInfos[i].uRedbookTrackID = atoi(test_string);
					  break;
				  case 29:
					  {
					  if ( !strcmp(test_string, "CAVE") )
						  {
						  pInfos[i].uEAXEnv = 8;
						  break;
						  }
					  if ( !strcmp(test_string, "STONEROOM") )
						  {
						  pInfos[i].uEAXEnv = 5;
						  break;
						  }
					  if ( !strcmp(test_string, "MOUNTAINS") )
						  {
						  pInfos[i].uEAXEnv = 17;
						  break;
						  }
					  if ( !strcmp(test_string, "PLAIN") )
						  {
						  pInfos[i].uEAXEnv = 19;
						  break;
						  }
					  if ( !strcmp(test_string, "FOREST") )
						  {
						  pInfos[i].uEAXEnv = 15;
						  break;
						  }
					  if ( !strcmp(test_string, "CITY") )
						  {
						  pInfos[i].uEAXEnv = 16;
						  break;
						  }
					  if ( !strcmp(test_string, "UNDERWATER") )
						  {
						  pInfos[i].uEAXEnv = 22;
						  break;
						  }
					  if ( !strcmp(test_string, "ARENA") )
						  {
						  pInfos[i].uEAXEnv = 9;
						  break;
						  }
					  if ( !strcmp(test_string, "GENERIC") )
						  {
						  pInfos[i].uEAXEnv = 0;
						  break;
						  }
					  if ( !strcmp(test_string, "PADDEDCELL") )
						  {
						  pInfos[i].uEAXEnv = 1;
						  break;
						  }
					  if ( !strcmp(test_string, "ROOM") )
						  {
						  pInfos[i].uEAXEnv = 2;
						  break;
						  }
					  if ( !strcmp(test_string, "BATHROOM") )
						  {
						  pInfos[i].uEAXEnv = 3;
						  break;
						  }
					  if ( !strcmp(test_string, "LIVINGROOM") )
						  {
						  pInfos[i].uEAXEnv = 4;
						  break;
						  }
					  if ( !strcmp(test_string, "AUDITORIUM") )
						  {
						  pInfos[i].uEAXEnv = 6;
						  break;
						  }
					  if ( !strcmp(test_string, "CONCERTHALL") )
						  {
						  pInfos[i].uEAXEnv = 7;
						  break;
						  }
					  if ( !strcmp(test_string, "HANGAR") )
						  {
						  pInfos[i].uEAXEnv = 10;
						  break;
						  }
					  if ( !strcmp(test_string, "CARPETEDHALLWAY") )
						  {
						  pInfos[i].uEAXEnv = 11;
						  break;
						  }
					  if ( !strcmp(test_string, "HALLWAY") )
						  {
						  pInfos[i].uEAXEnv = 12;
						  break;
						  }
					  if ( !strcmp(test_string, "STONECORRIDOR") )
						  {
						  pInfos[i].uEAXEnv = 13;
						  break;
						  }
					  if ( !strcmp(test_string, "ALLEY") )
						  {
						  pInfos[i].uEAXEnv = 14;
						  break;
						  }
					  if ( !strcmp(test_string, "QUARRY") )
						  {
						  pInfos[i].uEAXEnv = 18;
						  break;
						  }
					  if ( !strcmp(test_string, "PARKINGLOT") )
						  {
						  pInfos[i].uEAXEnv = 20;
						  break;
						  }
					  if ( !strcmp(test_string, "SEWERPIPE") )
						  {
						  pInfos[i].uEAXEnv = 21;
						  break;
						  }
					  if ( !strcmp(test_string, "DRUGGED") )
						  {
						  pInfos[i].uEAXEnv = 23;
						  break;
						  }
					  if ( !strcmp(test_string, "DIZZY") )
						  {
						  pInfos[i].uEAXEnv = 24;
						  break;
						  }
					  if ( !strcmp(test_string, "PSYCHOTIC") )
						  {
						  pInfos[i].uEAXEnv = 25;
						  break;
						  }
					   pInfos[i].uEAXEnv = 26;
					
						  }
					  break;
				  }
			  }
		  else
			  { 
				  break_loop = true;
			  }
		  ++decode_step;
		  test_string=tmp_pos+1;
		  } while ((decode_step<31)&&!break_loop);
	  }
 
  uNumMaps = 77;
}
// 453F62: using guessed type char Str[32];

//----- (004547A3) --------------------------------------------------------
MAP_TYPE MapStats::GetMapInfo(const char *Str2)
{
  assert(uNumMaps >= 2);

  for (uint i = 1; i < uNumMaps; ++i)
    if (!_stricmp(pInfos[i].pFilename, Str2))
      return (MAP_TYPE)i;

  assert(false && "Map not found!");
}

//----- (004547E4) --------------------------------------------------------
void FactionTable::Initialize()
{
  int i;
  char* test_string;
  unsigned char c;
  bool break_loop;
  unsigned int temp_str_len;
  char* tmp_pos;
  int decode_step;
  int item_counter;

  if ( pHostileTXT_Raw )
    pAllocator->FreeChunk(pHostileTXT_Raw);
  pHostileTXT_Raw = NULL;
  pHostileTXT_Raw = (char *)pEvents_LOD->LoadRaw("hostile.txt", 0);
  strtok(pHostileTXT_Raw, "\r");
  for (i=0; i<89; ++i)
	  {
	  test_string = strtok(NULL, "\r") + 1;
	  break_loop = false;
	  decode_step=0;
	  do 
		  {
		  c = *(unsigned char*)test_string;
		  temp_str_len = 0;
		  while((c!='\t')&&(c>0))
			  {
			  ++temp_str_len;
			  c=test_string[temp_str_len];
			  }		
		  tmp_pos=test_string+temp_str_len;
		  if (*tmp_pos == 0)
			  break_loop = true;
		  *tmp_pos = 0;
		  if (temp_str_len)
			  {
			  if ( decode_step >= 1 && decode_step < 90 )
				  relations[decode_step-1][i] = atoi(test_string);
			  }
		  else
			  { 
			  break_loop = true;
			  }
		  ++decode_step;
		  test_string=tmp_pos+1;
		  } while ((decode_step<92)&&!break_loop);
	  }
  if ( pHostileTXT_Raw)
  {
    pAllocator->FreeChunk(pHostileTXT_Raw);
    pHostileTXT_Raw = NULL;
  }
}

//----- (00458244) --------------------------------------------------------
int SkillToMastery( unsigned int skill_value )
{
  switch (skill_value & 0x1C0)
  {
    case 0x100: return 4;     // Grandmaster
    case 0x80:  return 3;     // Master
    case 0x40:  return 2;     // Expert
    case 0x00:  return 1;     // Normal
    default:
      assert(false);
  }
}

//----- (0045828B) --------------------------------------------------------
unsigned int __fastcall GetSpellColor(signed int a1)
{
  unsigned __int16 v1; // dx@3
  unsigned __int16 v2; // cx@6
  unsigned __int16 v4; // [sp-4h] [bp-4h]@3

  if ( a1 < 1 )
  {
    if ( a1 < 12 )
    {
      if ( a1 < 23 )
      {
        if ( a1 < 34 )
        {
          if ( a1 < 45 )
          {
            if ( a1 < 56 )
            {
              if ( a1 < 67 )
              {
                if ( a1 < 78 )
                {
                  if ( a1 < 89 )
                    goto LABEL_31;
                  goto LABEL_28;
                }
LABEL_25:
                if ( a1 < 89 )
                {
                  v4 = 155;
                  v2 = 255;
                  goto LABEL_30;
                }
LABEL_28:
                if ( a1 < 100 )
                {
                  v4 = 240;
                  v2 = 192;
                  goto LABEL_30;
                }
LABEL_31:
                v4 = 0;
                v1 = 0;
                goto LABEL_32;
              }
LABEL_21:
              if ( a1 < 78 )
              {
                v4 = 0;
                v1 = 128;
                goto LABEL_23;
              }
              goto LABEL_25;
            }
LABEL_18:
            if ( a1 < 67 )
            {
              v4 = 255;
              v1 = 15;
              v2 = 235;
              return TargetColor(v2, v1, v4);
            }
            goto LABEL_21;
          }
LABEL_15:
          if ( a1 < 56 )
          {
            v2 = 225;
            goto LABEL_13;
          }
          goto LABEL_18;
        }
LABEL_11:
        if ( a1 < 45 )
        {
          v2 = 128;
LABEL_13:
          v4 = v2;
LABEL_30:
          v1 = v2;
          return TargetColor(v2, v1, v4);
        }
        goto LABEL_15;
      }
LABEL_8:
      if ( a1 < 34 )
      {
        v4 = 255;
        v1 = 128;
LABEL_32:
        v2 = 0;
        return TargetColor(v2, v1, v4);
      }
      goto LABEL_11;
    }
  }
  else
  {
    if ( a1 < 12 )
    {
      v4 = 0;
      v1 = 85;
LABEL_23:
      v2 = 255;
      return TargetColor(v2, v1, v4);
    }
  }
  if ( a1 >= 23 )
    goto LABEL_8;
  v4 = 255;
  v1 = 212;
  v2 = 150;
  return TargetColor(v2, v1, v4);
}

//----- (004583B0) --------------------------------------------------------
LevelDecoration::LevelDecoration()
{
  this->field_1A = 0;
  this->field_18 = 0;
  this->vPosition.z = 0;
  this->vPosition.y = 0;
  this->vPosition.x = 0;
  this->uDecorationDescID = 0;
  this->field_2 = 0;
  this->field_16_event_id = 0;
  this->uCog = 0;
}

//----- (00458600) --------------------------------------------------------
void DecorationList::ToFile()
{
  DecorationList *v1; // esi@1
  FILE *v2; // eax@1
  FILE *v3; // edi@1

  v1 = this;
  v2 = fopen("data\\ddeclist.bin", "wb");
  v3 = v2;
  if ( !v2 )
    Abortf("Unable to save ddeclist.bin!");
  fwrite(v1, 4u, 1u, v2);
  fwrite(v1->pDecorations, 0x54u, v1->uNumDecorations, v3);
  fclose(v3);
}

//----- (0045864C) --------------------------------------------------------
void DecorationList::FromFile(void *pSerialized)
{
  uNumDecorations = *(int *)pSerialized;
  pDecorations = (DecorationDesc *)pAllocator->AllocNamedChunk(pDecorations,
                           84 * uNumDecorations, "Dec Descrip");
  memcpy(pDecorations, (char *)pSerialized + 4, 84 * uNumDecorations);
}

//----- (00458693) --------------------------------------------------------
void DecorationList::InitializeDecorationSprite(unsigned int uDecID)
{
  pSpriteFrameTable->InitializeSprite(this->pDecorations[uDecID].uSpriteID);
}

//----- (004586B0) --------------------------------------------------------
bool DecorationList::FromFileTxt(const char *Args)
{
  DecorationList *v2; // ebx@1
  FILE *v3; // eax@1
  unsigned int v4; // esi@3
  void *v5; // eax@10
  FILE *v6; // ST18_4@12
  char *i; // eax@12
  unsigned __int16 v8; // ax@16
  const char *v9; // ST20_4@16
  const char *v10; // ST18_4@16
  __int16 v11; // ax@16
  const char *v12; // ST14_4@16
  unsigned __int16 v13; // ax@16
  const char *v14; // ST10_4@16
  __int16 v15; // ax@16
  const char *v16; // ST0C_4@16
  unsigned __int8 v17; // al@16
  const char *v18; // ST08_4@16
  unsigned __int8 v19; // al@16
  const char *v20; // ST04_4@16
  unsigned __int8 v21; // al@16
  const char *v22; // ST00_4@16
  unsigned __int8 v23; // zf@16
  char v24; // sf@16
  unsigned __int8 v25; // of@16
  int j; // edi@17
  const char *v27; // esi@18
  int v28; // eax@19
  int v29; // eax@21
  int v30; // eax@23
  int v31; // eax@25
  int v32; // eax@27
  int v33; // eax@29
  int v34; // eax@31
  int v35; // eax@33
  FrameTableTxtLine v37; // [sp+Ch] [bp-460h]@17
  FrameTableTxtLine v38; // [sp+88h] [bp-3E4h]@13
  char Dest; // [sp+104h] [bp-368h]@17
  char Buf; // [sp+17Ch] [bp-2F0h]@3
  FrameTableTxtLine v41; // [sp+370h] [bp-FCh]@4
  FrameTableTxtLine v42; // [sp+3ECh] [bp-80h]@4
  FILE *File; // [sp+468h] [bp-4h]@1
  unsigned int Argsa; // [sp+474h] [bp+8h]@3

  v2 = this;
  v3 = fopen(Args, "r");
  File = v3;
  if ( !v3 )
    Abortf("DecorationDescriptionList::load - Unable to open file: %s.");
  v4 = 0;
  Argsa = 0;
  if ( fgets(&Buf, 490, v3) )
  {
    do
    {
      *strchr(&Buf, 10) = 0;
      memcpy(&v42, frame_table_txt_parser(&Buf, &v41), sizeof(v42));
      if ( v42.uPropCount && *v42.pProperties[0] != 47 && v42.uPropCount >= 3 )
        ++Argsa;
    }
    while ( fgets(&Buf, 490, File) );
    v4 = Argsa;
  }
  v2->uNumDecorations = v4;
  v5 = pAllocator->AllocNamedChunk(v2->pDecorations, 84 * v4, "Dec Descrip");
  v2->pDecorations = (DecorationDesc *)v5;
  if ( !v5 )
    Abortf("DecorationDescriptionList::load - Out of Memory!");
  v6 = File;
  v2->uNumDecorations = 0;
  fseek(v6, 0, 0);
  for ( i = fgets(&Buf, 490, File); i; i = fgets(&Buf, 490, File) )
  {
    *strchr(&Buf, 10) = 0;
    memcpy(&v42, frame_table_txt_parser(&Buf, &v38), sizeof(v42));
    if ( v42.uPropCount && *v42.pProperties[0] != 47 && v42.uPropCount >= 3 )
    {
      strcpy(v2->pDecorations[v2->uNumDecorations].pName, v42.pProperties[1]);
      v8 = pSpriteFrameTable->FastFindSprite(v2->pDecorations[v2->uNumDecorations].pName);
      v9 = v42.pProperties[2];
      v2->pDecorations[v2->uNumDecorations].uSpriteID = v8;
      strcpy(v2->pDecorations[v2->uNumDecorations].field_20, v9);
      v10 = v42.pProperties[3];
      v2->pDecorations[v2->uNumDecorations].uType = 0;
      v11 = atoi(v10);
      v12 = v42.pProperties[4];
      v2->pDecorations[v2->uNumDecorations].uRadius = v11;
      v13 = atoi(v12);
      v14 = v42.pProperties[5];
      v2->pDecorations[v2->uNumDecorations].uDecorationHeight = v13;
      v15 = atoi(v14);
      v16 = v42.pProperties[6];
      v2->pDecorations[v2->uNumDecorations].uLightRadius = v15;
      v17 = atoi(v16);
      v18 = v42.pProperties[7];
      v2->pDecorations[v2->uNumDecorations].uColoredLightRed = v17;
      v19 = atoi(v18);
      v20 = v42.pProperties[8];
      v2->pDecorations[v2->uNumDecorations].uColoredLightGreen = v19;
      v21 = atoi(v20);
      v22 = v42.pProperties[9];
      v2->pDecorations[v2->uNumDecorations].uColoredLightBlue = v21;
      v2->pDecorations[v2->uNumDecorations].uSoundID = atoi(v22);
      v25 = __OFSUB__(v42.uPropCount, 10);
      v23 = v42.uPropCount == 10;
      v24 = v42.uPropCount - 10 < 0;
      v2->pDecorations[v2->uNumDecorations].uFlags = 0;
      if ( !((unsigned __int8)(v24 ^ v25) | v23) )
      {
        strcpy(&Dest, v42.pProperties[10]);
        memcpy(&v41, frame_table_txt_parser(&Dest, &v37), sizeof(v41));
        for ( j = 0; j < v41.uPropCount; ++j )
        {
          v27 = v41.pProperties[j];
          if ( _stricmp(v41.pProperties[j], "NBM") )
          {
            if ( _stricmp(v27, "Invisible") )
            {
              if ( _stricmp(v27, "FS") )
              {
                if ( _stricmp(v27, "FM") )
                {
                  if ( _stricmp(v27, "FF") )
                  {
                    if ( _stricmp(v27, "Marker") )
                    {
                      if ( _stricmp(v27, "LoopSlow") )
                      {
                        if ( _stricmp(v27, "EmitFire") )
                        {
                          if ( _stricmp(v27, "Dawn") )
                          {
                            if ( !_stricmp(v27, "Dusk") )
                              HIBYTE(v2->pDecorations[v2->uNumDecorations].uFlags) |= 2u;
                          }
                          else
                          {
                            HIBYTE(v2->pDecorations[v2->uNumDecorations].uFlags) |= 1u;
                          }
                        }
                        else
                        {
                          v35 = (int)&v2->pDecorations[v2->uNumDecorations].uFlags;
                          *(char *)v35 |= 0x80u;
                        }
                      }
                      else
                      {
                        v34 = (int)&v2->pDecorations[v2->uNumDecorations].uFlags;
                        *(char *)v34 |= 0x40u;
                      }
                    }
                    else
                    {
                      v33 = (int)&v2->pDecorations[v2->uNumDecorations].uFlags;
                      *(char *)v33 |= 0x20u;
                    }
                  }
                  else
                  {
                    v32 = (int)&v2->pDecorations[v2->uNumDecorations].uFlags;
                    *(char *)v32 |= 0x10u;
                  }
                }
                else
                {
                  v31 = (int)&v2->pDecorations[v2->uNumDecorations].uFlags;
                  *(char *)v31 |= 8u;
                }
              }
              else
              {
                v30 = (int)&v2->pDecorations[v2->uNumDecorations].uFlags;
                *(char *)v30 |= 4u;
              }
            }
            else
            {
              v29 = (int)&v2->pDecorations[v2->uNumDecorations].uFlags;
              *(char *)v29 |= 2u;
            }
          }
          else
          {
            v28 = (int)&v2->pDecorations[v2->uNumDecorations].uFlags;
            *(char *)v28 |= 1u;
          }
        }
      }
      ++v2->uNumDecorations;
    }
  }
  fclose(File);
  return 1;
}

//----- (00459064) --------------------------------------------------------
void ObjectList::InitializeSprites()
{
  for (uint i = 0; i < uNumObjects; ++i)
    pSpriteFrameTable->InitializeSprite(pObjects[i].uSpriteID);
}

//----- (00459090) --------------------------------------------------------
void ObjectList::ToFile()
{
  ObjectList *v1; // esi@1
  FILE *v2; // eax@1
  FILE *v3; // edi@1

  v1 = this;
  v2 = fopen("data\\dobjlist.bin", "wb");
  v3 = v2;
  if ( !v2 )
    Abortf("Unable to save dobjlist.bin!");
  fwrite(v1, 4u, 1u, v2);
  fwrite(v1->pObjects, 0x38u, v1->uNumObjects, v3);
  fclose(v3);
}

//----- (004590DC) --------------------------------------------------------
void ObjectList::FromFile(void *pSerialized)
{
  uNumObjects = *(int *)pSerialized;
  pObjects = (ObjectDesc *)pAllocator->AllocNamedChunk(pObjects, 56 * uNumObjects, "Obj Descrip");
  memcpy(pObjects, (char *)pSerialized + 4, 56 * uNumObjects);
}

//----- (00459123) --------------------------------------------------------
bool ObjectList::FromFileTxt(const char *Args)
{
  ObjectList *v2; // ebx@1
  __int32 v3; // edi@1
  FILE *v4; // eax@1
  unsigned int v5; // esi@3
  void *v6; // eax@9
  FILE *v7; // ST0C_4@11
  char *i; // eax@11
  unsigned __int16 v9; // ax@14
  const char *v10; // ST20_4@14
  __int16 v11; // ax@14
  const char *v12; // ST1C_4@14
  __int16 v13; // ax@14
  const char *v14; // ST18_4@14
  __int16 v15; // ax@14
  const char *v16; // ST14_4@14
  __int16 v17; // ax@14
  const char *v18; // ST10_4@14
  __int16 v19; // ax@14
  const char *v20; // ST0C_4@14
  int v21; // esi@16
  const char *v22; // edi@16
  int v23; // eax@17
  int v24; // eax@19
  int v25; // eax@21
  int v26; // eax@21
  int v27; // eax@21
  int v28; // eax@23
  int v29; // eax@25
  int v30; // eax@27
  int v31; // eax@29
  const char *v32; // edi@30
  const char *v33; // ST20_4@35
  int v34; // eax@35
  char v35; // al@35
  const char *v36; // ST1C_4@35
  char v37; // al@35
  const char *v38; // ST18_4@35
  FrameTableTxtLine v40; // [sp+8h] [bp-460h]@14
  FrameTableTxtLine v41; // [sp+84h] [bp-3E4h]@12
  char Dest; // [sp+100h] [bp-368h]@14
  char Buf; // [sp+178h] [bp-2F0h]@3
  FrameTableTxtLine v44; // [sp+36Ch] [bp-FCh]@4
  FrameTableTxtLine v45; // [sp+3E8h] [bp-80h]@4
  FILE *File; // [sp+464h] [bp-4h]@1
  unsigned int Argsa; // [sp+470h] [bp+8h]@3
  int Argsb; // [sp+470h] [bp+8h]@15

  v2 = this;
  pAllocator->FreeChunk(this->pObjects);
  v3 = 0;
  v2->pObjects = 0;
  v2->uNumObjects = 0;
  v4 = fopen(Args, "r");
  File = v4;
  if ( !v4 )
    Abortf("ObjectDescriptionList::load - Unable to open file: %s.");
  v5 = 0;
  Argsa = 0;
  if ( fgets(&Buf, 490, v4) )
  {
    do
    {
      *strchr(&Buf, 10) = 0;
      memcpy(&v45, frame_table_txt_parser(&Buf, &v44), sizeof(v45));
      if ( v45.uPropCount && *v45.pProperties[0] != '/' )
        ++Argsa;
    }
    while ( fgets(&Buf, 490, File) );
    v5 = Argsa;
    v3 = 0;
  }
  v2->uNumObjects = v5;
  v6 = pAllocator->AllocNamedChunk(v2->pObjects, 56 * v5, "Obj Descrip");
  v2->pObjects = (ObjectDesc *)v6;
  if ( v6 == (void *)v3 )
    Abortf("ObjectDescriptionList::load - Out of Memory!");
  memset(v6, v3, 56 * v2->uNumObjects);
  v7 = File;
  v2->uNumObjects = v3;
  fseek(v7, v3, v3);
  for ( i = fgets(&Buf, 490, File); i; i = fgets(&Buf, 490, File) )
  {
    *strchr(&Buf, 10) = 0;
    memcpy(&v45, frame_table_txt_parser(&Buf, &v41), sizeof(v45));
    if ( v45.uPropCount && *v45.pProperties[0] != 47 )
    {
      strcpy(v2->pObjects[v2->uNumObjects].field_0, v45.pProperties[0]);
      v9 = pSpriteFrameTable->FastFindSprite((char *)v45.pProperties[1]);
      v10 = v45.pProperties[2];
      v2->pObjects[v2->uNumObjects].uSpriteID = v9;
      v11 = atoi(v10);
      v12 = v45.pProperties[3];
      v2->pObjects[v2->uNumObjects].uObjectID = v11;
      v13 = atoi(v12);
      v14 = v45.pProperties[4];
      v2->pObjects[v2->uNumObjects].uRadius = v13;
      v15 = atoi(v14);
      v16 = v45.pProperties[5];
      v2->pObjects[v2->uNumObjects].uHeight = v15;
      v17 = atoi(v16);
      v18 = v45.pProperties[6];
      v2->pObjects[v2->uNumObjects].uLifetime = v17;
      v19 = atoi(v18);
      v20 = v45.pProperties[7];
      v2->pObjects[v2->uNumObjects].uSpeed = v19;
      strcpy(&Dest, v20);
      memcpy(&v44, frame_table_txt_parser(&Dest, &v40), sizeof(v44));
      if ( v45.uPropCount > 7 )
      {
        for ( Argsb = 0; Argsb < v44.uPropCount; ++Argsb )
        {
          v21 = Argsb;
          v22 = v44.pProperties[Argsb];
          if ( !_stricmp(v44.pProperties[Argsb], "NoDraw") )
          {
            v23 = (int)&v2->pObjects[v2->uNumObjects].uFlags;
            *(char *)v23 |= 1u;
          }
          if ( !_stricmp(v22, "Lifetime") )
          {
            v24 = (int)&v2->pObjects[v2->uNumObjects].uFlags;
            *(char *)v24 |= 4u;
          }
          if ( !_stricmp(v22, "FTLifetime") )
          {
            v25 = (int)&v2->pObjects[v2->uNumObjects];
            *(short *)(v25 + 42) = 8 * pSpriteFrameTable->pSpriteSFrames[*(short *)(v25 + 40)].uAnimLength;
            v26 = (int)&v2->pObjects[v2->uNumObjects].uFlags;
            *(char *)v26 |= 8u;
            v27 = (int)&v2->pObjects[v2->uNumObjects].uFlags;
            *(char *)v27 |= 4u;
          }
          if ( !_stricmp(v22, "NoPickup") )
          {
            v28 = (int)&v2->pObjects[v2->uNumObjects].uFlags;
            *(char *)v28 |= 0x10u;
          }
          if ( !_stricmp(v22, "NoGravity") )
          {
            v29 = (int)&v2->pObjects[v2->uNumObjects].uFlags;
            *(char *)v29 |= 0x20u;
          }
          if ( !_stricmp(v22, "FlagOnIntercept") )
          {
            v30 = (int)&v2->pObjects[v2->uNumObjects].uFlags;
            *(char *)v30 |= 0x40u;
          }
          if ( !_stricmp(v22, "Bounce") )
          {
            v31 = (int)&v2->pObjects[v2->uNumObjects].uFlags;
            *(char *)v31 |= 0x80u;
          }
          v32 = v45.pProperties[v21];
          if ( !_stricmp(v45.pProperties[v21], "Fire") )
            HIBYTE(v2->pObjects[v2->uNumObjects].uFlags) |= 2u;
          if ( !_stricmp(v32, "Lines") )
            HIBYTE(v2->pObjects[v2->uNumObjects].uFlags) |= 4u;
          if ( !_stricmp(v44.pProperties[v21], "bits") )
          {
            v33 = v44.pProperties[v21 + 1];
            v34 = (int)&v2->pObjects[v2->uNumObjects].uFlags;
            *(char *)(v34 + 1) |= 1u;
            v35 = atoi(v33);
            v36 = v44.pProperties[v21 + 2];
            v2->pObjects[v2->uNumObjects].uParticleTrailColorR = v35;
            v37 = atoi(v36);
            v38 = v44.pProperties[v21 + 3];
            v2->pObjects[v2->uNumObjects].uParticleTrailColorG = v37;
            v2->pObjects[v2->uNumObjects].uParticleTrailColorB = atoi(v38);
          }
        }
      }
      ++v2->uNumObjects;
    }
  }
  fclose(File);
  return 1;
}

//----- (0045E03A) --------------------------------------------------------
unsigned short * MakeScreenshot( signed int width, signed int height )
{
  //signed int v2; // edi@1
  unsigned __int16 *v3; // ebx@1
  int v4; // edx@7
  unsigned __int8 v5; // cf@9
  unsigned int v6; // ecx@9
  unsigned __int16 *v7; // edi@9
  int j; // ecx@9
  //unsigned __int16 *v9; // edi@15
  //int v10; // ecx@15
  //LONG v11; // esi@15
  //signed __int64 v12; // qax@18
  //unsigned int v13; // ST10_4@21
  HRESULT v14; // eax@21
  int v15; // edi@29
  signed __int64 v16; // qax@30
  signed int v17; // edx@34
  unsigned __int16 *v18; // edi@36
  int k; // ecx@36
  DDSURFACEDESC2 Dst; // [sp+4h] [bp-A0h]@6
  unsigned __int16 *pPixels; // [sp+80h] [bp-24h]@1
  float v23; // [sp+84h] [bp-20h]@1
  unsigned __int16 *_this; // [sp+88h] [bp-1Ch]@21
  float v25; // [sp+8Ch] [bp-18h]@1
  unsigned int v26; // [sp+90h] [bp-14h]@17
  //int v27; // [sp+94h] [bp-10h]@1
  int v28; // [sp+98h] [bp-Ch]@16
  int v29; // [sp+9Ch] [bp-8h]@15
  //int v30; // [sp+A0h] [bp-4h]@1

  //v30 = width;
  //v2 = height;
  //v27 = height;
  v23 = game_viewport_width / (double)width;
  v25 = game_viewport_height / (double)height;

  pPixels = (unsigned __int16 *)malloc(2 * height * width);
  memset(pPixels, 0 , 2 * height * width);

  v3 = pPixels;
  if ( pRenderer->pRenderD3D )
  {
    pRenderer->BeginSceneD3D();

    if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
      pIndoor->Draw();
    else if (uCurrentlyLoadedLevelType == LEVEL_Outdoor)
      pOutdoor->Draw();

    pRenderer->DrawBillboards_And_MaybeRenderSpecialEffects_And_EndScene();
    memset(&Dst, 0, 0x7Cu);
    Dst.dwSize = sizeof(Dst);

    if ( pRenderer->LockSurface_DDraw4(pRenderer->pBackBuffer4, &Dst, DDLOCK_WAIT) )
    {
      auto src = (unsigned __int16 *)Dst.lpSurface;
      auto src_width = (Dst.lPitch / sizeof(short));
      auto src_height = Dst.dwHeight;
      auto dst = pPixels;
      for (uint y = 0; y < height; ++y)
      {
        //uint src_y = (game_viewport_y + y * v25) * (Dst.lPitch / sizeof(short));
        uint src_y = game_viewport_y + y * v25;
        assert(game_viewport_y + y * v25 < src_height);
        assert(y < height);

        for (uint x = 0; x < width; ++x)
        {
          //uint src_x = game_viewport_x + x * v23;
          uint src_x = game_viewport_x + x * v23;
          assert(src_x < src_width);
          assert(x < width);

          dst[y * width + x] = (((63*y)/117) << 5) | 31*x/155;//31*y/117;//src[src_y * src_width + src_x];
        }
      }
      ErrD3D(pRenderer->pBackBuffer4->Unlock(0));
    }
    else
    {
      __debugbreak(); // unrefactored
      v4 = height;
      if ( height > 0 )
      {
        do
        {
          if ( width > 0 )
          {
            v5 = width & 1;
            v6 = (unsigned int)width >> 1;
            memset(v3, 0, 4 * ((unsigned int)width >> 1));
            v7 = &v3[2 * v6];
            for ( j = v5; j; --j )
            {
              *v7 = 0;
              ++v7;
            }
            v3 += width;
          }
          --v4;
        }
        while ( v4 );
      }
    }
  }
  else
  {
    pRenderer->BeginScene();
    if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
    {
      pIndoor->Draw();
    }
    else
    {
      if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
        pOutdoor->Draw();
    }
    _this = pRenderer->pTargetSurface;
    v26 = pRenderer->uTargetSurfacePitch;
    if ( pRenderer->pTargetSurface )
    {
      v29 = 0;
      if ( height > 0 )
      {
        do
        {
          v28 = 0;
          if ( width > 0 )
          {
            v15 = v26 * (unsigned __int64)(signed __int64)((double)v29 * v25 + 8.0);
            do
            {
              v16 = (signed __int64)((double)v28++ * v23 + 8.0);
              *v3 = _this[v15 + (int)v16];
              ++v3;
            }
            while ( v28 < width );
          }
          ++v29;
        }
        while ( v29 < height );
      }
    }
    else
    {
      if ( height > 0 )
      {
        v17 = height;
        do
        {
          if ( width > 0 )
          {
            memset(v3, 0, 4 * ((unsigned int)width >> 1));
            v18 = &v3[2 * ((unsigned int)width >> 1)];
            for ( k = width & 1; k; --k )
            {
              *v18 = 0;
              ++v18;
            }
            v3 += width;
          }
          --v17;
        }
        while ( v17 );
      }
    }
    pRenderer->EndScene();
  }
  return pPixels;
}

//----- (0045E26C) --------------------------------------------------------
void __thiscall SaveScreenshot(const char *pFilename)
{
  const char *v1; // edi@1
  unsigned __int16 *v2; // esi@1

  v1 = pFilename;
  v2 = MakeScreenshot(92, 68);
  pRenderer->SavePCXImage(v1, (char *)v2, 92, 68);
  free(v2);
}

//----- (00460706) --------------------------------------------------------
void TryLoadLevelFromLOD()
{
  FILE *v0; // eax@1
  FILE *v1; // esi@1
  __int32 v2; // edi@2
  char Ext[256]; // [sp+4h] [bp-40Ch]@1
  char Dir[256]; // [sp+104h] [bp-30Ch]@1
  char Filename[256]; // [sp+204h] [bp-20Ch]@1
  char a1[260]; // [sp+304h] [bp-10Ch]@1
  char Drive[4]; // [sp+408h] [bp-8h]@1
  int DstBuf; // [sp+40Ch] [bp-4h]@2

  strcpy(a1, pCurrentMapName.data());
  _splitpath(a1, Drive, Dir, Filename, Ext);
  sprintf(a1, "levels\\%s%s", Filename, ".lod");
  v0 = fopen(a1, "rb");
  v1 = v0;
  if ( v0 )
  {
    fseek(v0, 0, 2);
    v2 = ftell(v1);
    rewind(v1);
    ptr_6A0D08 = pAllocator->AllocNamedChunk(ptr_6A0D08, v2, "LevelLod");
    fread(ptr_6A0D08, v2, 1u, v1);
    fseek(v1, v2 - 6, 0);
    DstBuf = 0;
    fread(&DstBuf, 4u, 1u, v1);
    fread(&_6A0D10_txt_lod_loading__unused, 2u, 1u, v1);
    _6A0D0C_txt_lod_loading = (int)((char *)ptr_6A0D08 + DstBuf);
    fclose(v1);
  }
}

//----- (0046080D) --------------------------------------------------------
void __cdecl sub_46080D()
{
  pAllocator->FreeChunk(ptr_6A0D08);
  ptr_6A0D08 = 0;
  _6A0D0C_txt_lod_loading = 0;
}

//----- (0046082C) --------------------------------------------------------
bool Initialize_GamesLOD_NewLOD()
{
  pGames_LOD = new LODWriteableFile;
  pGames_LOD->AllocSubIndicesAndIO(300, 0);
  if (pGames_LOD->LoadFile("data\\games.lod", 1))
  {
    pNew_LOD = new LODWriteableFile;
    pNew_LOD->AllocSubIndicesAndIO(300, 100000);
    return true;
  }
  return false;
}

//----- (0046086A) --------------------------------------------------------
void SaveNewGame()
{
  FILE *v3; // eax@7
  void *pSave; // [sp+170h] [bp-8h]@3

  if ( pVideoPlayer->AnyMovieLoaded() )
    pVideoPlayer->Unload();
  pSave = pAllocator->AllocNamedChunk(0, 1000000, 0);
  pNew_LOD->CloseWriteFile();
  remove("data\\new.lod");

  LOD::FileHeader this_; // [sp+Ch] [bp-16Ch]@3
  strcpy(this_.LodVersion, "MMVII");
  strcpy(this_.LodDescription, "newmaps for MMVII");
  this_.LODSize = 100;
  this_.dword_0000A8 = 0;

  LOD::Directory a3; // [sp+14Ch] [bp-2Ch]@3
  a3.dword_000018 = 0;
  a3.word_00001E = 0;
  strcpy(a3.pFilename, "current");
  pNew_LOD->CreateNewLod(&this_, &a3, "data\\new.lod");
  if (pNew_LOD->LoadFile("data\\new.lod", false))
  {
    pNew_LOD->CreateTempFile();
    pNew_LOD->uNumSubDirs = 0;

    LOD::Directory pDir; // [sp+10Ch] [bp-6Ch]@4
    for (int i = pGames_LOD->uNumSubDirs / 2; i < pGames_LOD->uNumSubDirs; ++i)
    {
      memcpy(&pDir, &pGames_LOD->pSubIndices[i], sizeof(pDir));
      v3 = pGames_LOD->FindContainer(pGames_LOD->pSubIndices[i].pFilename, 1);
      fread(pSave, pGames_LOD->pSubIndices[i].uDataSize, 1, v3);
      pNew_LOD->AppendDirectory(&pDir, pSave);
    }

    LOD::Directory save_game_dir; // [sp+12Ch] [bp-4Ch]@9
    strcpy(pSavegameHeader[0].pLocationName, "out01.odm");
    strcpy(save_game_dir.pFilename, "header.bin");
    save_game_dir.uDataSize = sizeof(SavegameHeader);
    pNew_LOD->AppendDirectory(&save_game_dir, &pSavegameHeader[0]);

    pNew_LOD->FixDirectoryOffsets();
    pParty->vPrevPosition.y = 0;
    pParty->vPrevPosition.x = 12552;
    pParty->vPosition.x = 12552;
    pParty->vPosition.z = 0;
    pParty->uFallStartY = 0;
    pParty->sPrevRotationX = 0;
    pParty->sRotationX = 0;
    pParty->vPrevPosition.z = 1816;
    pParty->vPosition.y = 1816;
    pParty->sPrevRotationY = 512;
    pParty->sRotationY = 512;
    SaveGame(1, 1);
  }
  pAllocator->FreeChunk(pSave);
}

//----- (004610AA) --------------------------------------------------------
void __fastcall PrepareToLoadODM(unsigned int bLoading, OutdoorCamera *a2)
{
  unsigned int v2; // edi@1
  OutdoorCamera *v3; // esi@1

  v2 = bLoading;
  v3 = a2;
  pGameLoadingUI_ProgressBar->Reset(0x1Bu);
  pSoundList->_4A9D79(0);
  uCurrentlyLoadedLevelType = (LEVEL_TYPE)2;
  ODM_LoadAndInitialize(pCurrentMapName.data(), v3);
  if ( !v2 )
    TeleportToStartingPoint(uLevel_StartingPointType);
  viewparams->_443365();
  PlayLevelMusic();
}
// 6BE35C: using guessed type int uLevel_StartingPointType;

//----- (00461103) --------------------------------------------------------
void __cdecl sub_461103()
{
  //GUIProgressBar *v0; // ebx@1
  //signed int v1; // ebp@1
  //char *v2; // esi@2
  __int16 v3; // cx@3
  int v4; // edx@8
  //size_t v5; // edi@14
  signed int v6; // esi@14
  //char *v7; // edx@15
  signed int v8; // ecx@16
  int v9; // ecx@23
  MonsterInfo *v10; // ebx@23
  //int *v11; // esi@23
  int v12; // esi@25
  int v13; // eax@26
  __int16 v14; // ax@41
  //signed int v15; // [sp+10h] [bp-4Ch]@1
  //signed int v16; // [sp+10h] [bp-4Ch]@14
  signed int v17; // [sp+14h] [bp-48h]@3
  signed int v18; // [sp+14h] [bp-48h]@23
  int v19; // [sp+18h] [bp-44h]@1
  signed int v20; // [sp+18h] [bp-44h]@14
  int v21[16]; // [sp+1Ch] [bp-40h]@17

  GenerateItemsInChest();
  //v0 = pGameLoadingUI_ProgressBar;
  pGameLoadingUI_ProgressBar->Progress();
  pParty->uFlags |= 2u;
  pParty->field_7B5_in_arena_quest = 0;
  //v1 = 0;
  dword_5C6DF8 = 1;
  pNPCStats->uNewlNPCBufPos = 0;
  v19 = pMapStats->GetMapInfo(pCurrentMapName.data());

  //v15 = 0;
  for (uint i = 0; i < uNumActors; ++i)
  //if ( (signed int)uNumActors > 0 )
  {
    auto pActor = &pActors[i];
    //v2 = (char *)&pActors[0].uNPC_ID;
    //do
    //{
      v3 = pActor->pMonsterInfo.uID;
      v17 = 0;
      if ( v3 >= 115 && v3 <= 186 || v3 >= 232 && v3 <= 249 )
        v17 = 1;
      //v1 = 0;
      v4 = (v3 - 1) % 3;
      if ( 2 == v4 )
      {
        if ( pActor->sNPC_ID && pActor->sNPC_ID < 5000 )
          continue;
      }
      else
      {
        if ( v4 != 1 )
        {
          if ( v4 != 0 || pActor->sNPC_ID )
            continue;
          goto LABEL_12;
        }
      }
      if ( pActor->sNPC_ID > 0 && pActor->sNPC_ID < 5000 )
        continue;
      if ( v17 )
      {
        pNPCStats->InitializeAdditionalNPCs(&pNPCStats->pAdditionalNPC[pNPCStats->uNewlNPCBufPos], v3, 0, v19);
        v14 = LOWORD(pNPCStats->uNewlNPCBufPos) + 5000;
        ++pNPCStats->uNewlNPCBufPos;
        pActor->sNPC_ID = v14;
        continue;
      }
LABEL_12:
      pActor->sNPC_ID = 0;
//LABEL_13:
      //++v15;
      //v2 += 836;
    //}
    //while ( v15 < (signed int)uNumActors );
  }

  pGameLoadingUI_ProgressBar->Progress();

  //v5 = uNumActors;
  v6 = 0;
  v20 = 0;
  //v16 = v1;

  for (uint i = 0; i < uNumActors; ++i)
  {
    auto pActor = &pActors[i];
    //v7 = (char *)&pActors[0].pMonsterInfo;
    //do
    //{
      v8 = 0;
      if ( v6 > 0 )
      {
        do
        {
          if ( v21[v8] == pActor->pMonsterInfo.uID - 1 )
            break;
          ++v8;
        }
        while ( v8 < v6 );
      }

      if ( v8 == v6 )
      {
        v21[v6++] = pActor->pMonsterInfo.uID - 1;
        v20 = v6;
        if ( v6 == 16 )
          break;
      }
      //++v16;
      //v7 += 836;
    //}
    //while ( v16 < (signed int)v5 );
  }

  pGameLoadingUI_ProgressBar->Progress();

  if ( v6 > 0 )
  {
    int _v0 = 0;
    do
    {
      v9 = v21[_v0];
      v18 = 4;
      v10 = &pMonsterStats->pInfos[v9 + 1];
      //v11 = (int *)pMonsterList->pMonsters[v9].pSoundSampleIDs;
      auto v11 = &pMonsterList->pMonsters[v9];
      do
      {
        pSoundList->LoadSound(v11->pSoundSampleIDs[4 - v18], 0);
        //v11 = (int *)((char *)v11 + 2);
        --v18;
      }
      while ( v18 );
      v12 = 0;
      do
        v13 = pSoundList->LoadSound(v12++ + word_4EE088_sound_ids[v10->uSpell1ID], 1);
      while ( v13 );
      ++_v0;
    }
    while ( _v0 < v6 );
    //v0 = pGameLoadingUI_ProgressBar;
    //v1 = 0;
  }

  pGameLoadingUI_ProgressBar->Progress();

  if ( dword_6BE368_debug_settings_2 & 4 )
    uNumActors = 0;
  if ( dword_6BE368_debug_settings_2 & 8 )
    uNumLevelDecorations = 0;
  sub_4613C4();

  pGameLoadingUI_ProgressBar->Progress();

  pIndoorCamera->pos.y = 0;
  pIndoorCamera->pos.x = 0;
  pIndoorCamera->pos.z = 100;
  pIndoorCamera->sRotationY = 0;
  pIndoorCamera->sRotationX = 0;
  viewparams->bRedrawGameUI = 1;
  uLevel_StartingPointType = MapStartPoint_Party;
  pSprites_LOD->_461397();
  pPaletteManager->LockTestAll();
  if ( pParty->pPickedItem.uItemID != 0 )
    pMouse->SetCursorBitmapFromItemID(pParty->pPickedItem.uItemID);
}

//----- (004613C4) --------------------------------------------------------
int __cdecl sub_4613C4()
{
  unsigned __int16 v0; // ax@1
  size_t v1; // ecx@1
  int v2; // esi@1
  int result; // eax@1
  LevelDecoration *v4; // edx@2
  int v5; // edi@4

  _6836C8_num_decorations_6807E8 = 0;
  v0 = pDecorationList->GetDecorIdByName("Event Trigger");
  v1 = uNumLevelDecorations;
  v2 = (signed __int16)v0;
  result = 0;
  if ( (signed int)uNumLevelDecorations > 0 )
  {
    v4 = pLevelDecorations.data();
    do
    {
      if ( v4->uDecorationDescID == v2 )
      {
        v5 = _6836C8_num_decorations_6807E8++;
        _6807E8_level_decorations_ids[v5] = result;
      }
      ++result;
      ++v4;
    }
    while ( result < (signed int)v1 );
  }
  return result;
}
// 6836C8: using guessed type int 6836C8_num_decorations_6807E8;

//----- (004621DA) --------------------------------------------------------
int __fastcall int_get_vector_length(signed int a1, signed int a2, signed int a3)
{
  signed int v3; // eax@2
  signed int v4; // eax@3
  signed int v5; // esi@4
  signed int v6; // esi@6

  if ( a1 < a2 )
  {
    v3 = a1;
    a1 = a2;
    a2 = v3;
  }
  v4 = a3;
  if ( a1 < a3 )
  {
    v5 = a1;
    a1 = a3;
    v4 = v5;
  }
  if ( a2 < v4 )
  {
    v6 = a2;
    a2 = v4;
    v4 = v6;
  }
  return (11 * a2 >> 5) + a1 + (v4 >> 2);
}

OPENFILENAMEA ofn;
//----- (0046271C) --------------------------------------------------------
void __cdecl crt_init_globals_46271C()
{
  ofn.lStructSize = 0x4Cu;
  ofn.hwndOwner = hWnd;
  ofn.hInstance = 0;
  ofn.lpstrFilter = "Indoor  BLV Files (*.blv)";
  ofn.lpstrCustomFilter = 0;
  ofn.nMaxCustFilter = 0;
  ofn.nFilterIndex = 0;
  ofn.lpstrFile = 0;
  ofn.nMaxFile = 260;
  ofn.nMaxFileTitle = 512;
  ofn.lpstrInitialDir = "levels";
  ofn.lpstrTitle = "Might and Magic® VII - Load Which Level?";
  ofn.Flags = 4;
  ofn.nFileOffset = 0;
  ofn.nFileExtension = 0;
  ofn.lpstrDefExt = "blv";
  ofn.lCustData = 0;
  ofn.lpfnHook = 0;
  ofn.lpTemplateName = 0;
  ofn.lpstrFileTitle = pTmpBuf.data();
}

//----- (004627B7) --------------------------------------------------------
void MainMenu_Loop()
{
  GUIButton *pButton; // eax@27
  unsigned int pControlParam; // ecx@35
  int v10; // ecx@36
  int v11; // ecx@37
  unsigned int pY; // [sp-18h] [bp-54h]@39
  Texture *pTexture; // [sp-14h] [bp-50h]@39
  GUIButton *pButton2; // [sp+0h] [bp-3Ch]@27
  GUIWindow *pWindow; // [sp+4h] [bp-38h]@11
  
  pCurrentScreen = SCREEN_GAME;

  pGUIWindow2 = 0;
  pAudioPlayer->StopChannels(-1, -1);
  pMouse->RemoveHoldingItem();

  pIcons_LOD->_inlined_sub2();

  pWindow_MainMenu = GUIWindow::Create(0, 0, 640, 480, WINDOW_MainMenu, 0, 0);
  auto pNew = pIcons_LOD->LoadTexturePtr("title_new", TEXTURE_16BIT_PALETTE);
  auto pLoad = pIcons_LOD->LoadTexturePtr("title_load", TEXTURE_16BIT_PALETTE);
  auto pCredits = pIcons_LOD->LoadTexturePtr("title_cred", TEXTURE_16BIT_PALETTE);
  auto pExit = pIcons_LOD->LoadTexturePtr("title_exit", TEXTURE_16BIT_PALETTE);

  pMainMenu_BtnNew     = pWindow_MainMenu->CreateButton(495, 172, pNew->uTextureWidth,     pNew->uTextureHeight,     1, 0, UIMSG_MainMenu_ShowPartyCreationWnd, 0, 'N', "", pNew, 0);
  pMainMenu_BtnLoad    = pWindow_MainMenu->CreateButton(495, 227, pLoad->uTextureWidth,    pLoad->uTextureHeight,    1, 0, UIMSG_MainMenu_ShowLoadWindow,       1, 'L', "", pLoad, 0);
  pMainMenu_BtnCredits = pWindow_MainMenu->CreateButton(495, 282, pCredits->uTextureWidth, pCredits->uTextureHeight, 1, 0, UIMSG_ShowCredits,                   2, 'C', "", pCredits, 0);
  pMainMenu_BtnExit    = pWindow_MainMenu->CreateButton(495, 337, pExit->uTextureWidth,    pExit->uTextureHeight,    1, 0, UIMSG_ExitToWindows,                 3, 0, "", pExit, 0);

  pTexture_PCX.Release();
  pTexture_PCX.Load("title.pcx", 0);
  SetCurrentMenuID(MENU_MAIN);
  SetForegroundWindow(hWnd);
  SendMessageW(hWnd, WM_ACTIVATEAPP, 1, 0);
  while (GetCurrentMenuID() == MENU_MAIN || GetCurrentMenuID() == MENU_SAVELOAD)
  {
    POINT pt;
    pMouse->GetCursorPos(&pt);
    pWindow = pWindow_MainMenu;
    if ( GetCurrentMenuID() == MENU_SAVELOAD)
    {
      if ( pCurrentScreen != SCREEN_LOADGAME )
      {
        pTexture_PCX.Release();
        pTexture_PCX.Load("lsave640.pcx", 0);
        pGUIWindow2 = GUIWindow::Create(0, 0, 640, 480, WINDOW_MainMenu, 0, 0);
        pCurrentScreen = SCREEN_LOADGAME;
        LoadUI_Load(0);
      }
      pWindow = pGUIWindow_CurrentMenu;
    }

    MSG msg;
    while ( PeekMessageA(&msg, 0, 0, 0, PM_REMOVE) )
    {
      if (msg.message == WM_QUIT)
        Game_DeinitializeAndTerminate(0);
      TranslateMessage(&msg);
      DispatchMessageA(&msg);
    }
    if (dword_6BE364_game_settings_1 & 0x0100)
    {
      WaitMessage();
    }
    else
    {
      pRenderer->BeginScene();
      pRenderer->DrawTextureRGB(0, 0, &pTexture_PCX);

      GUI_MainMenuMessageProc();
      GUI_UpdateWindows();

      if (GetCurrentMenuID() != MENU_MAIN)
      {
        if (GetCurrentMenuID() == MENU_LoadingProcInMainMenu)
        {
          pIcons_LOD->_4114F2();
          pGUIWindow_CurrentMenu->Release();
          pGUIWindow_CurrentMenu = 0;
          pCurrentScreen = SCREEN_GAME;
          viewparams->bRedrawGameUI = 1;
        }
      }
      else
      {
        if ( !ptr_507BDC )// ???
        {
          pButton = pWindow->pControlsHead;
          for ( pButton = pWindow->pControlsHead; pButton; pButton = pButton->pNext )
          {
           if ( pt.x >= (signed int)pButton->uX && pt.x <= (signed int)pButton->uZ
                && pt.y >= (signed int)pButton->uY && pt.y <= (signed int)pButton->uW
                && pWindow == pWindow_MainMenu )
           {
            pControlParam = pButton->msg_param;
            switch (pControlParam) // ïîäñâåòêà êíîïîê
            {
              case 0:
              pTexture = pNew;
              pY = 172;
              break;
              case 1:
              pTexture = pLoad;
              pY = 227;
              break;
              case 2:
              pTexture = pCredits;
              pY = 282;
              break;
              case 3:
              pTexture = pExit;
              pY = 337;
              break;
            }
            pRenderer->DrawTextureIndexed(495, pY, pTexture); //ïîäñâåòêà êíîïîê
           }
          }
        }
      }
      pRenderer->EndScene();
      pRenderer->Present();
    }
  }
  GUI_MainMenuMessageProc();
  pRenderer->BeginScene();
  GUI_UpdateWindows();
  pRenderer->EndScene();
  pRenderer->Present();
  pTexture_PCX.Release();
  if ( pGUIWindow2 )
  {
    pGUIWindow2->Release();
    pGUIWindow2 = 0;
  }
  pWindow_MainMenu->Release();
  pIcons_LOD->_4114F2();
}

//----- (004637EB) --------------------------------------------------------
int __stdcall aWinProc(HWND hWnd, UINT Msg, WPARAM wParam, unsigned int lParam)
{
  //unsigned int v4; // esi@1
  Render *v5; // ecx@14
  HANDLE v6; // eax@32
  Keyboard *v7; // eax@33
  //HDC v9; // edi@41
  HDC v10; // edi@50
  int v11; // esi@50
  //char v12; // zf@132
  signed int v13; // eax@135
  int v14; // eax@139
  int v15; // eax@140
  int v16; // eax@141
  int v17; // eax@142
  int v18; // eax@150
  int v19; // eax@151
  int v20; // eax@152
  int v21; // eax@161
  int v22; // eax@162
  int v23; // eax@163
  int v24; // eax@170
  int v25; // eax@171
  int v26; // eax@172
  char v27; // al@174
  //bool v28; // ebx@201
  char v29; // dl@209
  char v30; // cl@210
  bool v31; // ebx@211
  void *v32; // ebx@214
  float v33; // ST04_4@246
  float v34; // ST04_4@254
  HWND v35; // [sp+8h] [bp-64h]@103
  UINT v36; // [sp+Ch] [bp-60h]@103
  WPARAM v37; // [sp+10h] [bp-5Ch]@103
  LPARAM v38; // [sp+14h] [bp-58h]@103
  struct tagPAINTSTRUCT Paint; // [sp+24h] [bp-48h]@13
  int pXY[2]; // [sp+64h] [bp-8h]@261
  int a2; // [sp+7Ch] [bp+10h]@50
  
  switch (Msg)
  {
    case WM_SETTEXT: return DefWindowProcW(hWnd, Msg, wParam, lParam);
    case WM_CHAR:
    {
      if (!pKeyActionMap->_459F10(wParam) && !viewparams->field_4C)
        GUI_HandleHotkey(wParam);
    }
    return DefWindowProcA(hWnd, Msg, wParam, lParam);

    case WM_COMMAND:
    {
      switch (wParam)
      {
        case 103:  pRenderer->SavePCXScreenshot();  return 0;

        case 101:  // Quit game
        case 40001:
          SendMessageA(::hWnd, WM_DESTROY, 0, 0);
        return 0;


        case 104:
          pRenderer->ChangeBetweenWinFullscreenModes();
          if ( pArcomageGame->bGameInProgress )
            pArcomageGame->field_F6 = 1;
        return 0;

        //SubMenu "Party"
        case 40007:  pParty->SetGold(pParty->uNumGold + 10000); return 0;
        case 40008:  GivePartyExp(20000);  return 0;
        case 40013:  pParty->SetGold(0);   return 0;

        case 40059:
          for (uint i = 0; i < 4; ++i)
            pParty->pPlayers[i].uSkillPoints = 50;
        return 0;
        
        case 40029:  pPlayers[uActiveCharacter]->SetPertified(true);  return 0;
        case 40030:  pPlayers[uActiveCharacter]->SetWeak(true);       return 0;
        case 40031:  pPlayers[uActiveCharacter]->SetPoison3(true);    return 0;
        case 40032:  pPlayers[uActiveCharacter]->SetPoison2(true);    return 0;
        case 40033:  pPlayers[uActiveCharacter]->SetPoison1(true);    return 0;
        case 40034:  pPlayers[uActiveCharacter]->SetDisease3(true);   return 0;
        case 40035:  pPlayers[uActiveCharacter]->SetDisease2(true);   return 0;
        case 40036:  pPlayers[uActiveCharacter]->SetDisease1(true);   return 0;
        case 40037:  pPlayers[uActiveCharacter]->SetCursed(true);     return 0;
        case 40038:  pPlayers[uActiveCharacter]->SetInsane(true);     return 0;
        case 40039:  pPlayers[uActiveCharacter]->SetDrunk(true);      return 0;
        case 40040:  pPlayers[uActiveCharacter]->SetUnconcious(true); return 0;
        case 40041:  pPlayers[uActiveCharacter]->SetDead(true);       return 0;
        case 40042:  pPlayers[uActiveCharacter]->SetEradicated(true); return 0;
        case 40043:  pPlayers[uActiveCharacter]->SetAsleep(true);     return 0;
        case 40044:  pPlayers[uActiveCharacter]->SetAfraid(true);     return 0;
        case 40045:  pPlayers[uActiveCharacter]->SetParalyzed(true);  return 0;
        case 40073:  pPlayers[uActiveCharacter]->SetZombie(true);     return 0;

        case 40006:  pParty->SetFood(pParty->uNumFoodRations + 20);   return 0;

        case 40062:
          pParty->alignment = PartyAlignment_Good;
          SetUserInterface(pParty->alignment, true);
          return 0;
        case 40063:
          pParty->alignment = PartyAlignment_Neutral;
          SetUserInterface(pParty->alignment, true);
          return 0;
        case 40064:
          pParty->alignment = PartyAlignment_Evil;
          SetUserInterface(pParty->alignment, true);
          return 0;

        //SubMenu "Time"
        case 40009:  pParty->uTimePlayed += Timer::Day;   return 0;
        case 40010:  pParty->uTimePlayed += Timer::Week;   return 0;
        case 40011:  pParty->uTimePlayed += Timer::Month;   return 0;
        case 40012:  pParty->uTimePlayed += Timer::Year;   return 0;

        //SubMenu "Items"
        case 40015:
        {
          int pItemID = rand() % 500;
          for ( uint i = 0; i < 500; ++i )
          {
            if ( pItemID + i > 499 )
              pItemID = 0;
            if ( pItemsTable->pItems[pItemID + i].uItemID_Rep_St == 1 )
            {
              pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
              return 0;
            }
          }
        }
        return 0;
        case 40016:
        {
          int pItemID = rand() % 500;
          for ( uint i = 0; i < 500; ++i )
          {
            if ( pItemID + i > 499 )
              pItemID = 0;
            if ( pItemsTable->pItems[pItemID + i].uItemID_Rep_St == 2 )
            {
              pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
              return 0;
            }
          }
        }
        return 0;
        case 40017:
        {
          int pItemID = rand() % 500;
          for ( uint i = 0; i < 500; ++i )
          {
            if ( pItemID + i > 499 )
              pItemID = 0;
            if ( pItemsTable->pItems[pItemID + i].uItemID_Rep_St == 3 )
            {
              pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
              return 0;
            }
          }
        }
        return 0;
        case 40018:
        {
          int pItemID = rand() % 500;
          for ( uint i = 0; i < 500; ++i )
          {
            if ( pItemID + i > 499 )
              pItemID = 0;
            if ( pItemsTable->pItems[pItemID + i].uItemID_Rep_St == 4 )
            {
              pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
              return 0;
            }
          }
        }
        return 0;
        case 40019:
        {
          int pItemID = rand() % 500;
          for ( uint i = 0; i < 500; ++i )
          {
            if ( pItemID + i > 499 )
              pItemID = 0;
            if ( pItemsTable->pItems[pItemID + i].uItemID_Rep_St == 5 )
            {
              pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
              return 0;
            }
          }
        }
        return 0;
        case 40020:
        {
          int pItemID = rand() % 500;
          for ( uint i = 0; i < 500; ++i )
          {
            if ( pItemID + i > 499 )
              pItemID = 0;
            if ( pItemsTable->pItems[pItemID + i].uItemID_Rep_St == 6 )
            {
              pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
              return 0;
            }
          }
        }
        return 0;
        case 40061:
        {
          int pItemID = rand() % 500;
          for ( uint i = 0; i < 500; ++i )
          {
            if ( pItemID + i > 499 )
              pItemID = 0;
            if ( pItemsTable->pItems[pItemID + i].uItemID_Rep_St > 6 )
            {
              pPlayers[uActiveCharacter]->AddItem(-1, pItemID + i);
              return 0;
            }
          }
        }
        return 0;

      }
    }
    return DefWindowProcA(hWnd, Msg, wParam, lParam);
  };

  if ( Msg > WM_SYSCOMMAND )
  {
    switch ( Msg )
    {
      case WM_DEVICECHANGE:
        if ( wParam == 0x8000 )
          PostMessageA(hInsertCDWindow, WM_CHOOSEFONT_GETLOGFONT, 0, 0);
        return 0;
      case WM_SIZING:
        return 1;
      case WM_LBUTTONDOWN:
        if ( pArcomageGame->bGameInProgress )
        {
          pArcomageGame->stru1.field_0 = 7;
          ArcomageGame::OnMouseClick(0, 1);
          return DefWindowProcA(hWnd, Msg, wParam, lParam);
        }
        goto __handle_mouse_click;

      case WM_RBUTTONDOWN:
        v31 = 0;
        if ( !pArcomageGame->bGameInProgress )
          //goto LABEL_240;
        {
          if ( pVideoPlayer->pVideoFrame.pPixels != (unsigned __int16 *)v31 )
            pVideoPlayer->bStopBeforeSchedule = 1;

          pMouse->SetMouseClick((unsigned __int16)lParam, lParam >> 16);
          if (pGame)
          {
            v33 = pGame->pIndoorCameraD3D->GetPickDepth();
            pGame->PickMouse(v33, (unsigned __int16)lParam, lParam >> 16, v31, &vis_sprite_filter_2, &vis_door_filter);
          }

            sub_416D62_ShowPopupWindow_MonsterRecord_ItemInfo_etcsub_416D62(0);
            return DefWindowProcA(hWnd, Msg, wParam, lParam);

        }

        pArcomageGame->stru1.field_0 = 8;
        ArcomageGame::OnMouseClick(1, 1);
        return DefWindowProcA(hWnd, Msg, wParam, lParam);
      case WM_LBUTTONUP:
        v32 = 0;
        if ( !pArcomageGame->bGameInProgress )
          //goto LABEL_218;
        {
          back_to_game();
          return DefWindowProcA(hWnd, Msg, wParam, lParam);
        }
        pArcomageGame->stru1.field_0 = 3;
        ArcomageGame::OnMouseClick(0, 0);
        return DefWindowProcA(hWnd, Msg, wParam, lParam);
      case WM_RBUTTONUP:
        v32 = 0;
        if ( !pArcomageGame->bGameInProgress )
        {
//LABEL_218:

          back_to_game();
          return DefWindowProcA(hWnd, Msg, wParam, lParam);
        }
        pArcomageGame->stru1.field_0 = 4;
        v29 = 0;
        //goto LABEL_262;
        v30 = 1;
        ArcomageGame::OnMouseClick(v30, v29 != 0);
        return DefWindowProcA(hWnd, Msg, wParam, lParam);

      case WM_LBUTTONDBLCLK:
        if ( pArcomageGame->bGameInProgress )
        {
          pArcomageGame->stru1.field_0 = 7;
          return DefWindowProcA(hWnd, Msg, wParam, lParam);
        }
        
__handle_mouse_click:
        if ( pVideoPlayer->pVideoFrame.pPixels )
          pVideoPlayer->bStopBeforeSchedule = 1;

          pMouse->SetMouseClick((unsigned __int16)lParam, lParam >> 16);

        if (GetCurrentMenuID() != MENU_CREATEPARTY)
          pMouse->SetMouseClick((unsigned __int16)lParam, lParam >> 16);
        else
        {
          UI_OnKeyDown(VK_SELECT);
          pMouse->SetMouseClick((unsigned __int16)lParam, lParam >> 16);
        }


          if (pGame)
            pGame->PickMouse(512.0, (unsigned __int16)lParam, lParam >> 16, false, &vis_sprite_filter_3, &vis_door_filter);

          UI_OnMouseLeftClick(0);

        return DefWindowProcA(hWnd, Msg, wParam, lParam);

      case WM_RBUTTONDBLCLK:
        v31 = 0;
        if ( !pArcomageGame->bGameInProgress )
        {
//LABEL_240:
          if ( pVideoPlayer->pVideoFrame.pPixels != (unsigned __int16 *)v31 )
            pVideoPlayer->bStopBeforeSchedule = 1;

            pMouse->SetMouseClick((unsigned __int16)lParam, lParam >> 16);
          if (pGame)
          {
            v33 = pGame->pIndoorCameraD3D->GetPickDepth();
            pGame->PickMouse(v33, (unsigned __int16)lParam, lParam >> 16, v31, &vis_sprite_filter_2, &vis_door_filter);
          }

            sub_416D62_ShowPopupWindow_MonsterRecord_ItemInfo_etcsub_416D62(0);
            return DefWindowProcA(hWnd, Msg, wParam, lParam);

        }
        pArcomageGame->stru1.field_0 = 8;
        return DefWindowProcA(hWnd, Msg, wParam, lParam);
      case WM_MBUTTONDOWN:
        if ( pRenderer->pRenderD3D )
        {
          if ( pGame )
          {
            v34 = pGame->pIndoorCameraD3D->GetPickDepth();
            pGame->PickMouse(v34, (unsigned __int16)lParam, lParam >> 16, 1, &vis_sprite_filter_3, &vis_face_filter);
            return DefWindowProcA(hWnd, Msg, wParam, lParam);
          }
        }
        if ( !pGame )
          //goto _def_wnd_proc;
          return DefWindowProcA(hWnd, Msg, wParam, lParam);
        sub_417871(0);
        return DefWindowProcA(hWnd, Msg, wParam, lParam);
      case WM_MOUSEMOVE:
        if ( pArcomageGame->bGameInProgress )
        {
          pXY[0] = (unsigned __int16)lParam;
          pXY[1] = lParam >> 16;
          ArcomageGame::OnMouseMove((POINT *)pXY);
          ArcomageGame::OnMouseClick(0, wParam & 1);
          v29 = (wParam >> 1) & 1;
          ArcomageGame::OnMouseClick(1, v29 != 0);
        }
        else
        {
          pMouse->SetMouseClick((unsigned __int16)lParam, lParam >> 16);
        }
        return DefWindowProcA(hWnd, Msg, wParam, lParam);
      default:
        //goto _def_wnd_proc;
        return DefWindowProcA(hWnd, Msg, wParam, lParam);
    }
  }
  if ( Msg == WM_SYSCOMMAND )
  {
    if ( wParam == SC_SCREENSAVE || wParam == SC_MONITORPOWER )
      return 0;
    //goto _def_wnd_proc;
    return DefWindowProcA(hWnd, Msg, wParam, lParam);
  }
  if ( Msg > WM_ACTIVATEAPP )
  {
    if ( Msg == WM_WINDOWPOSCHANGED )
    {
      if (pVideoPlayer)
      {
        if (pVideoPlayer->AnyMovieLoaded() && pVideoPlayer->pBinkBuffer)
        {
          BinkBufferSetOffset(pVideoPlayer->pBinkBuffer, 0, 0);
          return DefWindowProcA(hWnd, Msg, wParam, lParam);
        }
      }
      //goto _def_wnd_proc;
      return DefWindowProcA(hWnd, Msg, wParam, lParam);
    }
    if ( Msg != WM_KEYFIRST )
    {
      if ( Msg == WM_KEYUP )
      {
        if ( wParam == VK_CONTROL )
        {
          dword_507B98_ctrl_pressed = 0;
          return DefWindowProcA(hWnd, Msg, wParam, lParam);
        }
        //goto _def_wnd_proc;
        return DefWindowProcA(hWnd, Msg, wParam, lParam);
      }
        return DefWindowProcA(hWnd, Msg, wParam, lParam);
    }
    if ( uGameMenuUI_CurentlySelectedKeyIdx != -1 )
    {
      pKeyActionMap->_459F10(wParam);
      return DefWindowProcA(hWnd, Msg, wParam, lParam);
    }
    if ( !pArcomageGame->bGameInProgress )
    {
      if ( pVideoPlayer->pVideoFrame.pPixels )
        pVideoPlayer->bStopBeforeSchedule = 1;
      if ( wParam == VK_RETURN )
      {
        if ( !viewparams->field_4C )
          UI_OnKeyDown(wParam);
        return 0;
      }
      if ( wParam == VK_CONTROL )
      {
        dword_507B98_ctrl_pressed = 1;
        return 0;
      }
      if ( wParam == VK_ESCAPE )
      {
        pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, window_SpeakInHouse != 0, 0);
        return 0;
      }
      if ( wParam <= VK_HOME )
        return 0;
      if ( wParam > VK_DOWN )
      {
        if ( wParam != VK_F4 || pVideoPlayer->AnyMovieLoaded() )
          return 0;
        SendMessageA(hWnd, WM_COMMAND, 104, 0);
        return 0;
      }
      if ( wParam >= VK_LEFT && wParam <= VK_DOWN )
      {
        if ( pCurrentScreen != SCREEN_GAME && pCurrentScreen != SCREEN_PRESS_ESCAPE_MESSAGE )
        {
          if ( !viewparams->field_4C )
            UI_OnKeyDown(wParam);
          return 0;
        }
      }
      if ( pCurrentScreen != SCREEN_GAME && pCurrentScreen != SCREEN_PRESS_ESCAPE_MESSAGE )
        return 0;
    }
    pArcomageGame->stru1.field_0 = 1;
    if ( (unsigned __int16)GetAsyncKeyState(VK_SHIFT) >> 8 >= 0 )
      v27 = MapVirtualKeyA((unsigned __int16)wParam, 2u);
    else
    {
      v13 = (unsigned __int16)MapVirtualKeyA((unsigned __int16)wParam, 2u);
      if ( (signed int)(unsigned __int16)v13 > 54 )
      {
        if ( v13 > 61 )
        {
          if ( v13 == 91 )
          {
            LOBYTE(pArcomageGame->stru1.field_8) = 123;
            //goto LABEL_181;
            if ( wParam == 27 )
            {
              pArcomageGame->GameOver = 1;
              pArcomageGame->field_F4 = 1;
              pArcomageGame->uGameResult = 2;
              pArcomageGame->field_B0 = -2;
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            if ( wParam != 114 )
            {
              if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
                SendMessageA(hWnd, 0x111u, 0x68u, 0);
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            SendMessageA(hWnd, WM_COMMAND, 103, 0);
            return 0;
          }
          if ( v13 == 92 )
          {
            LOBYTE(pArcomageGame->stru1.field_8) = 124;
            //goto LABEL_181;
            if ( wParam == 27 )
            {
              pArcomageGame->GameOver = 1;
              pArcomageGame->field_F4 = 1;
              pArcomageGame->uGameResult = 2;
              pArcomageGame->field_B0 = -2;
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            if ( wParam != 114 )
            {
              if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
                SendMessageA(hWnd, 0x111u, 0x68u, 0);
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            SendMessageA(hWnd, WM_COMMAND, 103, 0);
            return 0;
          }
          if ( v13 == 93 )
          {
            LOBYTE(pArcomageGame->stru1.field_8) = 125;
            //goto LABEL_181;
            if ( wParam == 27 )
            {
              pArcomageGame->GameOver = 1;
              pArcomageGame->field_F4 = 1;
              pArcomageGame->uGameResult = 2;
              pArcomageGame->field_B0 = -2;
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            if ( wParam != 114 )
            {
              if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
                SendMessageA(hWnd, 0x111u, 0x68u, 0);
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            SendMessageA(hWnd, WM_COMMAND, 103, 0);
            return 0;
          }
          if ( v13 == 96 )
          {
            LOBYTE(pArcomageGame->stru1.field_8) = 126;
            //goto LABEL_181;
            if ( wParam == 27 )
            {
              pArcomageGame->GameOver = 1;
              pArcomageGame->field_F4 = 1;
              pArcomageGame->uGameResult = 2;
              pArcomageGame->field_B0 = -2;
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            if ( wParam != 114 )
            {
              if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
                SendMessageA(hWnd, 0x111u, 0x68u, 0);
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            SendMessageA(hWnd, WM_COMMAND, 103, 0);
            return 0;
          }
        }
        else
        {
          if ( v13 == 61 )
          {
            LOBYTE(pArcomageGame->stru1.field_8) = 43;
            //goto LABEL_181;
            if ( wParam == 27 )
            {
              pArcomageGame->GameOver = 1;
              pArcomageGame->field_F4 = 1;
              pArcomageGame->uGameResult = 2;
              pArcomageGame->field_B0 = -2;
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            if ( wParam != 114 )
            {
              if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
                SendMessageA(hWnd, 0x111u, 0x68u, 0);
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            SendMessageA(hWnd, WM_COMMAND, 103, 0);
            return 0;
          }
          if ( v13 == 55 )
          {
            LOBYTE(pArcomageGame->stru1.field_8) = 38;
            //goto LABEL_181;
            if ( wParam == 27 )
            {
              pArcomageGame->GameOver = 1;
              pArcomageGame->field_F4 = 1;
              pArcomageGame->uGameResult = 2;
              pArcomageGame->field_B0 = -2;
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            if ( wParam != 114 )
            {
              if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
                SendMessageA(hWnd, 0x111u, 0x68u, 0);
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            SendMessageA(hWnd, WM_COMMAND, 103, 0);
            return 0;
          }
          if ( v13 == 56 )
          {
            LOBYTE(pArcomageGame->stru1.field_8) = 42;
            //goto LABEL_181;
            if ( wParam == 27 )
            {
              pArcomageGame->GameOver = 1;
              pArcomageGame->field_F4 = 1;
              pArcomageGame->uGameResult = 2;
              pArcomageGame->field_B0 = -2;
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            if ( wParam != 114 )
            {
              if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
                SendMessageA(hWnd, 0x111u, 0x68u, 0);
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            SendMessageA(hWnd, WM_COMMAND, 103, 0);
            return 0;
          }
          if ( v13 == 57 )
          {
            LOBYTE(pArcomageGame->stru1.field_8) = 40;
            //goto LABEL_181;
            if ( wParam == 27 )
            {
              pArcomageGame->GameOver = 1;
              pArcomageGame->field_F4 = 1;
              pArcomageGame->uGameResult = 2;
              pArcomageGame->field_B0 = -2;
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            if ( wParam != 114 )
            {
              if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
                SendMessageA(hWnd, 0x111u, 0x68u, 0);
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            SendMessageA(hWnd, WM_COMMAND, 103, 0);
            return 0;
          }
          if ( v13 == 59 )
          {
            LOBYTE(pArcomageGame->stru1.field_8) = 58;
            //goto LABEL_181;
            if ( wParam == 27 )
            {
              pArcomageGame->GameOver = 1;
              pArcomageGame->field_F4 = 1;
              pArcomageGame->uGameResult = 2;
              pArcomageGame->field_B0 = -2;
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            if ( wParam != 114 )
            {
              if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
                SendMessageA(hWnd, 0x111u, 0x68u, 0);
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            SendMessageA(hWnd, WM_COMMAND, 103, 0);
            return 0;
          }
        }
      }
      else
      {
        if ( (unsigned __int16)v13 == 54 )
        {
          LOBYTE(pArcomageGame->stru1.field_8) = 94;
          //goto LABEL_181;
          if ( wParam == 27 )
          {
            pArcomageGame->GameOver = 1;
            pArcomageGame->field_F4 = 1;
            pArcomageGame->uGameResult = 2;
            pArcomageGame->field_B0 = -2;
            //goto _def_wnd_proc;
            return DefWindowProcA(hWnd, Msg, wParam, lParam);
          }
          if ( wParam != 114 )
          {
            if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
              SendMessageA(hWnd, 0x111u, 0x68u, 0);
            //goto _def_wnd_proc;
            return DefWindowProcA(hWnd, Msg, wParam, lParam);
          }
          SendMessageA(hWnd, WM_COMMAND, 103, 0);
          return 0;
        }
        if ( v13 > 49 )
        {
          if ( v13 == 50 )
          {
            LOBYTE(pArcomageGame->stru1.field_8) = 64;
            //goto LABEL_181;
            if ( wParam == 27 )
            {
              pArcomageGame->GameOver = 1;
              pArcomageGame->field_F4 = 1;
              pArcomageGame->uGameResult = 2;
              pArcomageGame->field_B0 = -2;
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            if ( wParam != 114 )
            {
              if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
                SendMessageA(hWnd, 0x111u, 0x68u, 0);
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            SendMessageA(hWnd, WM_COMMAND, 103, 0);
            return 0;
          }
          if ( v13 == 51 )
          {
            LOBYTE(pArcomageGame->stru1.field_8) = 35;
            //goto LABEL_181;
            if ( wParam == 27 )
            {
              pArcomageGame->GameOver = 1;
              pArcomageGame->field_F4 = 1;
              pArcomageGame->uGameResult = 2;
              pArcomageGame->field_B0 = -2;
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            if ( wParam != 114 )
            {
              if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
                SendMessageA(hWnd, 0x111u, 0x68u, 0);
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            SendMessageA(hWnd, WM_COMMAND, 103, 0);
            return 0;
          }
          if ( v13 == 52 )
          {
            LOBYTE(pArcomageGame->stru1.field_8) = 36;
            //goto LABEL_181;
            if ( wParam == 27 )
            {
              pArcomageGame->GameOver = 1;
              pArcomageGame->field_F4 = 1;
              pArcomageGame->uGameResult = 2;
              pArcomageGame->field_B0 = -2;
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            if ( wParam != 114 )
            {
              if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
                SendMessageA(hWnd, 0x111u, 0x68u, 0);
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            SendMessageA(hWnd, WM_COMMAND, 103, 0);
            return 0;
          }
          if ( v13 == 53 )
          {
            LOBYTE(pArcomageGame->stru1.field_8) = 37;
            //goto LABEL_181;
            if ( wParam == 27 )
            {
              pArcomageGame->GameOver = 1;
              pArcomageGame->field_F4 = 1;
              pArcomageGame->uGameResult = 2;
              pArcomageGame->field_B0 = -2;
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            if ( wParam != 114 )
            {
              if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
                SendMessageA(hWnd, 0x111u, 0x68u, 0);
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            SendMessageA(hWnd, WM_COMMAND, 103, 0);
            return 0;
          }
        }
        else
        {
          if ( v13 == 49 )
          {
            LOBYTE(pArcomageGame->stru1.field_8) = 33;
            //goto LABEL_181;
            if ( wParam == 27 )
            {
              pArcomageGame->GameOver = 1;
              pArcomageGame->field_F4 = 1;
              pArcomageGame->uGameResult = 2;
              pArcomageGame->field_B0 = -2;
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            if ( wParam != 114 )
            {
              if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
                SendMessageA(hWnd, 0x111u, 0x68u, 0);
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            SendMessageA(hWnd, WM_COMMAND, 103, 0);
            return 0;
          }
          if ( v13 == 39 )
          {
            LOBYTE(pArcomageGame->stru1.field_8) = 34;
            //goto LABEL_181;
            if ( wParam == 27 )
            {
              pArcomageGame->GameOver = 1;
              pArcomageGame->field_F4 = 1;
              pArcomageGame->uGameResult = 2;
              pArcomageGame->field_B0 = -2;
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            if ( wParam != 114 )
            {
              if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
                SendMessageA(hWnd, 0x111u, 0x68u, 0);
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            SendMessageA(hWnd, WM_COMMAND, 103, 0);
            return 0;
          }
          if ( v13 == 44 )
          {
            LOBYTE(pArcomageGame->stru1.field_8) = 60;
            //goto LABEL_181;
            if ( wParam == 27 )
            {
              pArcomageGame->GameOver = 1;
              pArcomageGame->field_F4 = 1;
              pArcomageGame->uGameResult = 2;
              pArcomageGame->field_B0 = -2;
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            if ( wParam != 114 )
            {
              if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
                SendMessageA(hWnd, 0x111u, 0x68u, 0);
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            SendMessageA(hWnd, WM_COMMAND, 103, 0);
            return 0;
          }
          if ( v13 == 46 )
          {
            LOBYTE(pArcomageGame->stru1.field_8) = 62;
            //goto LABEL_181;
            if ( wParam == 27 )
            {
              pArcomageGame->GameOver = 1;
              pArcomageGame->field_F4 = 1;
              pArcomageGame->uGameResult = 2;
              pArcomageGame->field_B0 = -2;
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            if ( wParam != 114 )
            {
              if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
                SendMessageA(hWnd, 0x111u, 0x68u, 0);
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            SendMessageA(hWnd, WM_COMMAND, 103, 0);
            return 0;
          }
          if ( v13 == 47 )
          {
            LOBYTE(pArcomageGame->stru1.field_8) = 63;
            //goto LABEL_181;
            if ( wParam == 27 )
            {
              pArcomageGame->GameOver = 1;
              pArcomageGame->field_F4 = 1;
              pArcomageGame->uGameResult = 2;
              pArcomageGame->field_B0 = -2;
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            if ( wParam != 114 )
            {
              if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
                SendMessageA(hWnd, 0x111u, 0x68u, 0);
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            SendMessageA(hWnd, WM_COMMAND, 103, 0);
            return 0;
          }
          if ( v13 == 48 )
          {
            LOBYTE(pArcomageGame->stru1.field_8) = 41;
//LABEL_181:
            if ( wParam == 27 )
            {
              pArcomageGame->GameOver = 1;
              pArcomageGame->field_F4 = 1;
              pArcomageGame->uGameResult = 2;
              pArcomageGame->field_B0 = -2;
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            if ( wParam != 114 )
            {
              if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
                SendMessageA(hWnd, 0x111u, 0x68u, 0);
              //goto _def_wnd_proc;
              return DefWindowProcA(hWnd, Msg, wParam, lParam);
            }
            SendMessageA(hWnd, WM_COMMAND, 103, 0);
            return 0;
          }
        }
      }
      v27 = MapVirtualKeyA((unsigned __int16)wParam, 2u);
    }
    LOBYTE(pArcomageGame->stru1.field_8) = v27;
    //goto LABEL_181;
    if ( wParam == 27 )
    {
      pArcomageGame->GameOver = 1;
      pArcomageGame->field_F4 = 1;
      pArcomageGame->uGameResult = 2;
      pArcomageGame->field_B0 = -2;
      //goto _def_wnd_proc;
      return DefWindowProcA(hWnd, Msg, wParam, lParam);
    }
    if ( wParam != 114 )
    {
      if ( wParam == 115 && !pVideoPlayer->AnyMovieLoaded() )
      SendMessageA(hWnd, 0x111u, 0x68u, 0);
      //goto _def_wnd_proc;
      return DefWindowProcA(hWnd, Msg, wParam, lParam);
    }
    SendMessageA(hWnd, WM_COMMAND, 103, 0);
    return 0;
  }
  if ( Msg == WM_ACTIVATEAPP )
  {
    if ( wParam && (GetForegroundWindow() == hWnd || GetForegroundWindow() == hInsertCDWindow) )
    {
      if ( BYTE1(dword_6BE364_game_settings_1) & 1 )
      {
        dword_4E98BC_bApplicationActive = 1;
        if ( pRenderer->bWindowMode )
        {
          v10 = GetDC(0);
          a2 = GetDeviceCaps(v10, BITSPIXEL);
          v11 = GetDeviceCaps(v10, PLANES);
          ReleaseDC(0, v10);
          if ( a2 != 16 || v11 != 1 )
            Abortf(pGlobalTXT_LocalizationStrings[62]);
        }
        BYTE1(dword_6BE364_game_settings_1) &= 0xFEu;

        if ( pArcomageGame->bGameInProgress )
        {
          pArcomageGame->field_F9 = 1;
        }
        else
        {
          if ( BYTE1(dword_6BE364_game_settings_1) & 2 )
            BYTE1(dword_6BE364_game_settings_1) &= 0xFDu;
          else
            pEventTimer->Resume();
          if ( BYTE1(dword_6BE364_game_settings_1) & 4 )
            BYTE1(dword_6BE364_game_settings_1) &= 0xFBu;
          else
            pMiscTimer->Resume();

          viewparams->bRedrawGameUI = true;
          if ( pVideoPlayer->pSmackerMovie )
          {
            pRenderer->RestoreFrontBuffer();
            pRenderer->_4A184C();
            pVideoPlayer->_4BF5B2();
          }
        }
        if ( pAudioPlayer->hAILRedbook && !bGameoverLoop && !pVideoPlayer->pSmackerMovie )
          AIL_redbook_resume(pAudioPlayer->hAILRedbook);
      }
    }
    else
    {
      if ( !(dword_6BE364_game_settings_1 & 0x100) )
      {
        while(initing); //ADDED spinlock to allow int players ets! Gloval
          dword_4E98BC_bApplicationActive = 0;
        if ( (pVideoPlayer->pSmackerMovie || pVideoPlayer->pBinkMovie) && pVideoPlayer->bPlayingMovie )
          pVideoPlayer->bStopBeforeSchedule = 1;

        if ( pRenderer->bUserDirect3D && pRenderer->uAcquiredDirect3DDevice == 1 )
          SetWindowPos(::hWnd, (HWND)0xFFFFFFFE, 0, 0, 0, 0, 0x18u);
        ClipCursor(0);
        dword_6BE364_game_settings_1 |= 0x100u;
        if ( pEventTimer->bPaused )
          BYTE1(dword_6BE364_game_settings_1) |= 2u;
        else
          pEventTimer->Pause();
        if ( pMiscTimer->bPaused )
          BYTE1(dword_6BE364_game_settings_1) |= 4u;
        else
          pMiscTimer->Pause();

        pAudioPlayer->StopChannels(-1, -1);
        if ( pAudioPlayer->hAILRedbook )
          AIL_redbook_pause(pAudioPlayer->hAILRedbook);
      }
    }
    return 0;
  }
  if (Msg == WM_CREATE)
  {
    auto hDC = GetDC(hWnd);
    {
      if (GetDeviceCaps(hDC, BITSPIXEL) < 8)
      {
        ReleaseDC(hWnd, hDC);
        Log::Warning(L"You must be running in 256 color mode or higher.");
        Abortf("You must be running in 256 color mode or higher. You can change the screen depth with the control panel display icon.");
      }
    }
    ReleaseDC(hWnd, hDC);
    return 0;
  }
  if ( Msg == WM_DESTROY )
  {
    v6 = GetCurrentProcess();
    SetPriorityClass(v6, 0x20u);
    if ( pGame )
    {

    }

    PostQuitMessage(0);
    return 0;
  }
  if ( Msg == WM_SETFOCUS )
  {
    if ( ::hWnd == (HWND)wParam )
    {
      dword_4E98BC_bApplicationActive = 0;
      if ( pRenderer->bUserDirect3D && pRenderer->uAcquiredDirect3DDevice == 1 )
        SetWindowPos(::hWnd, (HWND)0xFFFFFFFE, 0, 0, 0, 0, 0x18u);
      ClipCursor(0);

    }
//_def_wnd_proc:
    return DefWindowProcA(hWnd, Msg, wParam, lParam);
  }
  if ( Msg != WM_KILLFOCUS )
  {
    if ( Msg == WM_PAINT )
    {
      if ( !GetUpdateRect(hWnd, 0, 0) || !dword_4E98BC_bApplicationActive && !pRenderer->bWindowMode )
        return 0;
      BeginPaint(hWnd, &Paint);
      if ( pArcomageGame->bGameInProgress )
      {
        pArcomageGame->field_F9 = 1;
        v5 = pRenderer;
      }
      else
      {
        if ( !pRenderer->pRenderD3D && !pRenderer->UsingDirect3D() || !AreRenderSurfacesOk() )
          //goto LABEL_20;
        {
          EndPaint(hWnd, &Paint);
          return 0;
        }
        v5 = pRenderer;
      }
      pRenderer->Present();
//LABEL_20:
      EndPaint(hWnd, &Paint);
      return 0;
    }
    //goto _def_wnd_proc;
    return DefWindowProcA(hWnd, Msg, wParam, lParam);
  }
  if ( ::hWnd != (HWND)wParam || (dword_4E98BC_bApplicationActive = 1, pRenderer->bWindowMode) || true )
    return DefWindowProcA(hWnd, Msg, wParam, lParam);

}

//----- (00464479) --------------------------------------------------------
void __cdecl ResetCursor_Palettes_LODs_Level_Audio_SFT_Windows()
{
  int v0; // esi@9

  if (pMouse)
    pMouse->SetCursorBitmap("MICON1");

  pPaletteManager->ResetNonLocked();
  pBitmaps_LOD->ReleaseAll2();
  pSprites_LOD->DeleteSomeOtherSprites();
  pIcons_LOD->ReleaseAll2();
  if (pRenderer->pRenderD3D)
  {
    pRenderer->field_1036B8 = 0;
    pRenderer->_gpu_memory_used = 0;
  }
  sub_46080D();
  if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
    pIndoor->Release();
  else if (uCurrentlyLoadedLevelType == LEVEL_Outdoor)
    pOutdoor->Release2();

  pAudioPlayer->StopChannels(-1, -1);
  pSoundList->_4A9D79(0);
  uCurrentlyLoadedLevelType = LEVEL_null;
  pSpriteFrameTable->ResetSomeSpriteFlags();
  v0 = uNumVisibleWindows;
  pParty->armageddon_timer = 0;
  while ( v0 > 0 )
    pWindowList[pVisibleWindowsIdxs[v0--] - 1].Release();
}

//----- (004646F0) --------------------------------------------------------
void PrepareWorld(unsigned int this_)
{
  unsigned int v1; // ebx@1

  v1 = this_;
  if ( pRenderer->pRenderD3D )
    pGame->pVisInstance->_4C1A02();
  pEventTimer->Pause();
  pMiscTimer->Pause();
  pParty->uFlags = 2;
  pCastSpellInfo.data()->_427D48(1);
  ResetCursor_Palettes_LODs_Level_Audio_SFT_Windows();
  DoPrepareWorld(0, (v1 == 0) + 1);
  pMiscTimer->Resume();
  pEventTimer->Resume();
}

//----- (00464761) --------------------------------------------------------
void __thiscall Game_DeinitializeAndTerminate(int exitCode)
{
  int v1; // esi@1
  HANDLE v2; // eax@1

  v1 = exitCode;
  v2 = GetCurrentProcess();
  SetPriorityClass(v2, 0x20u);
  ResetCursor_Palettes_LODs_Level_Audio_SFT_Windows();
  pGame->Deinitialize();
  pRenderer->Release2();
  if ( !DestroyWindow(hWnd) )
    GetLastError();
  hWnd = 0;
  exit(v1);
}

//----- (004647AB) --------------------------------------------------------
void FinalInitialization()
{
  pViewport->SetScreen(viewparams->uSomeX, viewparams->uSomeY, viewparams->uSomeZ, viewparams->uSomeW);
  pViewport->_4C02F8((signed __int64)(flt_6BE3A0 * 65536.0));

  pIndoorCamera = new IndoorCamera;
  pIndoorCamera->Initialize(65, viewparams->uScreen_BttmR_X - viewparams->uScreen_topL_X + 1,
                                viewparams->uScreen_BttmR_Y - viewparams->uScreen_topL_Y + 1);

  InitializeTurnBasedAnimations(&stru_50C198);
  pBitmaps_LOD->_inlined_sub1();
  pSprites_LOD->_inlined_sub1();
  pIcons_LOD->_inlined_sub1();
}
// 6BE3A0: using guessed type float flt_6BE3A0;

//----- (00464839) --------------------------------------------------------
char __cdecl Is_out15odm_underwater()
{
  return _stricmp(pCurrentMapName.data(), "out15.odm") == 0;
}

//----- (00464851) --------------------------------------------------------
void __cdecl SetUnderwaterFog()
{
  day_fogrange_1 = 50;
  day_fogrange_2 = 5000;
}

//----- (00464866) --------------------------------------------------------
void __fastcall DoPrepareWorld(unsigned int bLoading, int a2)
{
  int v2; // esi@1
  char *v3; // eax@1
  //char *v4; // eax@1
  unsigned int v5; // eax@3
  //size_t v6; // ecx@10
  //char *v7; // eax@11
  char Str1[20]; // [sp+Ch] [bp-18h]@1
  unsigned int v9; // [sp+20h] [bp-4h]@1

  v2 = a2;
  v9 = bLoading;
  ResetCursor_Palettes_LODs_Level_Audio_SFT_Windows();
  pDecalBuilder->Reset(0);
  pGameLoadingUI_ProgressBar->Initialize((GUIProgressBar::Type)v2);
  strcpy(Str1, pCurrentMapName.data());
  v3 = strtok(Str1, ".");
  strcpy(Str1, v3);
  Level_LoadEvtAndStr(Str1);
  LoadLevel_InitializeLevelEvt();
  strcpy(Str1, pCurrentMapName.data());
  _strrev(Str1);
  strtok(Str1, ".");
  _strrev(Str1);

  for (uint i = 0; i < 1000; ++i)
    pSpriteObjects[i].uObjectDescID = 0;

  v5 = pMapStats->GetMapInfo(pCurrentMapName.data());
  bUnderwater = 0;
  uLevelMapStatsID = v5;
  pGame->uFlags2 &= 0xFFFFFFF7u;
  if ( !_stricmp(pCurrentMapName.data(), "out15.odm") )
  {
    bUnderwater = 1;
    pGame->uFlags2 |= 8u;
  }
  pParty->floor_face_pid = 0;
  if ( _stricmp(Str1, "blv") )
    PrepareToLoadODM(v9, 0);
  else
    PrepareToLoadBLV(v9);
  pAudioPlayer->SetMapEAX();
  sub_461103();
  if ( !_stricmp(pCurrentMapName.data(), "d11.blv") || !_stricmp(pCurrentMapName.data(), "d10.blv") )
  {
    //spawning grounds & good analogue - no loot & exp from monsters

    for (uint i = 0; i < uNumActors; ++i)
    {
      pActors[i].pMonsterInfo.uTreasureType = 0;
      pActors[i].pMonsterInfo.uTreasureDiceRolls = 0;
      pActors[i].pMonsterInfo.uExp = 0;
    }
  }
  bDialogueUI_InitializeActor_NPC_ID = 0;
  OnMapLoad();
  pGameLoadingUI_ProgressBar->Progress();
memset(&pRenderer->pBillboardRenderListD3D, 0, sizeof(pRenderer->pBillboardRenderListD3D));
  pGameLoadingUI_ProgressBar->Release();
  _flushall();
}

//----- (004649EF) --------------------------------------------------------
int __fastcall ReadWindowsRegistryInt(const char *pKey, int uDefValue)
{
  int v3; // [sp+4h] [bp-24h]@1
  DWORD cbData; // [sp+8h] [bp-20h]@1
  LPCSTR lpValueName; // [sp+Ch] [bp-1Ch]@1
  DWORD dwDisposition; // [sp+10h] [bp-18h]@2
  BYTE Data[4]; // [sp+14h] [bp-14h]@5
  HKEY hKey; // [sp+18h] [bp-10h]@1
  HKEY phkResult; // [sp+1Ch] [bp-Ch]@1
  HKEY v10; // [sp+20h] [bp-8h]@1
  HKEY v11; // [sp+24h] [bp-4h]@1

  v3 = uDefValue;
  lpValueName = pKey;
  v11 = 0;
  v10 = 0;
  hKey = 0;
  phkResult = 0;
  cbData = 4;
  if ( !RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE", 0, KEY_READ|KEY_WOW64_32KEY, &hKey) )// for 64 bit
  {
    if ( !RegCreateKeyExA(hKey, "New World Computing", 0, "", 0, 0xF003Fu, 0, &phkResult, &dwDisposition) )
    {
      if ( !RegCreateKeyExA(phkResult, "Might and Magic VII", 0, "", 0, 0xF003Fu, 0, &v10, &dwDisposition) )
      {
        if ( !RegCreateKeyExA(v10, "1.0", 0, "", 0, 0xF003Fu, 0, &v11, &dwDisposition) )
        {
          if ( RegQueryValueExA(v11, lpValueName, 0, 0, Data, &cbData) )
          {
            *(int *)Data = v3;
            RegSetValueExA(v11, lpValueName, 0, 4u, Data, 4u);
          }
          RegCloseKey(v11);
        }
        RegCloseKey(v10);
      }
      RegCloseKey(phkResult);
    }
    RegCloseKey(hKey);
  }
  return *(int *)Data;
}

//----- (00464B02) --------------------------------------------------------
void __fastcall WriteWindowsRegistryString(const char *pKey, const char *pString)
{
  size_t v2; // eax@5
  const char *lpValueName; // [sp+4h] [bp-1Ch]@1
  const char *Str; // [sp+8h] [bp-18h]@1
  DWORD dwDisposition; // [sp+Ch] [bp-14h]@2
  HKEY hKey; // [sp+10h] [bp-10h]@1
  HKEY phkResult; // [sp+14h] [bp-Ch]@1
  HKEY v8; // [sp+18h] [bp-8h]@1
  HKEY v9; // [sp+1Ch] [bp-4h]@1

  Str = pString;
  lpValueName = pKey;
  v9 = 0;
  v8 = 0;
  hKey = 0;
  phkResult = 0;
  if ( !RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE", 0, 0x2001Fu, &hKey) )
  {
    if ( !RegCreateKeyExA(hKey, "New World Computing", 0, "", 0, 0xF003Fu, 0, &phkResult, &dwDisposition) )
    {
      if ( !RegCreateKeyExA(phkResult, "Might and Magic VII", 0, "", 0, 0xF003Fu, 0, &v8, &dwDisposition) )
      {
        if ( !RegCreateKeyExA(v8, "1.0", 0, "", 0, 0xF003Fu, 0, &v9, &dwDisposition) )
        {
          v2 = strlen(Str);
          RegSetValueExA(v9, lpValueName, 0, 1u, (const BYTE *)Str, v2 + 1);
          RegCloseKey(v9);
        }
        RegCloseKey(v8);
      }
      RegCloseKey(phkResult);
    }
    RegCloseKey(hKey);
  }
}

//----- (00464BEF) --------------------------------------------------------
void __fastcall ReadWindowsRegistryString(const char *pKeyName, char *pOutString, int uBufLen, const char *pDefaultValue)
{
  LSTATUS (__stdcall *v4)(HKEY); // esi@1
  LSTATUS result; // eax@7
  DWORD Type; // [sp+Ch] [bp-24h]@5
  LPCSTR lpValueName; // [sp+10h] [bp-20h]@1
  DWORD cbData; // [sp+14h] [bp-1Ch]@1
  LPBYTE Dest; // [sp+18h] [bp-18h]@1
  DWORD dwDisposition; // [sp+1Ch] [bp-14h]@2
  HKEY phkResult; // [sp+20h] [bp-10h]@1
  HKEY hKey; // [sp+24h] [bp-Ch]@1
  HKEY v13; // [sp+28h] [bp-8h]@1
  HKEY v14; // [sp+2Ch] [bp-4h]@1

  cbData = uBufLen;
  Dest = (LPBYTE)pOutString;
  lpValueName = pKeyName;
  v14 = 0;
  v13 = 0;
  hKey = 0;
  phkResult = 0;
  v4 = RegCloseKey;
  if ( RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE", 0, 0x2001Fu, &hKey)
    || RegCreateKeyExA(hKey, "New World Computing", 0, "", 0, 0xF003Fu, 0, &phkResult, &dwDisposition)
    || RegCreateKeyExA(phkResult, "Might and Magic VII", 0, "", 0, 0xF003Fu, 0, &v13, &dwDisposition)
    || RegCreateKeyExA(v13, "1.0", 0, "", 0, 0xF003Fu, 0, &v14, &dwDisposition) )
    goto LABEL_7;
  if ( RegQueryValueExA(v14, lpValueName, 0, &Type, Dest, &cbData) )
  {
    RegCloseKey(v14);
    v14 = 0;
LABEL_7:
    result = (LSTATUS)strncpy((char *)Dest, pDefaultValue, uBufLen);
    goto LABEL_8;
  }
  v4 = RegCloseKey;
  RegCloseKey(v14);
  v14 = 0;
  RegCloseKey(v13);
  v13 = 0;
  RegCloseKey(phkResult);
  phkResult = 0;
  result = RegCloseKey(hKey);
  hKey = 0;
LABEL_8:
  if ( v14 )
    result = v4(v14);
  if ( v13 )
    result = v4(v13);
  if ( hKey )
    result = v4(hKey);
  if ( phkResult )
    result = v4(phkResult);
}

//----- (00464D32) --------------------------------------------------------
void __fastcall WriteWindowsRegistryInt(const char *pKey, int val)
{
  const char *lpValueName; // [sp+4h] [bp-1Ch]@1
  BYTE Data[4]; // [sp+8h] [bp-18h]@1
  DWORD dwDisposition; // [sp+Ch] [bp-14h]@2
  HKEY hKey; // [sp+10h] [bp-10h]@1
  HKEY phkResult; // [sp+14h] [bp-Ch]@1
  HKEY v7; // [sp+18h] [bp-8h]@1
  HKEY v8; // [sp+1Ch] [bp-4h]@1

  *(int *)Data = val;
  lpValueName = pKey;
  v8 = 0;
  v7 = 0;
  hKey = 0;
  phkResult = 0;
  if ( !RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE", 0, 0x2001Fu, &hKey) )
  {
    if ( !RegCreateKeyExA(hKey, "New World Computing", 0, "", 0, 0xF003Fu, 0, &phkResult, &dwDisposition) )
    {
      if ( !RegCreateKeyExA(phkResult, "Might and Magic VII", 0, "", 0, 0xF003Fu, 0, &v7, &dwDisposition) )
      {
        if ( !RegCreateKeyExA(v7, "1.0", 0, "", 0, 0xF003Fu, 0, &v8, &dwDisposition) )
        {
          RegSetValueExA(v8, lpValueName, 0, 4u, Data, 4u);
          RegCloseKey(v8);
        }
        RegCloseKey(v7);
      }
      RegCloseKey(phkResult);
    }
    RegCloseKey(hKey);
  }
}

//----- (00464E17) --------------------------------------------------------
bool __fastcall CheckMM7CD(char c)
{
  char DstBuf[256]; // [sp+Ch] [bp-218h]@1
  char strCommand[256]; // [sp+10Ch] [bp-118h]@1
  char Filename[20]; // [sp+20Ch] [bp-18h]@1


  wchar_t pMagicPath[1024];
  swprintf(pMagicPath, wcslen(L"%C:\\anims\\magic7.vid"), L"%C:\\anims\\magic7.vid", c);
  if (GetFileAttributesW(pMagicPath) == -1)
    return false;

  wsprintfA(strCommand, "open %c: type cdaudio alias CD", c);
  if (!mciSendStringA(strCommand, DstBuf, 0xFFu, 0))
  {
    wsprintfA(strCommand, "info CD UPC wait");
    mciSendStringA(strCommand, DstBuf, 0xFFu, 0);
    wsprintfA(strCommand, "close CD");
    mciSendStringA(strCommand, DstBuf, 0xFFu, 0);
  }

  memcpy(Filename, "X:\\anims\\magic7.vid", sizeof(Filename));
  *Filename = c;

  auto f = fopen(Filename, "rb");
  if (!f)
    return false;

  if (!fseek(f, 0, SEEK_END))
  {
    if (!fseek(f, -100, SEEK_CUR))
      fread(DstBuf, 1u, 0x64u, f);

    fclose(f);
    return true;
  }
  fclose(f);
  return false;
}

//----- (00464F1B) --------------------------------------------------------
signed int __stdcall InsertMM7CDDialogFunc(HWND hDlg, int a2, __int16 a3, int a4)
{
  char v4; // zf@3
  int v6; // eax@10
  int v7; // eax@11
  int v8; // eax@12
  int v9; // eax@13
  BOOL (__stdcall *v10)(HWND, int, LPCSTR); // edi@15
  const CHAR *v11; // [sp-Ch] [bp-Ch]@15
  INT_PTR v12; // [sp-4h] [bp-4h]@5

  if ( a2 == 272 )
  {
    hInsertCDWindow = hDlg;
    v6 = (GetUserDefaultLangID() & 0x3FF) - 7;
    if ( v6 )
    {
      v7 = v6 - 3;
      if ( v7 )
      {
        v8 = v7 - 2;
        if ( v8 )
        {
          v9 = v8 - 4;
          if ( v9 )
          {
            if ( v9 != 5 )
              return 0;
            SetWindowTextA(hDlg, "Wloz CD-ROM numer 2");
            v10 = SetDlgItemTextA;
            SetDlgItemTextA(hDlg, 1010, "Wloz CD-ROM numer 2 Might and Magic® VII.");
            v11 = "Odwolaj";
          }
          else
          {
            SetWindowTextA(hDlg, "Inserire il secondo CD");
            v10 = SetDlgItemTextA;
            SetDlgItemTextA(hDlg, 1010, "Inserire il secondo CD di Might and Magic® VII.");
            v11 = "Annulla";
          }
        }
        else
        {
          SetWindowTextA(hDlg, "Insérez le CD 2");
          v10 = SetDlgItemTextA;
          SetDlgItemTextA(hDlg, 1010, "Insérez Might & Magic® VII CD 2.");
          v11 = "Supprimer";
        }
      }
      else
      {
        SetWindowTextA(hDlg, "Por favor, inserte disco 2");
        v10 = SetDlgItemTextA;
        SetDlgItemTextA(hDlg, 1010, "Por favor, inserte disco 2 de Might & Magic® VII.");
        v11 = "Cancelar";
      }
    }
    else
    {
      SetWindowTextA(hDlg, "Bitte CD 2 einlegen");
      v10 = SetDlgItemTextA;
      SetDlgItemTextA(hDlg, 1010, "Bitte CD 2 von Might and Magic® VII einlegen.");
      v11 = "Abbrechen";
    }
    v10(hDlg, 2, v11);
    return 0;
  }
  if ( a2 == 273 )
  {
    if ( a3 == 2 )
    {
      v12 = 0;
LABEL_9:
      EndDialog(hDlg, v12);
      return 1;
    }
    v4 = a3 == 1;
  }
  else
  {
    v4 = a2 == 1025;
  }
  if ( v4 )
  {
    v12 = 1;
    goto LABEL_9;
  }
  return 0;
}

//----- (00465061) --------------------------------------------------------
bool __fastcall FindMM7CD(HWND hWnd, char *pCDDrive)
{
  char drive[4] = {'X', ':', '\\', 0};

  bool bGotCDFromRegistry = false;

  HKEY hSoftware = nullptr,
       hNWC = nullptr,
       hMM7 = nullptr,
       hVersion = nullptr;
  if (!RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE", 0, 0x2001Fu, &hSoftware))
  {
    if (!RegOpenKeyExA(hSoftware, "New World Computing", 0, 0x2001Fu, &hNWC))
    {
      if (!RegOpenKeyExA(hNWC, "Might and Magic VII", 0, 0x2001Fu, &hMM7))
      {
        if (!RegOpenKeyExA(hMM7, "1.0", 0, 0x2001Fu, &hVersion))
        {
          DWORD cbData = 3;
          if (!RegQueryValueExA(hVersion, "CDDrive", 0, 0, (BYTE *)drive, &cbData))
            bGotCDFromRegistry = true;
        }
        RegCloseKey(hVersion);
      }
      RegCloseKey(hMM7);
    }
    RegCloseKey(hNWC);
  }
  RegCloseKey(hSoftware);

  if (bGotCDFromRegistry)
    if (CheckMM7CD(*drive))
    {
      cMM7GameCDDriveLetter = *drive;
      return true;
    }

  while (true)
  {
    for (uint i = 0; i < 26; ++i)
    {
      drive[0] = 'A' + i;

      if (GetDriveTypeA(drive) == DRIVE_CDROM)
        if (CheckMM7CD(*drive))
        {
          cMM7GameCDDriveLetter = *drive;
          WriteWindowsRegistryString("CDDrive", drive);
          return true;
        }
    }

    if (DialogBoxParamA(GetModuleHandleW(nullptr), "InsertCD", ::hWnd, (DLGPROC)InsertMM7CDDialogFunc, 0))
      continue;
    return false;
  }
}

//----- (004651F4) --------------------------------------------------------
bool MM7_Initialize()
{
initing=true; //ADDED Gloval
  wchar_t pCurrentDir[1024];
  _wgetcwd(pCurrentDir, 1024);

  wchar_t pMM6IniFile[1024];
  wsprintfW(pMM6IniFile, L"%s\\mm6.ini", pCurrentDir);

  bCanLoadFromCD = GetPrivateProfileIntW(L"settings", L"use_cd", 1, pMM6IniFile);
  if (bNoCD)
    bCanLoadFromCD = false;
  if (bCanLoadFromCD)
  {
    if (!FindMM7CD(hWnd, &cMM7GameCDDriveLetter))
      return false;
  }


  srand(GetTickCount());
  
  WNDCLASSEXW wcxw;
  {
    wcxw.cbSize = sizeof(wcxw);
    wcxw.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
    wcxw.lpfnWndProc = (WNDPROC)aWinProc;
    wcxw.cbClsExtra = 0;
    wcxw.cbWndExtra = 0;
    wcxw.hInstance = GetModuleHandleW(nullptr);
    wcxw.hCursor = 0;
    wcxw.hIcon = wcxw.hIconSm = LoadIconW(wcxw.hInstance, L"MM7_ICON");
    wcxw.lpszMenuName = nullptr;
    wcxw.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
    wcxw.lpszClassName = L"M&MTrilogy";
  }
  if (!RegisterClassExW(&wcxw))
  {
    Log::Warning(L"Cannot register window class");
    return false;
  }

  auto hDesktopDC = GetDC(nullptr);
  uint uDesktopWidth = GetDeviceCaps(hDesktopDC, HORZRES);
  uint uDesktopHeight = GetDeviceCaps(hDesktopDC, VERTRES);

  if (GetDeviceCaps(hDesktopDC, BITSPIXEL) != 16 ||
      GetDeviceCaps(hDesktopDC, PLANES) != 1 )
    dword_6BE364_game_settings_1 |= 2;

  ReleaseDC(nullptr, hDesktopDC);

  uint uTotalWinWidth = 2 * GetSystemMetrics(SM_CXFRAME) + 640;
  uint uTotalWinHeight = GetSystemMetrics(SM_CYCAPTION) + 2 * GetSystemMetrics(SM_CYFRAME) + 480;

  uint uWinCenteredPosX = (uDesktopWidth - uTotalWinWidth) / 2;
  uint uWinCenteredPosY = (uDesktopHeight - uTotalWinHeight) / 2;

  uWindowX = ReadWindowsRegistryInt("window X", uWinCenteredPosX);
  uWindowX = uDesktopWidth / 2 - 640 / 2;
  WriteWindowsRegistryInt("window X", uWindowX);

  uWindowY = ReadWindowsRegistryInt("window Y", uWinCenteredPosY);
  uWindowY = uDesktopHeight / 2 - 480 / 2;
  WriteWindowsRegistryInt("window Y", uWindowY);

  hWnd = CreateWindowExW(0, wcxw.lpszClassName, L"Might and Magic® VII",
                         uWindowStyle = WS_SYSMENU | WS_GROUP | WS_DLGFRAME | WS_BORDER,
                         uWindowX, uWindowY,
                         640, 480,
                         nullptr,
                         hOSMenu = nullptr,
                         wcxw.hInstance,
                         nullptr);
  SetWindowTextW(hWnd, L"Might and Magic® VII");

  HMENU menu = CreateMenu();
  {
    HMENU file = CreatePopupMenu();
    AppendMenuW(menu, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)file, L"&File");
    {
      AppendMenuW(file, MF_ENABLED | MF_STRING, 40001, L"Exit");
    }

    HMENU debug = CreatePopupMenu();
    AppendMenuW(menu, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug, L"&Debug");
    {
      HMENU debug_party = CreatePopupMenu();
      AppendMenuW(debug, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_party, L"&Party");
      {
        AppendMenuW(debug_party, MF_ENABLED | MF_STRING, 40007, L"Give Gold (10 000)");
        AppendMenuW(debug_party, MF_ENABLED | MF_STRING, 40008, L"Give Exp (20 000)");
        AppendMenuW(debug_party, MF_ENABLED | MF_STRING, 40059, L"Give Skills (50 each)");
        AppendMenuW(debug_party, MF_ENABLED | MF_STRING, 40013, L"Remove Gold");

        HMENU debug_party_setconditions = CreatePopupMenu();
        AppendMenuW(debug_party, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_party_setconditions, L"Set Condition");
        {
          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40044, L"Afraid");
          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40043, L"Asleep");
          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40037, L"Curse");
          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40036, L"Disease1");
          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40035, L"Disease2");
          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40034, L"Disease3");
          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40041, L"Dead");
          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40039, L"Drunk");
          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40042, L"Eradicated");
          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40038, L"Insane");
          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40045, L"Paralyzed");
          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40033, L"Poison1");
          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40032, L"Poison2");
          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40031, L"Poison3");
          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40029, L"&Stone");
          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40040, L"Unconscious");
          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40030, L"Weak");
          AppendMenuW(debug_party_setconditions, MF_ENABLED | MF_STRING, 40073, L"Zombie");
        }

        AppendMenuW(debug_party, MF_ENABLED | MF_STRING, 40006, L"Set Food (20)");

        HMENU debug_party_alignment = CreatePopupMenu();
        AppendMenuW(debug_party, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_party_alignment, L"Alignment");
        {
          AppendMenuW(debug_party_alignment, MF_ENABLED | MF_STRING, 40062, L"Good");
          AppendMenuW(debug_party_alignment, MF_ENABLED | MF_STRING | MF_CHECKED, 40063, L"Neutral");
          AppendMenuW(debug_party_alignment, MF_ENABLED | MF_STRING, 40064, L"Evil");
        }
      }

      HMENU debug_time = CreatePopupMenu();
      AppendMenuW(debug, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_time, L"&Time");
      {
        AppendMenuW(debug_time, MF_ENABLED | MF_STRING, 40009, L"Add 1 Day");
        AppendMenuW(debug_time, MF_ENABLED | MF_STRING, 40010, L"Add 1 Week");
        AppendMenuW(debug_time, MF_ENABLED | MF_STRING, 40011, L"Add 1 Month");
        AppendMenuW(debug_time, MF_ENABLED | MF_STRING, 40012, L"Add 1 Year");
      }

      HMENU debug_items = CreatePopupMenu();
      AppendMenuW(debug, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_items, L"&Items");
      {
        AppendMenuW(debug_items, MF_ENABLED | MF_STRING, 40015, L"Generate level &1 item");
        AppendMenuW(debug_items, MF_ENABLED | MF_STRING, 40016, L"Generate level &2 item");
        AppendMenuW(debug_items, MF_ENABLED | MF_STRING, 40017, L"Generate level &3 item");
        AppendMenuW(debug_items, MF_ENABLED | MF_STRING, 40018, L"Generate level &4 item");
        AppendMenuW(debug_items, MF_ENABLED | MF_STRING, 40019, L"Generate level &5 item");
        AppendMenuW(debug_items, MF_ENABLED | MF_STRING, 40020, L"Generate level &6 item");
        AppendMenuW(debug_items, MF_ENABLED | MF_STRING, 40061, L"Generate special item");
      }

      HMENU debug_graphics = CreatePopupMenu();
      AppendMenuW(debug, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_graphics, L"&Graphics");
      {
        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40023, L"Lighting Mode");
        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40024, L"Lighting Geometry");
        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING | MF_GRAYED, 40104, L"Lights Off");
        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40105, L"Colored Lights");
        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40025, L"Debug Lights");
        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40101, L"Debug Decals");
        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40027, L"HWID Portals");
        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40047, L"SWID Portals");
        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40051, L"OD Frustum");
        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40054, L"SWOD Constant Redraw");
        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40055, L"SWOD Lit Rasterizer");
        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40056, L"Party Light off");
        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40060, L"SWOD Nice Lighting off");
        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40067, L"HWOD Additive Fog Lights");
        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40072, L"HWID Nice Lighting");
        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40048, L"Wireframe");
        AppendMenuW(debug_graphics, MF_ENABLED | MF_STRING, 40049, L"Fog");
      }

      HMENU debug_misc = CreatePopupMenu();
      AppendMenuW(debug, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_misc, L"&Misc");
      {
        AppendMenuW(debug_misc, MF_ENABLED | MF_STRING, 40066, L"Object Viewcone Culling");
        AppendMenuW(debug_misc, MF_ENABLED | MF_STRING, 40068, L"Red Tint");
        AppendMenuW(debug_misc, MF_ENABLED | MF_STRING, 40071, L"Display Secrets");
        AppendMenuW(debug_misc, MF_ENABLED | MF_STRING, 40102, L"Massive Bloodsplat");
        AppendMenuW(debug_misc, MF_ENABLED | MF_STRING, 40103, L"Underwater Gravity");
      }
      
      HMENU debug_eax = CreatePopupMenu();
      AppendMenuW(debug, MF_ENABLED | MF_STRING | MF_POPUP, (UINT_PTR)debug_eax, L"EAX Environs");
      {
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40074, L"NONE");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40075, L"GENERIC");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40076, L"PADDEDCELL");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40077, L"ROOM");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40078, L"BATHROOM");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40079, L"LIVINGROOM");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40080, L"STONEROOM");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40081, L"AUDITORIUM");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40082, L"CONCERTHALL");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40083, L"CAVE");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40084, L"ARENA");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40085, L"HANGAR");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40086, L"CARPETEDHALLWAY");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40087, L"HALLWAY");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40088, L"STONECORRIDOR");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40089, L"ALLEY");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40090, L"FOREST");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40091, L"CITY");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40092, L"MOUNTAINS");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40093, L"QUARRY");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40094, L"PLAIN");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40095, L"PARKINGLOT");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40096, L"SEWERPIPE");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40097, L"UNDERWATER");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40098, L"DRUGGED");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40099, L"DIZZY");
        AppendMenuW(debug_eax, MF_ENABLED | MF_STRING, 40100, L"PSICHOTIC");
      }
    }
  }
  SetMenu(hWnd, menu);
  
  SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);

  pRenderer = Render::Create();
  if (!pRenderer)
  {
    Log::Warning(L"Render creation failed");
    return false;
  }
  else
  {
    bool bWindowMode = ReadWindowsRegistryInt("startinwindow", false);
    uint uDefaultDevice = ReadWindowsRegistryInt("D3D Device", 1);
    bool bColoredLights = ReadWindowsRegistryInt("Colored Lights", false);
    uint uLevelOfDetail = ReadWindowsRegistryInt("Detail Level", 1);
    uint bTinting = ReadWindowsRegistryInt("Tinting", 1) != 0;

    if (!pRenderer->Initialize(bWindowMode, uDefaultDevice, bColoredLights, uLevelOfDetail, bTinting))
    {
      Log::Warning(L"Render failed to initialize");
      return false;
    }
  }
  
  pAllocator = Allocator::Create();
  if (!pAllocator->Initialize(48 * 1024))
  {
    MessageBoxW(nullptr,
                L"Unable to Allocate 48Mb of RAM",
                L"More RAM Memory Required", MB_ICONEXCLAMATION);
    return false;
  }

  game_starting_year = 1168;

  pParty = new Party;
  memset(&pParty->pHirelings, 0, sizeof(pParty->pHirelings));
  pParty->uWalkSpeed = GetPrivateProfileIntW(L"debug", L"walkspeed", 384, pMM6IniFile);
  pParty->uDefaultEyelevel = GetPrivateProfileIntW(L"party", L"eyelevel", 160, pMM6IniFile);
  pParty->sEyelevel = pParty->uDefaultEyelevel;
  pParty->uDefaultPartyHeight = GetPrivateProfileIntW(L"party", L"height", 192, pMM6IniFile);
  pParty->uPartyHeight = pParty->uDefaultPartyHeight;
  
  bUseRegistry = GetPrivateProfileIntW(L"settings", L"registry", 1, pMM6IniFile);
  MM6_Initialize(pMM6IniFile);

  pKeyActionMap = new KeyboardActionMapping;

  pEventTimer = Timer::Create();
  pEventTimer->Initialize();

  OnTimer(1);
  GameUI_StatusBar_UpdateTimedString(1);
  pGame = Game::Create();
  pMouse = pGame->pMouseInstance;
  

  RECT rcWindow;
  GetWindowRect(hWnd, &rcWindow);

  RECT rcClient;
  GetClientRect(hWnd, &rcClient);
  uWindowWidth = rcClient.left - rcClient.right - rcWindow.left + rcWindow.right + 640;
  uWindowHeight = rcClient.top - rcClient.bottom - rcWindow.top + rcWindow.bottom + 480;
  MoveWindow(hWnd, uWindowX, uWindowY,
    rcClient.left - rcClient.right - rcWindow.left + rcWindow.right + 640,
    rcClient.top - rcClient.bottom - rcWindow.top + rcWindow.bottom + 480, 0);
  ShowWindow(hWnd, SW_SHOWNORMAL);

  pIcons_LOD = new LODFile_IconsBitmaps;
  if (!pIcons_LOD->LoadIconsOrEvents("data\\icons.lod"))
  {
    MessageBoxW(nullptr,
                L"Some files are missing\n\nPlease Reinstall.",
                L"Files Missing", MB_ICONEXCLAMATION);
    return false;
  }
  pIcons_LOD->dword_011BA4 = 0;
  
  pEvents_LOD = new LODFile_IconsBitmaps;
  if (!pEvents_LOD->LoadIconsOrEvents("data\\events.lod"))
  {
    MessageBoxW(nullptr,
                L"Some files are missing\n\nPlease Reinstall.",
                L"Files Missing", MB_ICONEXCLAMATION);
    return false;
  }

  InitializeGameText();
  
  pBitmaps_LOD = new LODFile_IconsBitmaps;
  if (!pBitmaps_LOD->LoadBitmaps("data\\bitmaps.lod"))
  {
    MessageBoxA(nullptr,
                pGlobalTXT_LocalizationStrings[63],
                pGlobalTXT_LocalizationStrings[184], MB_ICONEXCLAMATION);
    return false;
  }

  if (bUseRegistry)
    bUseLoResSprites = ReadWindowsRegistryInt("resolution", 0);
  else
    bUseLoResSprites = GetPrivateProfileIntW(L"settings", L"resolution", 0, pMM6IniFile);

  const char *pSpritesFile = nullptr;
  if (bUseLoResSprites)
    pSpritesFile = "data\\spriteLO.lod";
  else
    pSpritesFile = "data\\sprites.lod";

  pSprites_LOD = new LODFile_Sprites;
  if (!pSprites_LOD->LoadSprites(pSpritesFile))
  {
    MessageBoxA(nullptr,
                pGlobalTXT_LocalizationStrings[63],
                pGlobalTXT_LocalizationStrings[184], MB_ICONEXCLAMATION);
    return false;
  }

  if (bDebugResouces)
  {
    pSpriteFrameTable = new SpriteFrameTable;
    if (!pSpriteFrameTable->FromFileTxt("data\\sft.txt"))
      Abortf("Unable to open sft.txt");

    pDecorationList = new DecorationList;
    if (!pDecorationList->FromFileTxt("data\\declist.txt"))
      Abortf("Unable to open declist.txt");

    pObjectList = new ObjectList;
    if (!pObjectList->FromFileTxt("data\\objlist.txt"))
      Abortf("Unable to open objlist.txt");

    pMonsterList = new MonsterList;
    if (!pMonsterList->FromFileTxt("data\\monlist.txt"))
      Abortf("Unable to open monlist.txt");

    pIconsFrameTable = new IconFrameTable;
    if (!pIconsFrameTable->FromFileTxt("data\\ift.txt"))
      Abortf("Unable to open ift.txt");

    pTextureFrameTable = new TextureFrameTable;
    if (!pTextureFrameTable->FromFileTxt("data\\tft.def"))
      Abortf("Unable to open tft.def");

    pTileTable = new TileTable;
    if (!pTileTable->FromFileTxt("data\\tile.def"))
      Abortf("Unable to open tile.def");

    pPlayerFrameTable = new PlayerFrameTable;
    if (!pPlayerFrameTable->FromFileTxt("data\\pft.def"))
      Abortf("Unable to open pft.def");

    pChestList = new ChestList;
    if (!pChestList->FromFileTxt("data\\chest.def"))
      Abortf("Unable to open chest.def");

    pOverlayList = new OverlayList;
    if (!pOverlayList->FromFileTxt("data\\overlay.def"))
      Abortf("Unable to open overlay.def");

    pSoundList = new SoundList;
    if (!pSoundList->FromFileTxt("data\\sounds.def"))
      Abortf("Unable to open sounds.def");
  }
  else
  {
    auto pSFT = pEvents_LOD->LoadRaw("dsft.bin", 1);
    pSpriteFrameTable = new SpriteFrameTable;
    pSpriteFrameTable->FromFile(pSFT);
    free(pSFT);

    auto pTFT = pEvents_LOD->LoadRaw("dtft.bin", 1);
    pTextureFrameTable = new TextureFrameTable;
    pTextureFrameTable->FromFile(pTFT);
    free(pTFT);

    auto pTiles = pEvents_LOD->LoadRaw("dtile.bin", 1);
    pTileTable = new TileTable;
    pTileTable->FromFile(pTiles);
    free(pTiles);

    auto pPFT = pEvents_LOD->LoadRaw("dpft.bin", 1);
    pPlayerFrameTable = new PlayerFrameTable;
    pPlayerFrameTable->FromFile(pPFT);
    free(pPFT);

    auto pIFT = pEvents_LOD->LoadRaw("dift.bin", 1);
    pIconsFrameTable = new IconFrameTable;
    pIconsFrameTable->FromFile(pIFT);
    free(pIFT);

    auto pDecs = pEvents_LOD->LoadRaw("ddeclist.bin", 1);
    pDecorationList = new DecorationList;
    pDecorationList->FromFile(pDecs);
    free(pDecs);

    auto pObjs = pEvents_LOD->LoadRaw("dobjlist.bin", 1);
    pObjectList = new ObjectList;
    pObjectList->FromFile(pObjs);
    free(pObjs);

    auto pMons = pEvents_LOD->LoadRaw("dmonlist.bin", 1);
    pMonsterList = new MonsterList;
    pMonsterList->FromFile(pMons);
    free(pMons);

    auto pChests = pEvents_LOD->LoadRaw("dchest.bin", 1);
    pChestList = new ChestList;
    pChestList->FromFile(pChests);
    free(pChests);

    auto pOverlays = pEvents_LOD->LoadRaw("doverlay.bin", 1);
    pOverlayList = new OverlayList;
    pOverlayList->FromFile(pOverlays);
    free(pOverlays);

    auto pSounds = pEvents_LOD->LoadRaw("dsounds.bin", 1);
    pSoundList = new SoundList;
    pSoundList->FromFile(pSounds);
    free(pSounds);
  }


  if (bDebugResouces)
  {
    pSpriteFrameTable->ToFile();
    pDecorationList->ToFile();
    pObjectList->ToFile();
    pMonsterList->ToFile();
    pIconsFrameTable->ToFile();
    pTextureFrameTable->ToFile();
    pTileTable->ToFile();
    pPlayerFrameTable->ToFile();
    pChestList->ToFile();
    pOverlayList->ToFile();
    pSoundList->ToFile();
  }

  
  if (dword_6BE364_game_settings_1 & 2 || !(dword_6BE368_debug_settings_2 & 1))// 
                                                //   color depth != 16
                                                // or
                                                //   not in window
  {
    SetMenu(hWnd, 0);
    SetWindowLongA(hWnd, GWL_EXSTYLE, 0);
    SetWindowLongA(hWnd, GWL_STYLE, WS_VISIBLE);
    pRenderer->InitializeFullscreen(hWnd);
  }
  else
  {
    ClipCursor(nullptr);
    pRenderer->SwitchToWindow(hWnd);
  }

  uSoundVolumeMultiplier = ReadWindowsRegistryInt("soundflag", 9);
  if (uSoundVolumeMultiplier > 9)
    uSoundVolumeMultiplier = 9;
  uMusicVolimeMultiplier = ReadWindowsRegistryInt("musicflag", 9);
  if (uMusicVolimeMultiplier > 9)
    uMusicVolimeMultiplier = 9;
  uVoicesVolumeMultiplier = ReadWindowsRegistryInt("CharVoices", 9);
  if (uVoicesVolumeMultiplier > 9)
    uVoicesVolumeMultiplier = 9;
  bShowDamage = ReadWindowsRegistryInt("ShowDamage", 1) != 0;
  byte_6BE388_graphicsmode = ReadWindowsRegistryInt("graphicsmode", 1);
  if (byte_6BE388_graphicsmode < 0 || byte_6BE388_graphicsmode > 2)
    byte_6BE388_graphicsmode = 0;

  uGammaPos = ReadWindowsRegistryInt("GammaPos", 4);
  if (uGammaPos > 9)
    uGammaPos = 4;
  pGame->pGammaController->Initialize(uGammaPos * 0.1 + 0.6);

  if ( ReadWindowsRegistryInt("Bloodsplats", 1) )
    pGame->uFlags2 |= GAME_FLAGS_2_DRAW_BLOODSPLATS;
  else
    pGame->uFlags2 &= ~GAME_FLAGS_2_DRAW_BLOODSPLATS;

  uTurnSpeed = ReadWindowsRegistryInt("TurnDelta", 0);
  dword_6BE384_2dacceloff = ReadWindowsRegistryInt("2dacceloff", 0);

  if (!bNoSound)
    pAudioPlayer->Initialize(hWnd);

  pVideoPlayer = new VideoPlayer;
  pVideoPlayer->Initialize();

  dword_6BE364_game_settings_1 |= 0x4000;

    switch ( uTurnSpeed )
    {
      case 0: // undefined turn option
        __debugbreak(); // really shouldn't use this mode
        uTurnSpeed = (unsigned int)uCPUSpeed < 199 ? 128 : 64; // adjust turn speed to estimated fps
      break;

      case 1u:             // 16x
        Log::Warning(L"x16 Turn Speed"); // really shouldn't use this mode
        uTurnSpeed = 128;
      break;

      case 2u:             // 32x
        Log::Warning(L"x32 Turn Speed"); // really shouldn't use this mode
        uTurnSpeed = 64;
      break;

      case 3u:             // smooth
        uTurnSpeed = 0;
      break;
    }

  initing = false; //ADDED Gloval
  return true;
}

//----- (00465D0B) --------------------------------------------------------
void __cdecl SecondaryInitialization()
{
  __int16 v4; // ax@4
  signed int v5; // esi@5
  int v6; // ecx@6
  int v7; // edx@7
  ObjectDesc *v8; // eax@7
  char pContainer[32]; // [sp+10h] [bp-Ch]@9

  pMouse->Initialize(hWnd);

  pItemsTable = new ItemsTable;
  pItemsTable->Initialize();

  pBitmaps_LOD->dword_011BA8 = 1;
  pBitmaps_LOD->SetupPalettes(pRenderer->uTargetRBits, pRenderer->uTargetGBits, pRenderer->uTargetBBits);
  pIcons_LOD->SetupPalettes(pRenderer->uTargetRBits, pRenderer->uTargetGBits, pRenderer->uTargetBBits);
  pPaletteManager->SetColorChannelInfo(pRenderer->uTargetRBits, pRenderer->uTargetGBits, pRenderer->uTargetBBits);

  pPaletteManager->SetMistColor(128, 128, 128);
  pPaletteManager->RecalculateAll();
  pSprites_LOD->field_ECAC = 1;
  pObjectList->InitializeSprites();
  pOverlayList->InitializeSprites();
  if (!bNoSound)
    pSoundList->Initialize();

  static const char *pUIAnimNames[4] =
  {
    "glow03", "glow05",
    "torchA", "wizeyeA"
  };
  static unsigned short _4E98D0[4][4] =
  {
    {479, 0, 329, 0},
    {585, 0, 332, 0},
    {468, 0,   0, 0},
    {606, 0,   0, 0}
  };


  for (uint i = 0; i < 4; ++i)
  {
    pUIAnims[i]->uIconID = pIconsFrameTable->FindIcon(pUIAnimNames[i]);
    pIconsFrameTable->InitializeAnimation(pUIAnims[i]->uIconID);

    pUIAnims[i]->uAnimLength = 0;
    pUIAnims[i]->uAnimTime = 0;
    pUIAnims[i]->x = _4E98D0[i][0];
    pUIAnims[i]->y = _4E98D0[i][2];
  }

  v5 = 0;
  if ( (signed int)pObjectList->uNumObjects > 0 )
  {
    v6 = 0;
    do
    {
      BYTE3(v7) = 0;
      v8 = &pObjectList->pObjects[v6];
      ++v6;
      *(short *)((char *)&v7 + 1) = v8->uParticleTrailColorR;
      LOBYTE(v7) = v8->uParticleTrailColorG;
      ++v5;
      v8->uParticleTrailColor = v8->uParticleTrailColorB | (v7 << 8);
    }
    while ( v5 < (signed int)pObjectList->uNumObjects );
  }
  flt_6BE3A0 = 0.55000001f;
  MainMenuUI_Create();
  pGame->pStru6Instance->LoadAnimations();

  for (uint i = 0; i < 7; ++i)
  {
    sprintf(pContainer, "HDWTR%03u", i);
    pRenderer->pHDWaterBitmapIDs[i] = pBitmaps_LOD->LoadTexture(pContainer);
  }

  pNPCStats = new NPCStats;
  memset(pNPCStats->pNPCData, 0, 0x94BCu);
  pNPCStats->Initialize();

  Initialize_GlobalEVT();
  pBitmaps_LOD->_inlined_sub0();
  pSprites_LOD->_inlined_sub0();
  pPaletteManager->LockAll();

  _mkdir("Saves");
  for (uint i = 0; i < 5; ++i)
    for (uint j = 0; j < 6; ++j)
    {
      sprintf(pTmpBuf.data(), "data\\lloyd%d%d.pcx", i, j);
      remove(pTmpBuf.data());
    }

  Initialize_GamesLOD_NewLOD();
  _576E2C_current_minimap_zoom = 512;
  dword_576E28 = 9;
}

void IntegrityTest()
{
  assert(sizeof(RenderVertexSoft) == 0x30);
  assert(sizeof(RenderBillboard) == 0x34);
  assert(sizeof(Texture) == 0x48);
  assert(sizeof(RGBTexture) == 0x28);
  assert(sizeof(LODFile_IconsBitmaps) == 0x11BB8 + 4); // + virtual dtor ptr
  assert(sizeof(AudioPlayer) == 0xC84);
  assert(sizeof(SoundDesc) == 0x78);
  assert(sizeof(stru339_spell_sound) == 0xAFD8);
  assert(sizeof(VideoPlayer) == 0x108 + 4);
  assert(sizeof(MovieHeader) == 0x2C);
  assert(sizeof(DecorationDesc) == 0x54);
  assert(sizeof(ObjectDesc) == 0x38);
  assert(sizeof(OverlayDesc) == 0x8);
  assert(sizeof(ChestDesc) == 0x24);
  assert(sizeof(TileDesc) == 0x1A);
  assert(sizeof(MonsterDesc) == 0x98);
  assert(sizeof(Timer) == 0x28);
  assert(sizeof(OtherOverlay) == 0x14);
  assert(sizeof(ItemGen) == 0x24);
  assert(sizeof(SpriteObject) == 0x70);
  assert(sizeof(ItemDesc) == 0x30);
  assert(sizeof(ItemsTable) == 0x117A0);
  assert(sizeof(Chest) == 0x14CC);
  assert(sizeof(MapInfo) == 0x44);
  assert(sizeof(SpellInfo) == 0x24);
  assert(sizeof(SpellData) == 0x14);
  assert(sizeof(SpellBuff) == 0x10);
  assert(sizeof(AIDirection) == 0x1C);
  assert(sizeof(ActorJob) == 0xC);
  assert(sizeof(Actor) == 0x344);
  assert(sizeof(LevelDecoration) == 0x20);
  assert(sizeof(KeyboardActionMapping) == 0x20C);
  assert(sizeof(UIAnimation) == 0xD);
  assert(sizeof(SpawnPointMM7) == 0x18);
  assert(sizeof(ODMFace) == 0x134);
  assert(sizeof(BSPNode) == 0x8);
  assert(sizeof(BSPModel) == 0xBC);
  assert(sizeof(OutdoorLocation) == 0x1C28C);
  assert(sizeof(BLVFace) == 0x60);
  assert(sizeof(BLVFaceExtra) == 0x24);
  assert(sizeof(BLVSector) == 0x74);
  assert(sizeof(BLVLightMM7) == 0x10);
  assert(sizeof(BLVDoor) == 0x50);
  assert(sizeof(IndoorLocation) == 0x690);
  assert(sizeof(OutdoorCamera) == 0x74);
  assert(sizeof(Mouse) == 0x114);
  assert(sizeof(Particle_sw) == 0x68);
  assert(sizeof(Particle) == 0x68);
  assert(sizeof(ParticleEngine) == 0xE430);
  assert(sizeof(Lightmap) == 0xC1C);
  assert(sizeof(LightmapBuilder) == 0x3CBC38);
  assert(sizeof(Vis_SelectionList) == 0x2008);
  assert(sizeof(Vis) == 0x20D0);
  assert(sizeof(PlayerBuffAnim) == 0x10);
  assert(sizeof(ProjectileAnim) == 0x1C);
  assert(sizeof(stru6) == 0x5F8);
  assert(sizeof(IndoorCameraD3D_Vec3) == 0x10);
  assert(sizeof(IndoorCameraD3D_Vec4) == 0x18); //should be 14 (10 vec3 + 4 vdtor)  but 18 coz of his +4 from own vdtor, but it is odd since vdtor already present from vec3
  assert(sizeof(IndoorCameraD3D) == 0x1A1384);
  assert(sizeof(StationaryLight) == 0xC);
  assert(sizeof(LightsStack_StationaryLight_) == 0x12C8);
  assert(sizeof(MobileLight) == 0x12);
  assert(sizeof(LightsStack_MobileLight_) == 0x1C28);
  assert(sizeof(Game) == 0xE78);
  assert(sizeof(stru141) == 0xA8);
  assert(sizeof(ActionQueue) == 0x7C);
  assert(sizeof(NPCData) == 0x4C);
  assert(sizeof(NPCStats) == 0x17FFC);
  assert(sizeof(BspRenderer) == 0x53740);
  assert(sizeof(PaletteManager) == 0x267AF0);
  assert(sizeof(ViewingParams) == 0x26C);
  assert(sizeof(IndoorCamera) == 0x50);
  assert(sizeof(Bloodsplat) == 0x28);
  assert(sizeof(BloodsplatContainer) == 0xA0C);
  assert(sizeof(stru167) == 0x18);
  assert(sizeof(EventIndex) == 0xC);
  assert(sizeof(_2devent) == 0x34);
  assert(sizeof(stru176) == 0x20);
  assert(sizeof(SavegameHeader) == 0x64);
  assert(sizeof(SavegameList) == 0x3138);
  assert(sizeof(StorylineText) == 0x160);
  assert(sizeof(FactionTable) == 0x1EF1);
  assert(sizeof(Decal) == 0xC20);
  assert(sizeof(DecalBuilder) == 0x30C038);
  assert(sizeof(MonsterInfo) == 0x58);
  assert(sizeof(MonsterStats) == 0x5BA0);
  assert(sizeof(RenderD3D) == 0x148);
  assert(sizeof(Render) == 0x129844);
  assert(sizeof(Player) == 0x1B3C);
  assert(sizeof(Party_stru0) == 0x678);
  assert(sizeof(Party) == 0x16238);
  assert(sizeof(GUIButton) == 0xBC);
  assert(sizeof(GUIWindow) == 0x54);
  assert(sizeof(GUIProgressBar) == 0x1B8);
  assert(sizeof(GUIFont) == 0x1020);
  assert(sizeof(stru262_TurnBased) == 0x40);
  assert(sizeof(ArcomageGame) == 0xFB);
  assert(sizeof(CastSpellInfo) == 0x14);
  assert(sizeof(ArcomageCard) == 0x6C);
  assert(sizeof(stru320) == 0x3FC);
  assert(sizeof(TravelInfo) == 0x20);
  assert(sizeof(stru336) == 0x798);
  assert(sizeof(Vec3_short_) == 6);
  assert(sizeof(BLVFace) == 96);
  assert(sizeof(BLVFaceExtra) == 36);
  assert(sizeof(BLVSector) == 116);
  assert(sizeof(LevelDecoration) == 32);
  assert(sizeof(BLVLightMM7) == 16);
  assert(sizeof(BSPNode) == 8);
  assert(sizeof(SpawnPointMM7) == 24);
  assert(sizeof(DDM_DLV_Header) == 40);
  assert(sizeof(Actor) == 836);
  assert(sizeof(SpriteObject) == 112);
  assert(sizeof(Chest) == 5324);
  assert(sizeof(stru123) == 0xC8);
  assert(sizeof(BLVMapOutline) == 12);
  assert(sizeof(LODSprite) == 0x28);
}

bool new_sky = false;
bool change_seasons = false;
bool all_magic = true;

//----- (00462C94) --------------------------------------------------------
bool MM_Main(const wchar_t *pCmdLine)
{
  HWND hPrevWnd; // eax@1
  HWND hPrevWnd_; // esi@1
  HWND v6; // eax@4
  int v8; // eax@15
  //bool v9; // edx@16
  //OtherOverlay *v10; // esi@44
  //signed int v11; // edi@44
  //unsigned int v12; // ecx@56
  HANDLE v13; // eax@68
  unsigned int startms; // [sp+8h] [bp-24h]@55
  RECT Rect; // [sp+Ch] [bp-20h]@15
  int a2[4]; // [sp+1Ch] [bp-10h]@15
  
  IntegrityTest();
  char test[1024];
  sprintfex(test, "^Pi[%s]: çíàõàð^R[ü;êà;]", "Çîëòàí");

  bool bNoMargareth = false;
  if (pCmdLine && *pCmdLine)
  {
    if (wcsstr(pCmdLine, L"-usedefs"))
      bDebugResouces = 1;
    if (wcsstr(pCmdLine, L"-window"))
      dword_6BE368_debug_settings_2 |= 1u;

    if (wcsstr(pCmdLine, L"-nointro"))
      bNoIntro = true;//dword_6BE364_game_settings_1 |= 4;
    if (wcsstr(pCmdLine, L"-nologo"))
      bNoLogo = true;//dword_6BE364_game_settings_1 |= 8;
    if (wcsstr(pCmdLine, L"-nosound"))
      bNoSound = true; //dword_6BE364_game_settings_1 |= 0x10;

    bWalkSound = ReadWindowsRegistryInt("WalkSound", 1) != 0;
    if (wcsstr(pCmdLine, L"-nowalksound"))
      bWalkSound = false;//dword_6BE364_game_settings_1 |= 0x20;
    if (wcsstr(pCmdLine, L"-novideo"))
    {
      dword_6BE364_game_settings_1 |= 0x40;
      bNoVideo = true;
    }
    if (wcsstr(pCmdLine, L"-nocd"))
      bNoCD = true;
    if (wcsstr(pCmdLine, L"-new_sky"))
      new_sky = true;
    if (wcsstr(pCmdLine, L"-nomarg"))
      bNoMargareth = true;
  }


  /*v8 = _4AC1C9_get_cpu_speed(0, (Vec4_int_ *)a2);
  Rect.left = *(int *)v8;
  Rect.top = *(int *)(v8 + 4);
  Rect.right = *(int *)(v8 + 8);
  Rect.bottom = *(int *)(v8 + 12);
  uCPUSpeed = Rect.bottom;*/
  uCPUSpeed = 2048; // about 2GHz


  if (!MM7_Initialize())
  {
    Log::Warning(L"MM init: failed");
    pGame->Deinitialize();
    return 1;
  }


  Log::Warning(L"MM init: ok");

    pEventTimer->Pause();
    if ( pRenderer->bUserDirect3D && pRenderer->uAcquiredDirect3DDevice == 1 )
    {
      SetWindowPos(hWnd, (HWND)((int)HWND_MESSAGE|0x2), 320, 240, 640, 480, 0);
      Rect.left = 325;
      Rect.top = 245;
      Rect.right = 326;
      Rect.bottom = 246;
      ClipCursor(&Rect);
    }
    SetUserInterface(PartyAlignment_Neutral, false);
    ShowIntroVideo_and_LoadingScreen();
    WriteWindowsRegistryInt("Ran once", 1);
    dword_6BE364_game_settings_1 |= 0x4000;
    pGame->InitializeGammaController();
    SecondaryInitialization();
    pRenderer->SetRasterClipRect(0, 0, 639u, 479u);
    FinalInitialization();

    Log::Warning(L"MM: entering main loop");
    while ( 1 )
    {
      MainMenu_Loop();
      uGameState = GAME_STATE_PLAYING;
//LABEL_21:
      while ( 1 )
      {
        if (uGameState == GAME_FINISHED ||
            GetCurrentMenuID() == MENU_EXIT_GAME)
        {
          pGame->Deinitialize();
          return true;
        }

        if (GetCurrentMenuID() == MENU_NEWGAME)
        {
          if ( pAudioPlayer->hAILRedbook )
            AIL_redbook_stop(pAudioPlayer->hAILRedbook);
          pParty->Reset();
          pOtherOverlayList->Reset();

          strcpy(pCurrentMapName.data(), pStartingMapName.data());
          pParty->CreateDefaultParty(0);
          PlayerCreationUI_Initialize();
          if ( PlayerCreationUI_Loop() )
          {
            DeleteCCharFont();
            break;
          }
          DeleteCCharFont();
          bFlashQuestBook = true;
          pGame->pCShow->PlayMovie(MOVIE_Emerald, 0);
          SaveNewGame();

          if (bNoMargareth)
            _449B7E_toggle_bit(pParty->_quest_bits, PARTY_QUEST_EMERALD_MARGARETH_OFF, 1);
          pGame->Loop();

          if (uGameState == GAME_STATE_NEWGAME_OUT_GAMEMENU)
          {
            SetCurrentMenuID(MENU_NEWGAME);
            uGameState = GAME_STATE_PLAYING;
            continue;
          }
          else if (uGameState == GAME_STATE_GAME_QUITTING_TO_MAIN_MENU)
            break;

          assert(false && "Invalid game state");
        }
        if (GetCurrentMenuID() == MENU_CREDITS)
        {
         if ( pAudioPlayer->hAILRedbook )
          AIL_redbook_stop(pAudioPlayer->hAILRedbook);
         MainMenuUI_Credits_Loop();
         break;
        }
        if (GetCurrentMenuID() == MENU_5 || GetCurrentMenuID() == MENU_LoadingProcInMainMenu)
        {
          uGameState = GAME_STATE_PLAYING;
        }
        else
        {
          if (GetCurrentMenuID() != MENU_10)
            goto LABEL_49;
          pMouse->Activate(0);

          pParty->Reset();
          pParty->CreateDefaultParty(1);
          crt_init_globals_46271C();
          extern OPENFILENAMEA ofn;
          if ( !GetOpenFileNameA((LPOPENFILENAMEA)&ofn) )
          {
            pMouse->Activate(1);

            break;
          }
          _chdir("..\\");
          strcpy(pCurrentMapName.data(), ofn.lpstrFileTitle);
          pMouse->Activate(1);
        }
//LABEL_48:
        pGame->Loop();
LABEL_49:
        if ( uGameState == GAME_STATE_3 )
        {
          SetCurrentMenuID(MENU_5);
          uGameState = GAME_STATE_PLAYING;
          continue;
        }
        if ( uGameState == GAME_STATE_NEWGAME_OUT_GAMEMENU )
        {
          SetCurrentMenuID(MENU_NEWGAME);
          uGameState = GAME_STATE_PLAYING;
          continue;
        }
        if ( uGameState == GAME_STATE_GAME_QUITTING_TO_MAIN_MENU)// from the loaded game
        {
          pAudioPlayer->StopChannels(-1, -1);
          uGameState = GAME_STATE_PLAYING;
          break;
        }
      }
      if (!bNoSound && pAudioPlayer->hAILRedbook)
      {
        pAudioPlayer->SetMusicVolume(pSoundVolumeLevels[uMusicVolimeMultiplier] * 64.0f);
        AIL_redbook_stop(pAudioPlayer->hAILRedbook);
        unsigned int end_ms;
        AIL_redbook_track_info(pAudioPlayer->hAILRedbook, 0xE, &startms, &end_ms);
        AIL_redbook_play(pAudioPlayer->hAILRedbook, startms + 1, end_ms);
      }
    }

  pGame->Deinitialize();
  return 1;
}

//----- (004637E0) --------------------------------------------------------
char __cdecl sub_4637E0_is_there_popup_onscreen()
{
  return dword_507BF0_is_there_popup_onscreen == 1;
}
// 507BF0: using guessed type int dword_507BF0_is_there_popup_onscreen;

//----- (00466082) --------------------------------------------------------
void MM6_Initialize(const wchar_t *pIniFilename)
{
  //int v0; // eax@1
  UINT v1; // eax@18
  size_t v2; // eax@31
  size_t v3; // ebx@32
  size_t v4; // edi@36
  //char v5[120]; // [sp+Ch] [bp-17Ch]@1
  //char String[120]; // [sp+84h] [bp-104h]@32
  char pDefaultGroundTexture[16]; // [sp+FCh] [bp-8Ch]@32
  //char pIniFilename[120]; // [sp+10Ch] [bp-7Ch]@1
  unsigned int v9; // [sp+184h] [bp-4h]@28

  //_getcwd(v5, 120);
  //sprintfex(pIniFilename, "%s\\mm6.ini", v5);
  viewparams = new ViewingParams;
  game_viewport_x = viewparams->uScreen_topL_X = GetPrivateProfileIntW(L"screen", L"vx1", 8, pIniFilename);
  game_viewport_y = viewparams->uScreen_topL_Y = GetPrivateProfileIntW(L"screen", L"vy1", 8, pIniFilename);
  game_viewport_z = viewparams->uScreen_BttmR_X = GetPrivateProfileIntW(L"screen", L"vx2", 468, pIniFilename);
  game_viewport_w = viewparams->uScreen_BttmR_Y = GetPrivateProfileIntW(L"screen", L"vy2", 351, pIniFilename);
  game_viewport_width = game_viewport_z - game_viewport_x;
  game_viewport_height = game_viewport_w - game_viewport_y + 1;


  pAudioPlayer = new AudioPlayer;
  pAudioPlayer->uMixerChannels = GetPrivateProfileIntW(L"settings", L"mixerchannels", 16, pIniFilename);
  if ( pAudioPlayer->uMixerChannels > 16 )
    pAudioPlayer->uMixerChannels = 16;


  if (GetPrivateProfileIntW(L"debug", L"nomonster", 0, pIniFilename))
    dword_6BE368_debug_settings_2 |= 4;
  if (bUseRegistry)
    v1 = ReadWindowsRegistryInt("startinwindow", 0);
  else
    v1 = GetPrivateProfileIntW(L"debug", L"startinwindow", 0, pIniFilename);
  if (v1)
    dword_6BE368_debug_settings_2 |= 1;
  if (GetPrivateProfileIntW(L"debug", L"showFR", 0, pIniFilename))
    dword_6BE368_debug_settings_2 |= 2;
  if (GetPrivateProfileIntW(L"debug", L"nodamage", 0, pIniFilename))
    dword_6BE368_debug_settings_2 |= 0x10;
  if (GetPrivateProfileIntW(L"debug", L"nodecoration", 0, pIniFilename))
    dword_6BE368_debug_settings_2 |= 8;

  wchar_t pStartingMapNameW[1024];
  GetPrivateProfileStringW(L"file", L"startmap", L"out01.odm", pStartingMapNameW, 0x20u, pIniFilename);
  sprintf(pStartingMapName.data(), "%S", pStartingMapNameW);

  v9 = 0;
  if ( strlen(pStartingMapName.data()) )
  {
    do
    {
      if ( pStartingMapName[v9] == 32 )
        pStartingMapName[v9] = 0;
      ++v9;
      v2 = strlen(pStartingMapName.data());
    }
    while ( v9 < v2 );
  }

  pOutdoorCamera = new OutdoorCamera;
  outdoor_day_top_r      = GetPrivateProfileIntW(L"outdoor", L"RGBDayTop.r", 81, pIniFilename);
  outdoor_day_top_g      = GetPrivateProfileIntW(L"outdoor", L"RGBDayTop.g", 121, pIniFilename);
  outdoor_day_top_b      = GetPrivateProfileIntW(L"outdoor", L"RGBDayTop.b", 236, pIniFilename);
  outdoor_day_bottom_r   = GetPrivateProfileIntW(L"outdoor", L"RGBDayBottom.r", 153, pIniFilename);
  outdoor_day_bottom_g   = GetPrivateProfileIntW(L"outdoor", L"RGBDayBottom.g", 193, pIniFilename);
  outdoor_day_bottom_b   = GetPrivateProfileIntW(L"outdoor", L"RGBDayBottom.b", 237, pIniFilename);
  outdoor_night_top_r    = GetPrivateProfileIntW(L"outdoor", L"RGBNightTop.r", 0, pIniFilename);
  outdoor_night_top_g    = GetPrivateProfileIntW(L"outdoor", L"RGBNightTop.g", 0, pIniFilename);
  outdoor_night_top_b    = GetPrivateProfileIntW(L"outdoor", L"RGBNightTop.b", 0, pIniFilename);
  outdoor_night_bottom_r = GetPrivateProfileIntW(L"outdoor", L"RGBNightBottom.r", 11, pIniFilename);
  outdoor_night_bottom_g = GetPrivateProfileIntW(L"outdoor", L"RGBNightBottom.g", 41, pIniFilename);
  outdoor_night_bottom_b = GetPrivateProfileIntW(L"outdoor", L"RGBNightBottom.b", 129, pIniFilename);
  pOutdoorCamera->outdoor_no_mist = GetPrivateProfileIntW(L"debug", L"noMist", 0, pIniFilename);
  pOutdoorCamera->bNoSky          = GetPrivateProfileIntW(L"outdoor", L"nosky", 0, pIniFilename);
  pOutdoorCamera->bDoNotRenderDecorations = GetPrivateProfileIntW(L"render", L"nodecorations", 0, pIniFilename);
  pOutdoorCamera->outdoor_no_wavy_water   = GetPrivateProfileIntW(L"outdoor", L"nowavywater", 0, pIniFilename);
  outdoor_grid_band_1 = GetPrivateProfileIntW(L"outdoor", L"gridband1", 10, pIniFilename);
  outdoor_grid_band_2 = GetPrivateProfileIntW(L"outdoor", L"gridband2", 15, pIniFilename);
  outdoor_grid_band_3 = GetPrivateProfileIntW(L"outdoor", L"gridband3", 25, pIniFilename);
  pOutdoorCamera->terrain_gamma  = GetPrivateProfileIntW(L"outdoor", L"ter_gamma", 0, pIniFilename);
  pOutdoorCamera->building_gamme = GetPrivateProfileIntW(L"outdoor", L"bld_gamma", 0, pIniFilename);
  mipmapping_terrain_mm1  = GetPrivateProfileIntW(L"mipmapping", L"ter_mm1", 2048, pIniFilename);
  mipmapping_terrain_mm2  = GetPrivateProfileIntW(L"mipmapping", L"ter_mm2", 4096, pIniFilename);
  mipmapping_terrain_mm3  = GetPrivateProfileIntW(L"mipmapping", L"ter_mm3", 8192, pIniFilename);
  mipmapping_building_mm1 = GetPrivateProfileIntW(L"mipmapping", L"bld_mm1", 1024, pIniFilename);
  mipmapping_building_mm2 = GetPrivateProfileIntW(L"mipmapping", L"bld_mm2", 2048, pIniFilename);
  mipmapping_building_mm3 = GetPrivateProfileIntW(L"mipmapping", L"bld_mm3", 4096, pIniFilename);
  pOutdoorCamera->shading_dist_shade     = GetPrivateProfileIntW(L"shading", L"dist_shade", 2048, pIniFilename);
  pOutdoorCamera->shading_dist_shademist = GetPrivateProfileIntW(L"shading", L"dist_shademist", 4096, pIniFilename);
  pOutdoorCamera->shading_dist_mist      = GetPrivateProfileIntW(L"shading", L"dist_mist", 8192, pIniFilename);

  wchar_t pDefaultSkyTextureW[1024];
  GetPrivateProfileStringW(L"textures", L"sky", L"plansky1", pDefaultSkyTextureW, 0x10u, pIniFilename);
  sprintf(pDefaultSkyTexture.data(), "%S", pDefaultSkyTextureW);

  wchar_t pDefaultGroundTextureW[1024];
  GetPrivateProfileStringW(L"textures", L"default", L"dirt", pDefaultGroundTextureW, 0x10u, pIniFilename);
  sprintf(pDefaultGroundTexture, "%S", pDefaultGroundTextureW);

  wchar_t pFloat[1024];
  GetPrivateProfileStringW(L"debug", L"recmod1", L"1.0", pFloat, 0x10u, pIniFilename);
  swscanf(pFloat, L"%f", &flt_6BE3A4_debug_recmod1);

  GetPrivateProfileStringW(L"debug", L"recmod2", L"1.0", pFloat, 0x10u, pIniFilename);
  swscanf(pFloat, L"%f", &flt_6BE3A8_debug_recmod2);

  flt_6BE3AC_debug_recmod1_x_1_6 = flt_6BE3A4_debug_recmod1 * 1.666666666666667;

  v3 = 0;
  if ( strlen(pDefaultSkyTexture.data()) )
  {
    do
    {
      if ( pDefaultSkyTexture[v3] == ' ' )
        pDefaultSkyTexture[v3] = 0;
      ++v3;
    }
    while ( v3 < strlen(pDefaultSkyTexture.data()) );
  }
  v4 = 0;
  if ( strlen(pDefaultGroundTexture) )
  {
    do
    {
      if ( pDefaultGroundTexture[v4] == ' ' )
        pDefaultGroundTexture[v4] = 0;
      ++v4;
    }
    while ( v4 < strlen(pDefaultGroundTexture) );
  }

  texmapping_terrain_subdivsize  = GetPrivateProfileIntW(L"texmapping", L"terrain_subdivsize", 16, pIniFilename);
  texmapping_terrain_subdivpow2  = GetPrivateProfileIntW(L"texmapping", L"terrain_subdivpow2", 4, pIniFilename);
  texmapping_building_subdivsize = GetPrivateProfileIntW(L"texmapping", L"building_subdivsize", 32, pIniFilename);
  texmapping_building_subdivpow2 = GetPrivateProfileIntW(L"texmapping", L"building_subdivpow2", 5, pIniFilename);

  MM7Initialization();
}

//----- (004666D5) --------------------------------------------------------
void __cdecl MM7Initialization()
{
  if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
  {
    if ( !byte_6BE388_graphicsmode )
    {
      outdoor_grid_band_1 = 10;
      outdoor_grid_band_2 = 15;
      outdoor_grid_band_3 = 20;
      pOutdoorCamera->shading_dist_mist = 8192;
      pOutdoorCamera->bNoSky = 0;
      LOBYTE(viewparams->field_20) = 0;
    }
    mipmapping_terrain_mm1 = 1024;
    mipmapping_terrain_mm2 = 2048;
    mipmapping_building_mm1 = 1024;
    mipmapping_building_mm2 = 2048;
    pOutdoorCamera->shading_dist_shade = 2048;
    pOutdoorCamera->terrain_gamma = 0;
    pOutdoorCamera->building_gamme = 0;
    mipmapping_terrain_mm3 = 4096;
    mipmapping_building_mm3 = 4096;
    pOutdoorCamera->shading_dist_shademist = 4096;
    pOutdoorCamera->outdoor_no_wavy_water = 0;
    sub_47F4D3(outdoor_grid_band_1, outdoor_grid_band_2, outdoor_grid_band_3);
  }
  else
  {
    LOBYTE(viewparams->field_20) = 0;
  }
  pParty->uFlags |= 2u;
  viewparams->uSomeY = viewparams->uScreen_topL_Y;
  viewparams->uSomeX = viewparams->uScreen_topL_X;
  viewparams->uSomeZ = viewparams->uScreen_BttmR_X;
  viewparams->uSomeW = viewparams->uScreen_BttmR_Y;

  pViewport->SetScreen(viewparams->uScreen_topL_X, viewparams->uScreen_topL_Y, viewparams->uScreen_BttmR_X, viewparams->uScreen_BttmR_Y);
  if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
    pOutdoorCamera->_485F64();
}

//----- (00466B8C) --------------------------------------------------------
int __cdecl AbortWithError()
{
  if ( !aborting_app )
  {
    ClipCursor(0);
    aborting_app = 1;
    if ( !pRenderer->bWindowMode )
      pRenderer->ChangeBetweenWinFullscreenModes();
    if ( MessageBoxA(0, pGlobalTXT_LocalizationStrings[176], pGlobalTXT_LocalizationStrings[59], 0x34u) == 6 )
      SaveGame(1, 0);                           // "Internal Error"
                                                // "Might and Magic VII has detected an internal error and will be forced to close.  Would you like us to autosave your game before closing?"
    Game_DeinitializeAndTerminate(1);
  }
  return 0;
}
// 720018: using guessed type int aborting_app;

//----- (00466BE5) --------------------------------------------------------
void Abortf(const char *Format, ...)
{
  va_list va; // [sp+8h] [bp+8h]@1

  va_start(va, Format);
  if ( !pRenderer->bWindowMode )
    pRenderer->ChangeBetweenWinFullscreenModes();
  vsprintf(pTmpBuf.data(), Format, va);
  if ( pMouse )
    pMouse->Activate(0);
  ClipCursor(0);
  MessageBoxA(0, pTmpBuf.data(), "Error", 0x30u);
  Game_DeinitializeAndTerminate(1);
}

//----- (00466C40) --------------------------------------------------------
const wchar_t *MENU_STATE_to_string(MENU_STATE m)
{
  switch (m)
  {
    case -1:                return L"-1";
    case MENU_MAIN:         return L"MENU_MAIN";
    case MENU_NEWGAME:      return L"MENU_NEWGAME";
    case MENU_CREDITS:      return L"MENU_CREDITS";
    case MENU_SAVELOAD:     return L"MENU_SAVELOAD";
    case MENU_EXIT_GAME:    return L"MENU_EXIT_GAME";
    case MENU_5:            return L"MENU_5";
    case MENU_CREATEPARTY:  return L"MENU_CREATEPARTY";
    case MENU_NAMEPANELESC: return L"MENU_NAMEPANELESC";
    case MENU_CREDITSPROC:  return L"MENU_CREDITSPROC";
    case MENU_LoadingProcInMainMenu: return L"MENU_LoadingProcInMainMenu";
    case MENU_10:           return L"MENU_10";
    case MENU_CREDITSCLOSE: return L"MENU_CREDITSCLOSE";
    default:                return L"unk";
  };
};
void SetCurrentMenuID(MENU_STATE uMenu)
{
  uCurrentMenuID = uMenu;

  Log::Warning(L"CurrentMenu = %s", MENU_STATE_to_string(uMenu));
}

//----- (00466CA0) --------------------------------------------------------
MENU_STATE GetCurrentMenuID()
{
  return uCurrentMenuID;
}


//----- (00467E7F) --------------------------------------------------------
void sub_467E7F_EquipBody(ITEM_EQUIP_TYPE uEquipType)
{
  //unsigned int v1; // esi@1
  int v2; // ebx@1
  Player *v3; // eax@1
  int v4; // edx@1
  int v5; // esi@2
  //int v6; // eax@2
  unsigned int v7; // eax@3
  ItemGen _this; // [sp+Ch] [bp-30h]@1
  //Player *v9; // [sp+30h] [bp-Ch]@1
  int v10; // [sp+34h] [bp-8h]@1
  int *v11; // [sp+38h] [bp-4h]@1

  static unsigned char byte_4E8398[200] = // 4E8398
  {
     1, // EQUIP_OFF_HAND
     1, // EQUIP_MAIN_HAND
     2, // EQUIP_BOW
     3, // EQUIP_ARMOUR
     0, // EQUIP_SHIELD
     4, // EQUIP_HELMET
     5, // EQUIP_BELT
     6, // EQUIP_CLOAK
     7, // EQUIP_GAUNTLETS
     8, // EQUIP_BOOTS
    10, // EQUIP_RING
     9, // EQUIP_AMULET
     1, // EQUIP_WAND
     0, // EQUIP_REAGENT
     0, // EQUIP_POTION
     0, // EQUIP_SPELL_SCROLL
     0, // EQUIP_BOOK
     0, // EQUIP_MESSAGE_SCROLL
     0, // EQUIP_GOLD
     0, // EQUIP_GEM
     0, // EQUIP_NONE
  // ???
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
     0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0,  0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0,
     0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0,  0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,  1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,  0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 3, 3, 3, 3, 3, 3, 1, 1, 1,
     1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2,  2, 0, 0, 0, 0, 0
};

  _this.Reset();
  v2 = byte_4E8398[uEquipType];
  v3 = pPlayers[uActiveCharacter];
  v11 = (int *)&v3->pEquipment.pIndices[v2];
  v4 = *v11;
  v10 = *v11;
  if ( v10 )
  {
    memcpy(&_this, &pParty->pPickedItem, sizeof(_this));
    v5 = (int)((char *)v3 + 4 * (9 * v4 - 9));
    *(char *)(v5 + 556) = 0;
    pParty->pPickedItem.Reset();
    pParty->SetHoldingItem((ItemGen *)(v5 + 532));
    _this.uBodyAnchor = v2 + 1;
    memcpy((void *)(v5 + 532), &_this, 0x24u);
    *v11 = v10;
  }
  else
  {
    v7 = v3->FindFreeInventorySlot();
    if (v7 >= 0)
    {
      pParty->pPickedItem.uBodyAnchor = v2 + 1;
      memcpy(&v3->pInventoryItems[v7], &pParty->pPickedItem, sizeof(v3->pInventoryItems[v7]));
      *v11 = v7 + 1;
      pMouse->RemoveHoldingItem();
    }
  }
}

//----- (00467F48) --------------------------------------------------------
void CreateMsgScrollWindow( signed int mscroll_id )
    {
  signed int v1; // esi@1

  v1 = mscroll_id;
  if ( !pGUIWindow_ScrollWindow && mscroll_id >= 700 )
  {
    if ( mscroll_id <= 782 )
    {
      uTextureID_720980 = pIcons_LOD->LoadTexture("leather", TEXTURE_16BIT_PALETTE);
      pGUIWindow_ScrollWindow = GUIWindow::Create(0, 0, 640, 480, WINDOW_Scroll, v1 - 700, 0);
    }
  }
}
// 720980: using guessed type int uTextureID_720980;

//----- (00467F9F) --------------------------------------------------------
void __cdecl free_book_subwindow()
{
  if ( pGUIWindow_ScrollWindow )
  {
    pGUIWindow_ScrollWindow->Release();
    pGUIWindow_ScrollWindow = 0;
  }
}

//----- (00467FB6) --------------------------------------------------------
void CreateScrollWindow()
    {
  unsigned int v0; // eax@1
  char *v1; // ST18_4@3
  unsigned int v2; // eax@3
  GUIWindow a1; // [sp+Ch] [bp-54h]@1

  memcpy(&a1, pGUIWindow_ScrollWindow, sizeof(a1));
  a1.Hint = 0;
  a1.uFrameX = 1;
  a1.uFrameY = 1;
  a1.uFrameWidth = 468;
  v0 = pFontSmallnum->CalcTextHeight(pScrolls[(unsigned int)pGUIWindow_ScrollWindow->ptr_1C], &a1, 0, 0)
     + 2 * LOBYTE(pFontCreate->uFontHeight)
     + 24;
  a1.uFrameHeight = v0;
  if ( (signed int)(v0 + a1.uFrameY) > 479 )
  {
    v0 = 479 - a1.uFrameY;
    a1.uFrameHeight = 479 - a1.uFrameY;
  }
  a1.uFrameZ = a1.uFrameWidth + a1.uFrameX - 1;
  a1.uFrameW = v0 + a1.uFrameY - 1;
  a1.DrawMessageBox(0);
  a1.uFrameX += 12;
  a1.uFrameWidth -= 24;
  a1.uFrameY += 12;
  a1.uFrameHeight -= 12;
  a1.uFrameZ = a1.uFrameWidth + a1.uFrameX - 1;
  a1.uFrameW = a1.uFrameHeight + a1.uFrameY - 1;
  v1 = pItemsTable->pItems[(unsigned int)pGUIWindow_ScrollWindow->ptr_1C + 700].pName;
  v2 = TargetColor(0xFFu, 0xFFu, 0x9Bu);
  sprintf(pTmpBuf.data(), format_4E2D80, v2, v1);
  a1.DrawTitleText(pFontCreate, 0, 0, 0, pTmpBuf.data(), 3u);
  a1.DrawText(
           pFontSmallnum,
           1,
           LOBYTE(pFontCreate->uFontHeight) - 3,
           0,
           pScrolls[(unsigned int)pGUIWindow_ScrollWindow->ptr_1C],
           0,
           0,
           0);
}

//----- (00468F8A) --------------------------------------------------------
void __cdecl OnPaperdollLeftClick()
{
  int v1; // ecx@1
  unsigned int v2; // edi@1
  unsigned int v3; // edx@4
  unsigned int pSkillType; // esi@5
  unsigned __int16 v5; // ax@7
  unsigned int v6; // edi@19
  int v7; // esi@27
  unsigned int v8; // eax@29
  int v9; // edx@32
  int v10; // esi@34
  int v11; // eax@34
  int v12; // esi@38
  int v13; // eax@38
  char v14; // zf@38
  int v15; // esi@42
  int v16; // eax@42
  int v17; // eax@44
  unsigned int v18; // ecx@55
  unsigned int v19; // eax@55
  int v20; // esi@60
  int v21; // eax@60
  unsigned int v22; // eax@61
  unsigned int v23; // eax@62
  int v24; // esi@65
  int v25; // eax@65
  unsigned int v26; // eax@69
  int v27; // esi@81
  int v28; // eax@81
  int v29; // esi@84
  int v30; // eax@84
  int v31; // eax@85
  unsigned int v32; // ecx@88
  unsigned int v33; // eax@88
  int v34; // esi@90
  unsigned int v35; // eax@91
  int v36; // esi@93
  int v37; // edi@93
  ItemGen *v38; // edi@93
  __int16 v39; // dx@99
  ItemGen _this; // [sp+Ch] [bp-40h]@1
  unsigned int v48; // [sp+30h] [bp-1Ch]@88
  unsigned int v49; // [sp+34h] [bp-18h]@57
  unsigned int v50; // [sp+38h] [bp-14h]@50
  int v51; // [sp+3Ch] [bp-10h]@1
  unsigned int v52; // [sp+40h] [bp-Ch]@5
  //int v53; // [sp+44h] [bp-8h]@1
  //unsigned int v54; // [sp+48h] [bp-4h]@1

  v51 = 0;
  _this.Reset();
  //v0 = pPlayers[uActiveCharacter];
  v1 = pPlayers[uActiveCharacter]->pEquipment.uMainHand;
  v2 = pPlayers[uActiveCharacter]->pEquipment.uShield;
  //v54 = pPlayers[uActiveCharacter]->pEquipment.uShield;
  //v53 = v1;
  if ( v1 && pItemsTable->pItems[*(int *)&pPlayers[uActiveCharacter]->pInventoryItems[v1 - 1]].uEquipType == 1 )
    v51 = v1;
  v3 = pParty->pPickedItem.uItemID;
  if ( pParty->pPickedItem.uItemID )
  {
    v52 = pItemsTable->pItems[pParty->pPickedItem.uItemID].uEquipType;
    pSkillType = pItemsTable->pItems[pParty->pPickedItem.uItemID].uSkillType;
    if ( pSkillType == 4 )
    {
      if ( v2 )
      {
        LOBYTE(v5) = pPlayers[uActiveCharacter]->GetActualSkillLevel(PLAYER_SKILL_SPEAR);
        if ( (signed int)SkillToMastery(v5) < 3 )
        {
          pPlayers[uActiveCharacter]->PlaySound(SPEECH_39, 0);
          return;
        }
        v3 = pParty->pPickedItem.uItemID;
      }
    }
    else
    {
      if ( (pSkillType == 8 || pSkillType == 1 || pSkillType == 2)
        && v1
        && pItemsTable->pItems[*(int *)&pPlayers[uActiveCharacter]->pInventoryItems[v1-1]].uSkillType == 4 )
	  {
        LOBYTE(v5) = pPlayers[uActiveCharacter]->GetActualSkillLevel(PLAYER_SKILL_SPEAR);
        if ( (signed int)SkillToMastery(v5) < 3 )
        {
          pPlayers[uActiveCharacter]->PlaySound(SPEECH_39, 0);
          return;
        }
	  }
    }
    if ( !pPlayers[uActiveCharacter]->CanEquip_RaceAndAlignmentCheck(v3) )
    {

        pPlayers[uActiveCharacter]->PlaySound(SPEECH_39, 0);
        return;
    }
    if ( pParty->pPickedItem.uItemID == 604 )
    {
      sub_467E7F_EquipBody((ITEM_EQUIP_TYPE)3);
      WetsuitOn(uActiveCharacter);
      return;
    }
    v6 = v52;
    switch ( v52 )
    {
      case 2u:
      case 3u:
      case 5u:
      case 6u:
      case 7u:
      case 8u:
      case 9u:
      case 0xBu:
        if ( !pPlayers[uActiveCharacter]->HasSkill(pSkillType) )
        {
          pPlayers[uActiveCharacter]->PlaySound(SPEECH_39, 0);
          return;
        }
        if ( sub_43EE77_ProbablyIfUnderwaterSuitIsEquipped(uActiveCharacter) && (v6 != 3 || bUnderwater) )
		{
			pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
			return;
		}
        sub_467E7F_EquipBody((ITEM_EQUIP_TYPE)v6);
        if ( pParty->pPickedItem.uItemID == 604 )
          WetsuitOff(uActiveCharacter);
        return;
      case 0xAu:
        if ( sub_43EE77_ProbablyIfUnderwaterSuitIsEquipped(uActiveCharacter) )
		{
			pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
			return;
		}
        v52 = 10;
        v7 = (int)&pPlayers[uActiveCharacter]->pEquipment.uRings;
        while ( 1 )
        {
          if ( !*(int *)v7 )
          {
            v8 = pPlayers[uActiveCharacter]->FindFreeInventorySlot();
            if ( (v8 & 0x80000000u) == 0 )
			{
			  v9 = v52;
			  pParty->pPickedItem.uBodyAnchor = v52 + 1;
			  memcpy(&pPlayers[uActiveCharacter]->pInventoryItems[v8], &pParty->pPickedItem, sizeof(pPlayers[uActiveCharacter]->pInventoryItems[v8]));
			  *(&pPlayers[uActiveCharacter]->pEquipment.uShield + v9) = v8 + 1;
			  pMouse->RemoveHoldingItem();
              break;
			}
          }
          ++v52;
          v7 += 4;
          if ( (signed int)v52 > 15 )
            break;
        }
        if ( v52 == 16 )
        {
          v52 = pPlayers[uActiveCharacter]->pEquipment.uRings[6] - 1;
          memcpy(&_this, &pParty->pPickedItem, sizeof(_this));
          v10 = (int)((char *)pPlayers[uActiveCharacter] + 36 * v52);
          *(char *)(v10 + 556) = 0;
          pParty->pPickedItem.Reset();
          pParty->SetHoldingItem((ItemGen *)(v10 + 532));
          _this.uBodyAnchor = 16;
          v11 = v52 + 1;
          memcpy((void *)(v10 + 532), &_this, 0x24u);
          pPlayers[uActiveCharacter]->pEquipment.uRings[6] = v11;
        }
        return;
      case 4u:
        if ( sub_43EE77_ProbablyIfUnderwaterSuitIsEquipped(uActiveCharacter) )
		{
			pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
			return;
		}
        if ( !pPlayers[uActiveCharacter]->HasSkill(pSkillType) )
        {
          pPlayers[uActiveCharacter]->PlaySound(SPEECH_39, 0);
          return;
        }
        if ( v2 )
        {
          --v2;
          memcpy(&_this, &pParty->pPickedItem, sizeof(_this));
          v12 = (int)((char *)pPlayers[uActiveCharacter] + 36 * v2);
          *(char *)(v12 + 556) = 0;
          pParty->pPickedItem.Reset();
          pParty->SetHoldingItem((ItemGen *)(v12 + 532));
          _this.uBodyAnchor = 1;
          v13 = v2 + 1;
          v14 = v51 == 0;
          memcpy((void *)(v12 + 532), &_this, 0x24u);
          pPlayers[uActiveCharacter]->pEquipment.uShield = v13;
          if ( v14 )
            return;
        }
        else
        {
          v52 = pPlayers[uActiveCharacter]->FindFreeInventorySlot();
          if ( (v52 & 0x80000000u) != 0 )
            return;
          if ( !v51 )
          {
            pParty->pPickedItem.uBodyAnchor = 1;
            v17 = v52 + 1;
            memcpy(&pPlayers[uActiveCharacter]->pInventoryItems[v52], &pParty->pPickedItem, sizeof(pPlayers[uActiveCharacter]->pInventoryItems[v52]));
            pPlayers[uActiveCharacter]->pEquipment.uShield = v17;
            pMouse->RemoveHoldingItem();
	        return;
          }
          memcpy(&_this, &pParty->pPickedItem, sizeof(_this));
          v15 = (int)((char *)pPlayers[uActiveCharacter] + 36 * (v1 - 1));
          *(char *)(v15 + 556) = 0;
          pParty->pPickedItem.Reset();
          pParty->SetHoldingItem((ItemGen *)(v15 + 532));
          _this.uBodyAnchor = 1;
          v16 = v52 + 1;
          memcpy(&pPlayers[uActiveCharacter]->pInventoryItems[v52], &_this, sizeof(pPlayers[uActiveCharacter]->pInventoryItems[v52]));
          pPlayers[uActiveCharacter]->pEquipment.uShield = v16;
        }
        pPlayers[uActiveCharacter]->pEquipment.uMainHand = 0;
        return;
      case 0u:
      case 0xCu:
        if ( sub_43EE77_ProbablyIfUnderwaterSuitIsEquipped(uActiveCharacter)
          && pParty->pPickedItem.uItemID != 64
          && pParty->pPickedItem.uItemID != 65 )
		{
			pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
			return;
		}
        if ( !pPlayers[uActiveCharacter]->HasSkill(pSkillType) )
        {
          pPlayers[uActiveCharacter]->PlaySound(SPEECH_39, 0);
          return;
        }
        v50 = 0;
        if ( pSkillType == 2 && (unsigned __int16)(pPlayers[uActiveCharacter]->pActiveSkills[2] & 0xFFC0)
          || pSkillType == 1 && (signed int)SkillToMastery(pPlayers[uActiveCharacter]->pActiveSkills[1]) >= 3 )
        {

            v18 = pMouse->uMouseClickX;
            v19 = pMouse->uMouseClickY;

          v49 = v19;
          if ( (signed int)v18 >= 560 )
          {
            if ( !v51 )
            {
              if ( v2 )
              {
                --v2;
                memcpy(&_this, &pParty->pPickedItem, sizeof(_this));
                v20 = (int)((char *)pPlayers[uActiveCharacter] + 36 * v2);
                *(char *)(v20 + 556) = 0;
                pParty->pPickedItem.Reset();
                pParty->SetHoldingItem((ItemGen *)(v20 + 532));
                _this.uBodyAnchor = 1;
                v21 = v2 + 1;
                v14 = v52 == 12;
                memcpy((void *)(v20 + 532), &_this, 0x24u);
                pPlayers[uActiveCharacter]->pEquipment.uShield = v21;
                if ( !v14 )
                  return;
                v22 = _this.uItemID;
                v50 = v22;
				if ( v50 )
                {
                __debugbreak();  // looks like offset in player's inventory and wand_lut much like case in 0042ECB5
				  stru_A750F8[uActiveCharacter - 1]._494836(*((int *)&pSpellDatas[66].uNormalLevelRecovery + v50), uActiveCharacter - 1 + 9);
                }
				break;
              }
              v23 = pPlayers[uActiveCharacter]->FindFreeInventorySlot();
              if ( (v23 & 0x80000000u) != 0 )
                return;
              pParty->pPickedItem.uBodyAnchor = 1;
              v50 = (unsigned int)&pPlayers[uActiveCharacter]->pInventoryItems[v23];
              memcpy(&pPlayers[uActiveCharacter]->pInventoryItems[v23], &pParty->pPickedItem, sizeof(pPlayers[uActiveCharacter]->pInventoryItems[v23]));
              pPlayers[uActiveCharacter]->pEquipment.uShield = v23 + 1;
              pMouse->RemoveHoldingItem();
              if ( v52 != 12 )
                return;
              v22 = *(int *)v50;
			  v50 = v22;
			  if ( v50 )
              {
                __debugbreak();  // looks like offset in player's inventory and wand_lut much like case in 0042ECB5
				stru_A750F8[uActiveCharacter - 1]._494836(*((int *)&pSpellDatas[66].uNormalLevelRecovery + v50), uActiveCharacter - 1 + 9);
              }
			  break;
            }
          }
        }
        if ( !v1 )
        {
          v26 = pPlayers[uActiveCharacter]->FindFreeInventorySlot();
          if ( (v26 & 0x80000000u) != 0 )
            return;
          pParty->pPickedItem.uBodyAnchor = 2;
          v50 = (unsigned int)&pPlayers[uActiveCharacter]->pInventoryItems[v26];
          memcpy(&pPlayers[uActiveCharacter]->pInventoryItems[v26], &pParty->pPickedItem, sizeof(pPlayers[uActiveCharacter]->pInventoryItems[v26]));
          pPlayers[uActiveCharacter]->pEquipment.uMainHand = v26 + 1;
              pMouse->RemoveHoldingItem();
              if ( v52 != 12 )
                return;
              v22 = *(int *)v50;
			  v50 = v22;
			  if ( v50 )
              {
                __debugbreak();  // looks like offset in player's inventory and wand_lut much like case in 0042ECB5
				stru_A750F8[uActiveCharacter - 1]._494836(*((int *)&pSpellDatas[66].uNormalLevelRecovery + v50), uActiveCharacter - 1 + 9);
              }
			  break;
        }
        --v1;
        memcpy(&_this, &pParty->pPickedItem, sizeof(_this));
        v24 = (int)((char *)pPlayers[uActiveCharacter] + 36 * v1);
        *(char *)(v24 + 556) = 0;
        pParty->pPickedItem.Reset();
        pParty->SetHoldingItem((ItemGen *)(v24 + 532));
        _this.uBodyAnchor = 2;
        v25 = v1 + 1;
        v14 = v52 == 12;
        memcpy((void *)(v24 + 532), &_this, 0x24u);
        pPlayers[uActiveCharacter]->pEquipment.uMainHand = v25;
        if ( v14 )
          v50 = _this.uItemID;
        if ( v51 )
          pPlayers[uActiveCharacter]->pEquipment.uShield = 0;
        if ( v50 )
        {
                __debugbreak();  // looks like offset in player's inventory and wand_lut much like case in 0042ECB5
          stru_A750F8[uActiveCharacter - 1]._494836( *((int *)&pSpellDatas[66].uNormalLevelRecovery + v50), uActiveCharacter - 1 + 9);
        }
        break;
      case 1u:
        if ( sub_43EE77_ProbablyIfUnderwaterSuitIsEquipped(uActiveCharacter) )
		{
			pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
			return;
		}
        if ( !pPlayers[uActiveCharacter]->HasSkill(pSkillType) )
        {
          pPlayers[uActiveCharacter]->PlaySound(SPEECH_39, 0);
          return;
        }
        if ( v1 )
        {
          if ( v2 )
          {
			pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
			return;
          }
          --v1;
          memcpy(&_this, &pParty->pPickedItem, sizeof(_this));
          v27 = (int)((char *)pPlayers[uActiveCharacter] + 36 * v1);
          *(char *)(v27 + 556) = 0;
          pParty->pPickedItem.Reset();
          pParty->SetHoldingItem((ItemGen *)(v27 + 532));
          _this.uBodyAnchor = 2;
          v28 = v1 + 1;
          memcpy((void *)(v27 + 532), &_this, 0x24u);
          pPlayers[uActiveCharacter]->pEquipment.uMainHand = v28;
        }
        else
        {
          v52 = pPlayers[uActiveCharacter]->FindFreeInventorySlot();
          if ( (v52 & 0x80000000u) == 0 )
          {
            if ( v2 )
            {
              memcpy(&_this, &pParty->pPickedItem, sizeof(_this));
              v29 = (int)((char *)pPlayers[uActiveCharacter] + 36 * (v2 - 1));
              *(char *)(v29 + 556) = 0;
              pParty->pPickedItem.Reset();
              pParty->SetHoldingItem((ItemGen *)(v29 + 532));
              _this.uBodyAnchor = 2;
              v30 = v52 + 1;
              memcpy(&pPlayers[uActiveCharacter]->pInventoryItems[v52], &_this, sizeof(pPlayers[uActiveCharacter]->pInventoryItems[v52]));
              pPlayers[uActiveCharacter]->pEquipment.uShield = 0;
              pPlayers[uActiveCharacter]->pEquipment.uMainHand = v30;
            }
            else
            {
              pParty->pPickedItem.uBodyAnchor = 2;
              v31 = v52 + 1;
              memcpy(&pPlayers[uActiveCharacter]->pInventoryItems[v52], &pParty->pPickedItem, sizeof(pPlayers[uActiveCharacter]->pInventoryItems[v52]));
              pPlayers[uActiveCharacter]->pEquipment.uMainHand = v31;
              pMouse->RemoveHoldingItem();
            }
          }
        }
        return;
      default:
        pPlayers[uActiveCharacter]->UseItem_DrinkPotion_etc(uActiveCharacter, 0);
        return;
    }
    return;
  }

    v32 = pMouse->uMouseClickX;
    v33 = pMouse->uMouseClickY;

  v34 = pRenderer->pActiveZBuffer[v32 + pSRZBufferLineOffsets[v33]] & 0xFFFF;
  if ( v34 )
  {
    v36 = v34 - 1;
    v37 = (int)((char *)pPlayers[uActiveCharacter] + 36 * v36);
    v50 = v37;
    v38 = (ItemGen *)(v37 + 532);
    v14 = v38->uItemID == 604;
    v52 = pItemsTable->pItems[v38->uItemID].uEquipType;
    if ( v14 )
    {
      if ( bUnderwater )
      {
        pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
        return;
      }
      WetsuitOff(uActiveCharacter);
    }
    if ( unk_50C9A0 )
    {
      *((char *)pGUIWindow_Settings->ptr_1C + 8) &= 0x7Fu;
      *((short *)pGUIWindow_Settings->ptr_1C + 2) = uActiveCharacter - 1;
      v39 = v52;
      *((int *)pGUIWindow_Settings->ptr_1C + 3) = v36;
      *((short *)pGUIWindow_Settings->ptr_1C + 3) = v39;
      ptr_50C9A4 = v38;
      unk_50C9A0 = 0;
      if ( pMessageQueue_50CBD0->uNumMessages )
        pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
      pMouse->SetCursorBitmap("MICON1");
      dword_50C9D4 = 0;
      dword_50C9D0 = 113;
      dword_50C9D8 = 256;
    }
    else
    {
      if ( !ptr_50C9A4 )
      {
        pParty->SetHoldingItem(v38);
        *(&pPlayers[uActiveCharacter]->uBirthYear + *(char *)(v50 + 556)) = 0;
        v38->Reset();
      }
    }
  }
  else
  {
    v35 = pPlayers[uActiveCharacter]->pEquipment.uBow;
    if ( v35 )
    {
      auto _a = (ItemGen *)&pPlayers[uActiveCharacter]->pInventoryItems[v35 - 1];
      pParty->SetHoldingItem(_a);
      _a->Reset();
      pPlayers[uActiveCharacter]->pEquipment.uBow = 0;
    }
  }
}


//----- (0046A14B) --------------------------------------------------------
void OnPressSpace()
{
  //SHORT v0; // ax@2
  int *v1; // eax@2
  char *v2; // ebx@5
  unsigned int v3; // esi@5
  signed int v4; // edi@7
  unsigned int v5; // edx@7
  int v6; // ecx@8
  int v7; // eax@8
  int v8; // ecx@17
  int *v9; // esi@22
  signed int v10; // ebx@22
  int i; // edi@23
  int v12; // edx@24
  int v13; // ecx@24
  int j; // esi@28
  int v16; // [sp+4h] [bp-1Ch]@0
  char *v17; // [sp+8h] [bp-18h]@5
  unsigned int v18; // [sp+Ch] [bp-14h]@5
  int v19; // [sp+10h] [bp-10h]@8
  int *v20; // [sp+14h] [bp-Ch]@5
  int *v21; // [sp+18h] [bp-8h]@7
  int v22; // [sp+1Ch] [bp-4h]@4

  if ( pRenderer->pRenderD3D )
  {
    pGame->PickKeyboard(GetAsyncKeyState(VK_CONTROL) & 0x8001, &vis_sprite_filter_3, &vis_door_filter);
    auto pid = pGame->pVisInstance->get_picked_object_zbuf_val();
    if ( pid != -1 )
      DoInteractionWithTopmostZObject(pid & 0xFFFF, PID_ID(pid));
    return;
  }

  
  // software render stuff following

  static int dword_720660[100]; // 720660
  static int dword_7207F0[100]; // 7207F0

  v22 = 0;
  v1 = (int *)((signed int)(viewparams->uScreen_BttmR_X + viewparams->uScreen_topL_X) >> 1);//wrong pointer
  if ( (signed int)viewparams->uScreen_topL_Y < (signed int)viewparams->uScreen_BttmR_Y )
  {
	  v2 = (char *)v1 - 50;
	  v1 = (int *)((char *)v1 + 50);
	  v3 = 640 * viewparams->uScreen_topL_Y;
	  v17 = v2;
	  v20 = v1;
	  v18 = ((viewparams->uScreen_BttmR_Y - viewparams->uScreen_topL_Y - 1) >> 1) + 1;
	  do
	  {
		if ( (signed int)v2 < (signed int)v20 )
		{
			v1 = &pRenderer->pActiveZBuffer[(int)&v2[v3]];
			v21 = &pRenderer->pActiveZBuffer[(int)&v2[v3]];
			v4 = v22;
			v5 = (((char *)v20 - v2 - 1) >> 1) + 1;
			do
			{
			  v6 = 0;
			  v7 = *v1 & 0xFFFF;
			  v19 = 0;
			  if ( v4 > 0 )
			  {
				do
				{
				  if ( dword_7207F0[v6] == v7 )
					break;
				  ++v6;
				  v19 = v6;
				}
				while ( v6 < v22 );
			  }
			  if ( PID_TYPE(v7) == OBJECT_Decoration)
			  {
				v16 = (unsigned int)PID_ID(v7);
				if ( (signed int)(((unsigned int)*v21 >> 16)
								- pDecorationList->pDecorations[pLevelDecorations[(unsigned int)PID_ID(v7)].uDecorationDescID].uRadius) <= 512 )
				  if ( v19 == v22 && v4 < 100 )
				  {
					++v22;
					++v4;
					v8 = *v21;
					dword_7207F0[v4 - 1] = v7;
					dword_720660[v4 - 1] = v8;
				  }
			  }
			  else if ( (unsigned int)*v21 <= 0x2000000 )
			  {
				  if ( v19 == v22 && v4 < 100 )
				  {
					++v22;
					++v4;
					v8 = *v21;
					dword_7207F0[v4 - 1] = v7;
					dword_720660[v4 - 1] = v8;
				  }
			  }
			  v1 = v21 + 2;
			  --v5;
			  v21 += 2;
			}
			while ( v5 );
			v2 = v17;
		}
		v3 += 1280;
		--v18;
	  }
	  while ( v18 );
  }
  if ( v22 > 0 )
  {
    v9 = dword_720660;
    v10 = 1;
    do
    {
      for ( i = v10; i < v22; ++i )
      {
        v12 = *v9;
        v13 = dword_720660[i];
        if ( v13 < *v9 )
        {
          *v9 = v13;
          dword_720660[i] = v12;
        }
      }
      ++v10;
      ++v9;
      LOBYTE(v1) = v10 - 1;
    }
    while ( v10 - 1 < v22 );
  }
  for ( j = 0; j < v22; ++j )
  {
    LOBYTE(v1) = DoInteractionWithTopmostZObject(dword_720660[j] & 0xFFFF, v16);
    if ( !(char)v1 )
      break;
  }
}

//----- (0046A334) --------------------------------------------------------
char __fastcall DoInteractionWithTopmostZObject(int a1, int a2)
{
  int v2; // edx@1
  BLVFace *v4; // eax@9
  unsigned int v5; // ecx@9
  unsigned __int16 v6; // ax@11
  //ODMFace *v7; // eax@16
  LevelDecoration *v8; // esi@19
  __int16 v9; // ax@19
  int v10; // eax@22
  int v11; // ecx@22
  int v12; // edi@23
  Actor *v13; // esi@23
  unsigned __int16 v14; // ax@23
  unsigned __int16 v15; // ax@33
  const char *v16; // eax@34
  int v17; // edi@36
  int v18; // eax@36
  ItemGen *v19; // esi@39
  unsigned int v20; // eax@39
  int v21; // ecx@40
  std::string v22; // [sp-18h] [bp-2Ch]@5
  const char *v23; // [sp-8h] [bp-1Ch]@5
  int v24; // [sp-4h] [bp-18h]@5
  char v25; // [sp+8h] [bp-Ch]@5
  int v26; // [sp+Ch] [bp-8h]@1
  int a3; // [sp+13h] [bp-1h]@5

  v26 = a2;
  v2 = a1;
  switch ( PID_TYPE(a1) )
  {
    case OBJECT_Item: // take the item
      v17 = PID_ID(a1);
      v26 = PID_ID(a1);
      v18 = PID_ID(a1);
      if ( pObjectList->pObjects[pSpriteObjects[v18].uObjectDescID].uFlags & 0x10
        || v17 >= 1000
        || !pSpriteObjects[v18].uObjectDescID )
        return 1;
      v19 = &pSpriteObjects[v18].stru_24;
      v20 = pSpriteObjects[v18].stru_24.uItemID;
      if ( pItemsTable->pItems[v20].uEquipType == EQUIP_GOLD)
      {
        party_finds_gold(v19->uSpecEnchantmentType, 0);
        viewparams->bRedrawGameUI = 1;
        v21 = v17;
      }
      else
      {
        if ( pParty->pPickedItem.uItemID )
          return 1;
        v24 = (int)pItemsTable->pItems[v20].pUnidentifiedName;
        sprintfex(pTmpBuf2.data(), pGlobalTXT_LocalizationStrings[471], v24);
        ShowStatusBarString(pTmpBuf2.data(), 2u);
        if ( v19->uItemID == 506 )
          _449B7E_toggle_bit(pParty->_quest_bits, 184, 1u);
        if ( v19->uItemID == 455 )
          _449B7E_toggle_bit(pParty->_quest_bits, 185, 1u);
        if ( !pParty->AddItem(v19) )
          pParty->SetHoldingItem(v19);
        v21 = v26;
      }
      SpriteObject::OnInteraction(v21);
      break;

    case OBJECT_Actor:
      v12 = PID_ID(a1);
      v13 = &pActors[PID_ID(a1)];
      v14 = v13->uAIState;
      if ( v14 == 4 || v14 == 17 )
        return 1;
      if ( v14 == 5 )
      {
        stru_50C198.LootActor(&pActors[PID_ID(a1)]);
      }
      else
      {
        if ( !v13->GetActorsRelation(0) && !(BYTE2(v13->uAttributes) & 8) && v13->CanAct() )
        {
          Actor::AI_FaceObject(v12, 4u, 0, 0);
          if ( v13->sNPC_ID )
          {
            pMessageQueue_50CBD0->AddMessage(UIMSG_StartNPCDialogue, v12, 0);
          }
          else
          {
            v15 = pNPCStats->pGroups_copy[v13->uGroup];
            if ( v15 )
            {
              v16 = pNPCStats->pCatchPhrases[v15];
              if ( v16 )
              {
                pParty->uFlags |= 2u;
                strcpy(byte_5B0938.data(), v16);
                sub_4451A8_press_any_key(0, 0, 0);
              }
            }
          }
        }
      }
      break;

    case OBJECT_Decoration:
      v8 = &pLevelDecorations[PID_ID(a1)];
      v9 = v8->field_16_event_id;
      if ( v9 )
      {
        EventProcessor(v9, a1, 1);
        LOBYTE(v8->field_2) |= 8u;
      }
      else
      {
        if ( !pLevelDecorations[PID_ID(a1)].IsInteractive() )
          return 1;
        v10 = v8->_idx_in_stru123;
        v24 = 1;
        v11 = stru_5E4C90._decor_events[v10 - 75] + 380;
        activeLevelDecoration = v8;
        EventProcessor(v11, 0, 1);
        activeLevelDecoration = NULL;
      }
      break;

    default:
      MessageBoxW(nullptr, L"Warning: Invalid ID reached!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Mouse.cpp:2020", 0);
      return 1;

    case OBJECT_BModel:
      if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
      {
        int bmodel_id = a1 >> 9,
            face_id = PID_ID(a1) & 0x3F;
        if (bmodel_id >= pOutdoor->uNumBModels)
          return 1;
        auto face = &pOutdoor->pBModels[bmodel_id].pFaces[face_id];
        if (face->uAttributes & 0x100000 || face->sCogTriggeredID == 0 )
          return 1;
        EventProcessor((signed __int16)face->sCogTriggeredID, v2, 1);
      }
      else
      {
        v4 = &pIndoor->pFaces[PID_ID(a1)];
        v5 = v4->uAttributes;
        if ( !(v5 & 0x2000000) )
        {
          ShowNothingHereStatus();
          return 1;
        }
        if ( v5 & 0x100000 || (v6 = pIndoor->pFaceExtras[v4->uFaceExtraID].uEventID) == 0 )
          return 1;
        if ( pCurrentScreen != SCREEN_BRANCHLESS_NPC_DIALOG )
          EventProcessor((signed __int16)v6, v2, 1);
      }
      return 0;
      break;
  }
  return 0;
}
// 4E28F8: using guessed type int pCurrentScreen;

//----- (0046A6AC) --------------------------------------------------------
int __fastcall sub_46A6AC(int a1, int a2, int a3)
{
  int result; // eax@2
  unsigned int v4; // edx@3
  int *v5; // esi@6
  unsigned int v6; // ebx@6
  signed int v7; // edi@9
  unsigned __int16 v8; // ax@9
  int i; // eax@14
  int v10; // ecx@19
  int v11; // [sp+0h] [bp-18h]@1
  unsigned int v12; // [sp+4h] [bp-14h]@3
  unsigned int v13; // [sp+8h] [bp-10h]@4
  int v14; // [sp+Ch] [bp-Ch]@1
  int *v15; // [sp+10h] [bp-8h]@4
  int v16; // [sp+14h] [bp-4h]@3

  v11 = a2;
  v14 = a1;
  if ( pRenderer->pRenderD3D )
  {
    result = sub_46A7C8(a1, a2, a3);
  }
  else
  {
    v16 = 0;
    v4 = viewparams->uScreen_topL_X;
    v12 = viewparams->uScreen_BttmR_X;
    if ( (signed int)viewparams->uScreen_topL_Y < (signed int)viewparams->uScreen_BttmR_Y )
    {
      v15 = &pRenderer->pActiveZBuffer[viewparams->uScreen_topL_X + 640 * viewparams->uScreen_topL_Y];
      v13 = ((viewparams->uScreen_BttmR_Y - viewparams->uScreen_topL_Y - 1) >> 1) + 1;
      do
      {
        if ( (signed int)v4 < (signed int)v12 )
        {
          v5 = v15;
          v6 = ((v12 - v4 - 1) >> 1) + 1;
          do
          {
            if ( PID_TYPE(*(char *)v5) == OBJECT_Actor)
            {
              if ( *v5 <= a3 << 16 )
              {
                v7 = PID_ID((signed int)(unsigned __int16)*v5);
                v8 = pActors[v7].uAIState;
                if ( v8 != 5 )
                {
                  if ( v8 != 4 && v8 != 11 && v8 != 17 && v8 != 19 )
                  {
                    for ( i = 0; i < v16; ++i )
                    {
                      if ( *(int *)(v14 + 4 * i) == v7 )
                        break;
                    }
                    if ( i == v16 )
                    {
                      if ( i < v11 - 1 )
                      {
                        v10 = v16++;
                        *(int *)(v14 + 4 * v10) = v7;
                      }
                    }
                  }
                }
              }
            }
            v5 += 2;
            --v6;
          }
          while ( v6 );
        }
        v15 += 1280;
        --v13;
      }
      while ( v13 );
    }
    result = v16;
  }
  return result;
}

//----- (0046A7C8) --------------------------------------------------------
int __fastcall sub_46A7C8(int a1, int a2, signed int a3)
{
  unsigned int v3; // eax@2
  int v4; // ecx@2
  unsigned int v5; // eax@2
  unsigned int v6; // eax@4
  unsigned int v7; // edi@4
  unsigned __int16 v8; // ax@4
  float v9; // ST00_4@9
  int v10; // ecx@11
  unsigned int v12; // [sp+10h] [bp-14h]@1
  int v13; // [sp+14h] [bp-10h]@1
  int v14; // [sp+18h] [bp-Ch]@1
  int v15; // [sp+1Ch] [bp-8h]@1
  unsigned int a1a; // [sp+20h] [bp-4h]@1

  v13 = a1;
  v14 = a2;
  v15 = 0;
  a1a = 0;
  v12 = pRenderer->GetBillboardDrawListSize();
  if ( (signed int)v12 > 0 )
  {
    do
    {
      v3 = pRenderer->GetParentBillboardID(a1a);
      v4 = pBillboardRenderList[v3].sZValue;
      v5 = (unsigned __int16)pBillboardRenderList[v3].object_pid;
      if ( PID_TYPE(v5) == OBJECT_Actor)
      {
        if ( v4 <= (unsigned int)(a3 << 16) )
        {
          v6 = PID_ID(v5);
          v7 = v6;
          v8 = pActors[v6].uAIState;
          if ( v8 != Dead )
          {
            if ( v8 != Dying )
            {
              if ( v8 != Removed )
              {
                if ( v8 != Disabled )
                {
                  if ( v8 != Summoned )
                  {
                    v9 = (double)a3;
                    if ( pGame->pVisInstance->DoesRayIntersectBillboard(v9, a1a) )
                    {
                      if ( v15 < v14 - 1 )
                      {
                        v10 = v15++;
                        *(int *)(v13 + 4 * v10) = v7;
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
      ++a1a;
    }
    while ( (signed int)a1a < (signed int)v12 );
  }
  return v15;
}

//----- (0046A89E) --------------------------------------------------------
int __fastcall sub_46A89E(int a1, int a2, signed int a3)
{
  signed int v3; // edi@1
  Actor *v4; // esi@2
  int v5; // ebx@3
  int v6; // eax@3
  int v7; // ebx@3
  unsigned int v8; // ecx@3
  int v9; // edx@4
  unsigned int v10; // edx@6
  unsigned int v11; // edx@8
  __int16 v12; // ax@10
  int v13; // ecx@15
  int v15; // [sp+4h] [bp-18h]@1
  int v16; // [sp+8h] [bp-14h]@1
  int v17; // [sp+Ch] [bp-10h]@3
  int v18; // [sp+10h] [bp-Ch]@3
  int v19; // [sp+18h] [bp-4h]@1

  v3 = 0;
  v15 = a2;
  v16 = a1;
  v19 = 0;
  if ( (signed int)uNumActors > 0 )
  {
    v4 = pActors.data();//[0].uAIState;
    do
    {
	  v5 = abs(v4->vPosition.x - pParty->vPosition.x);
	  v17 = abs(v4->vPosition.y - pParty->vPosition.y);
	  v18 = abs(v4->vPosition.z - pParty->vPosition.z);
      v6 = v5;
      v7 = v17;
      v8 = v18;
      if ( v6 < v17 )
      {
        v9 = v6;
        v6 = v17;
        v7 = v9;
      }
      if ( v6 < v18 )
      {
        v10 = v6;
        v6 = v18;
        v8 = v10;
      }
      if ( v7 < (signed int)v8 )
      {
        v11 = v8;
        v8 = v7;
        v7 = v11;
      }
      if ( (signed int)(((unsigned int)(11 * v7) >> 5) + (v8 >> 2) + v6) <= a3 )
      {
		v12 = v4->uAIState;
        if ( v4->uAIState != 5 )
        {
          if ( v12 != 4 )
          {
            if ( v12 != 11 )
            {
              if ( v12 != 19 )
              {
                if ( v12 != 17 )
                {
                  v13 = v19++;
                  *(int *)(v16 + 4 * v13) = v3;
                  if ( v19 >= v15 - 1 )
                    break;
                }
              }
            }
          }
        }
      }
      ++v3;
      ++v4;
    }
    while ( v3 < (signed int)uNumActors );
  }
  return v19;
}

//----- (0046A99B) --------------------------------------------------------
int __cdecl sub_46A99B()
{
  int v0; // ebx@1
  signed int v1; // ecx@1
  signed int v2; // esi@1
  int v3; // edx@1
  signed int v4; // eax@1
  int v5; // ecx@2
  int *v6; // eax@3
  int v7; // ecx@3
  int v8; // edx@5
  int v9; // edi@6
  unsigned __int8 v10; // zf@14
  char v11; // sf@14
  char v12; // of@14
  int *v14; // esi@19
  signed int v15; // ebx@19
  int i; // edi@20
  int v17; // ecx@21
  int v18; // edi@26
  int v19; // esi@27
  unsigned int v20; // ecx@27
  BLVFace *v21; // eax@32
  unsigned int v22; // ecx@33
  const char *v23; // eax@35
  const char *v24; // ecx@36
  LevelDecoration *v25; // ecx@43
  LevelDecoration *v26; // edi@43
  __int16 v27; // ax@43
  int v28; // [sp+Ch] [bp-18h]@1
  int v29; // [sp+14h] [bp-10h]@2
  int v30; // [sp+18h] [bp-Ch]@1
  signed int v31; // [sp+1Ch] [bp-8h]@3
  int v32; // [sp+20h] [bp-4h]@1

  v0 = 0;
  v1 = (signed int)(viewparams->uScreen_BttmR_Y + viewparams->uScreen_topL_Y) >> 1;
  v2 = (signed int)(viewparams->uScreen_topL_X + viewparams->uScreen_BttmR_X) >> 1;
  v3 = v1 - 50;
  v32 = 0;
  v4 = 100;
  v30 = v1 - 50;
  v28 = v1 + 50;
  if ( v1 - 50 >= v1 + 50 )
    return 0;
  v5 = 640 * v3;
  v29 = 640 * v3;
  while ( 2 )
  {
    v31 = 100;
    v6 = &pRenderer->pActiveZBuffer[v2 + v5 - v4 / 2];
    v7 = v0;
    while ( 1 )
    {
      v8 = *v6;
      --v31;
      if ( (unsigned int)*v6 <= 0x2000000 )
      {
        v9 = 0;
        if ( v7 > 0 )
        {
          do
          {
            if ( dword_7201B0_zvalues[v9] == (unsigned __int16)v8 )
              break;
            ++v9;
          }
          while ( v9 < v0 );
        }
        if ( v9 == v0 )
        {
          if ( v8 & 7 )
          {
            dword_720020_zvalues[v7] = v8;
            dword_7201B0_zvalues[v7] = (unsigned __int16)v8;
            ++v7;
            ++v0;
            v32 = v0;
            if ( v7 == 99 )
            {
              v12 = 0;
              v10 = v0 == 0;
              v11 = v0 < 0;
              goto LABEL_18;
            }
          }
        }
      }
      if ( !v31 )
        break;
      ++v6;
    }
    v4 = -1;
    ++v30;
    v5 = v29 + 640;
    v29 += 640;
    if ( v30 < v28 )
      continue;
    break;
  }
  v12 = 0;
  v10 = v0 == 0;
  v11 = v0 < 0;
  if ( !v0 )
    return 0;
LABEL_18:
  if ( !((unsigned __int8)(v11 ^ v12) | v10) )
  {
    v14 = dword_720020_zvalues.data();
    v15 = 1;
    do
    {
      for ( i = v15; i < v32; ++i )
      {
        v17 = dword_720020_zvalues[i];
        if ( v17 < *v14 )
        {
          dword_720020_zvalues[i] = *v14;
          *v14 = v17;
        }
      }
      ++v15;
      ++v14;
    }
    while ( v15 - 1 < v32 );
    v0 = v32;
  }
  v18 = 0;
  if ( v0 <= 0 )
    return 0;
  while ( 1 )
  {
    v19 = dword_720020_zvalues[v18] & 0xFFFF;
    v20 = PID_ID(dword_720020_zvalues[v18]);
    if ( PID_TYPE(dword_720020_zvalues[v18]) == OBJECT_Item)
    {
      if ( v20 >= 0x3E8 )
        return 0;
      if ( !(pSpriteObjects[v20].uAttributes & 0x10) )
      {
        v23 = pSpriteObjects[v20].stru_24.GetDisplayName();
LABEL_36:
        v24 = v23;
        goto LABEL_51;
      }
      goto LABEL_41;
    }
    if ( PID_TYPE(dword_720020_zvalues[v18]) == OBJECT_Actor)
    {
      if ( v20 >= 0xBB8 )
        return 0;
      v24 = (const char *)&pActors[v20];
      goto LABEL_51;
    }
    if ( PID_TYPE(dword_720020_zvalues[v18]) == OBJECT_Decoration)
      break;
    if ( PID_TYPE(dword_720020_zvalues[v18]) == OBJECT_BModel)
    {
      if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
      {
        v21 = &pIndoor->pFaces[v20];
        if ( !(BYTE3(v21->uAttributes) & 2) )
          goto LABEL_41;
        v22 = pIndoor->pFaceExtras[v21->uFaceExtraID].uEventID;
      }
      else
      {
        if ( (dword_720020_zvalues[v18] & 0xFFFFu) >> 9 >= pOutdoor->uNumBModels )
          goto LABEL_41;
        v22 = pOutdoor->pBModels[(dword_720020_zvalues[v18] & 0xFFFFu) >> 9].pFaces[v20 & 0x3F].sCogTriggeredID;
      }
      if ( v22 )
      {
        v23 = GetEventHintString(v22);
        if ( v23 )
          goto LABEL_36;
      }
    }
LABEL_41:
    ++v18;
    if ( v18 >= v0 )
      return 0;
  }
  v25 = &pLevelDecorations[v20];
  v26 = v25;
  v27 = v25->field_16_event_id;
  if ( v27 )
  {
    v23 = GetEventHintString(v27);
    if ( !v23 )
      return v19;
    goto LABEL_36;
  }
  if ( v25->IsInteractive() )
    v24 = pNPCTopics[stru_5E4C90._decor_events[v26->_idx_in_stru123 - 75] + 379].pTopic;
  else
    v24 = pDecorationList->pDecorations[v26->uDecorationDescID].field_20;
LABEL_51:
  GameUI_SetFooterString(v24);
  return v19;
}

//----- (0046BDA8) --------------------------------------------------------
unsigned int __cdecl GetGravityStrength()
{
  int v0; // eax@1

  v0 = ~LOBYTE(pGame->uFlags2) & 8;
  LOBYTE(v0) = v0 | 2;
  return (unsigned int)v0 >> 1;
}

//----- (0046BDC0) --------------------------------------------------------
void __cdecl UpdateUserInput_and_MapSpecificStuff()
{
  if ( dword_6BE364_game_settings_1 & 0x80 )
  {
    LOBYTE(dword_6BE364_game_settings_1) = dword_6BE364_game_settings_1 & 0x7F;
  }
  else
  {
    if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
      BLV_UpdateUserInputAndOther();
    else if (uCurrentlyLoadedLevelType == LEVEL_Outdoor)
        ODM_UpdateUserInputAndOther();

    area_of_effect__damage_evaluate();
  }
}

//----- (0046BDF1) --------------------------------------------------------
void __cdecl BLV_UpdateUserInputAndOther()
{
  UpdateObjects();
  BLV_ProcessPartyActions();
  UpdateActors_BLV();
  BLV_UpdateDoors();
  check_event_triggers();
}

//----- (0046BE0A) --------------------------------------------------------
void __cdecl ODM_UpdateUserInputAndOther()
{
  bool v0; // eax@5
  char pOut[32]; // [sp+8h] [bp-20h]@5

  UpdateObjects();
  ODM_ProcessPartyActions();
  if ( pParty->vPosition.x < -22528
    || pParty->vPosition.x > 22528
    || pParty->vPosition.y < -22528
    || pParty->vPosition.y > 22528 )
  {
    strcpy(pOutdoor->pLevelFilename, pCurrentMapName.data());
    v0 = pOutdoor->GetTravelDestination(pParty->vPosition.x, pParty->vPosition.y, pOut, 32);
    if ( !bUnderwater && (pParty->uFlags & (PARTY_FLAGS_1_STANDING_ON_WATER | PARTY_FLAGS_1_FALLING | 0x04) || pParty->uFlags & 0x0200 || pParty->bFlying) || !v0 )
    {
      if ( pParty->vPosition.x < -22528 )
        pParty->vPosition.x = -22528;
      if ( pParty->vPosition.x > 22528 )
        pParty->vPosition.x = 22528;
      if ( pParty->vPosition.y < -22528 )
        pParty->vPosition.y = -22528;
      if ( pParty->vPosition.y > 22528 )
        pParty->vPosition.y = 22528;
    }
    else
    {
      pAudioPlayer->StopChannels(-1, -1);
      TravelUI_Load();
    }
  }
  UpdateActors_ODM();
  check_event_triggers();
}

//----- (0046BEF1) --------------------------------------------------------
void SpriteObject::_46BEF1_apply_spells_aoe()
{
  SpriteObject *v1; // edi@1
  Actor *v2; // esi@2
  __int16 v3; // fps@4
  unsigned __int8 v4; // c0@4
  unsigned __int8 v5; // c3@4
  signed int v6; // [sp+8h] [bp-4h]@1

  int v7,v8,v9,v10,v11;

  v6 = 0;
  v1 = this;
  if ( (signed int)uNumActors > 0 )
  {
    v2 = pActors.data();//[0].vPosition.y;
    do
    {
      if ( v2->CanAct() )
      {
        //UNDEF(v3);
		//.text:0046BF26                 movsx   eax, word ptr [esi-2]
		//.text:0046BF2A                 sub     eax, [edi+4]
		//.text:0046BF31                 mov     [ebp+var_8], eax
		//.text:0046BF37                 fild    [ebp+var_8]
		// v7 pushed to stack
		v7 = v2->vPosition.x - this->vPosition.x;

		//.text:0046BF2D                 movsx   ecx, word ptr [esi+2]
		v8 = v2->vPosition.z;

		//.text:0046BF34                 movsx   eax, word ptr [esi]
		//.text:0046BF3A                 sub     eax, [edi+8]
		//.text:0046BF3D                 mov     [ebp+var_8], eax
		//.text:0046BF44                 fild    [ebp+var_8]
		// v9 pushed to stack
		v9 = v2->vPosition.y - this->vPosition.y;

		//.text:0046BF40                 movsx   eax, word ptr [esi-6]
		//.text:0046BF47                 sar     eax, 1
		//.text:0046BF49                 add     eax, ecx
		//.text:0046BF4B                 sub     eax, [edi+0Ch]
		//.text:0046BF4E                 mov     [ebp+var_8], eax
		//.text:0046BF51                 fild    [ebp+var_8]
		//.text:0046BF58                 fld     st
		// v10 pushed to stack, two times
		v10 = v2->uActorHeight / 2 + v8 - this->vVelocity.y;

		//.text:0046BF54                 movsx   eax, word ptr [esi-8]
		//.text:0046BF5A                 add     eax, 100h
		//.text:0046BF63                 mov     ecx, eax
		v11 = this->vVelocity.x;

		//.text:0046BF5F                 fmul    st, st(1)
		// stack: v10*v10, v10, v9, v7
		//.text:0046BF61                 fld     st(2)
		// stack: v7, v10*v10, v10, v9, v7
		

		//.text:0046BF65                 fmul    st, st(3)
		// stack: v7*v9, v10*v10, v10, v9, v7
		
		//.text:0046BF67                 imul    ecx, eax
		v11 = v11 * v11;

		//.text:0046BF6A                 faddp   st(1), st
		// stack: v10*v10+v7*v9, v10, v9, v7
		//.text:0046BF6C                 fld     st(3)
		// stack: v7, v10*v10+v7*v9, v10, v9, v7
		//.text:0046BF6E                 fmul    st, st(4)
		// stack: v7*v7, v10*v10+v7*v9, v10, v9, v7
		//.text:0046BF70                 faddp   st(1), st
		// stack: v10*v10+v7*v9+v7*v7, v10, v9, v7
		
		//.text:0046BF72                 mov     [ebp+var_8], ecx
		//.text:0046BF75                 fild    [ebp+var_8]
		// v11 pushed to stack

		//.text:0046BF78                 fcompp
		// if ( v11 > v10*v10+v7*v9+v7*v7 )
		// stack: v10, v9, v7

		//.text:0046BF7A                 fstp    st
		// stack: v9, v7

		//.text:0046BF7C                 fnstsw  ax
		//.text:0046BF7E                 fstp    st
		// stack: v7

		//.text:0046BF80                 test    ah, 41h
		//.text:0046BF83                 fstp    st
		//.text:0046BF85                 jnz     short loc_46BFDD

		if ( v11 >= v10*v10+v7*v9+v7*v7 )
        {
          if ( stru_50C198.GetMagicalResistance(v2, 0xAu) )
          {
			  v2->pActorBuffs[v1->spell_id].Apply(
              pParty->uTimePlayed + (signed int)(signed __int64)((double)(v1->spell_level << 7) * 0.033333335),
              v1->spell_skill,
              4u,
              0,
              0);
            HIWORD(v2->uAttributes) |= 8u;
          }
        }
      }
      ++v6;
      ++v2;
    }
    while ( v6 < (signed int)uNumActors );
  }
}

//----- (0046BFFA) --------------------------------------------------------
bool __fastcall _46BFFA_check_object_intercept(unsigned int uLayingItemID, signed int a2)
{
  SpriteObject *v2; // esi@1
  ObjectDesc *v3; // ebx@1
  unsigned __int16 v5; // cx@9
  unsigned __int16 v6; // cx@14
  signed int v7; // edx@14
  unsigned int v8; // eax@19
  unsigned int v9; // edi@19
  signed int v10; // ebx@19
  char *v11; // edx@20
  unsigned __int16 v12; // ax@23
  int v13; // eax@27
  unsigned int v14; // ebx@33
  unsigned __int16 v15; // ax@35
  int v16; // eax@36
  unsigned int v17; // eax@37
  __int16 v18; // di@37
  signed int v19; // edx@37
  unsigned __int8 v20; // sf@37
  char *v21; // ecx@38
  unsigned __int16 v22; // ax@41
  unsigned int v23; // eax@46
  signed int v24; // ebx@46
  char *v25; // edx@47
  int v26; // edx@54
  int v27; // edx@55
  int v28; // edx@56
  int v29; // edx@57
  unsigned __int16 v30; // ax@60
  unsigned int v31; // ecx@60
  int v32; // edi@60
  unsigned int v33; // eax@65
  signed int v34; // edx@65
  char *v35; // ecx@66
  unsigned __int16 v36; // ax@69
  int v37; // ST14_4@72
  int v38; // eax@72
  int v39; // ST10_4@72
  int v40; // ST0C_4@72
  int v41; // edx@76
  int v42; // edx@77
  int v43; // edx@78
  unsigned __int8 v44; // zf@79
  int v45; // edx@79
  unsigned __int16 v46; // ax@80
  int v47; // eax@81
  int v48; // edx@87
  int v49; // edx@88
  int v50; // edx@89
  unsigned int v51; // eax@93
  signed int v52; // ebx@93
  char *v53; // edx@94
  unsigned __int16 v54; // ax@98
  unsigned int v55; // ecx@98
  signed int v56; // ebx@98
  char *v57; // edx@99
  unsigned __int16 v58; // ax@102
  unsigned __int16 v59; // ax@107
  unsigned int v60; // ecx@107
  signed int v61; // ebx@107
  char *v62; // edx@108
  unsigned __int16 v63; // ax@111
  int v64; // ebx@114
  signed int v65; // eax@114
  unsigned int v66; // edi@123
  unsigned __int16 v67; // ax@124
  unsigned int v68; // ecx@124
  signed int v69; // ebx@124
  char *v70; // edx@125
  unsigned __int16 v71; // ax@128
  unsigned int v72; // ebx@131
  int v73; // ST14_4@132
  int v74; // ST10_4@132
  int v75; // ebx@132
  int v76; // ST0C_4@132
  unsigned __int16 v77; // ax@132
  int v78; // eax@133
  char v79; // zf@139
  unsigned int v80; // eax@140
  signed int v81; // edx@140
  char *v82; // ecx@141
  unsigned __int16 v83; // ax@144
  unsigned __int16 v84; // ax@151
  unsigned int v85; // ecx@151
  signed int v86; // ebx@151
  char *v87; // edx@152
  unsigned __int16 v88; // ax@155
  unsigned int v89; // eax@158
  int v90; // ST34_4@159
  int v91; // eax@159
  unsigned int v92; // eax@163
  unsigned int v93; // eax@177
  char *v94; // ecx@178
  unsigned __int16 v95; // ax@181
  unsigned __int16 v96; // ax@184
  int v97; // eax@185
  unsigned __int16 v98; // ax@191
  unsigned int v99; // ecx@191
  char v100; // ST18_1@198
  int v101; // ST14_4@198
  int v102; // eax@198
  int v103; // ST10_4@198
  int v104; // ST0C_4@198
  unsigned __int16 v105; // ax@200
  signed int v106; // eax@208
  unsigned int v107; // edx@220
  signed int v108; // ebx@225
  unsigned int v109; // eax@234
  signed int v110; // ebx@234
  char *v111; // ecx@235
  unsigned __int16 v112; // ax@238
  unsigned __int16 v113; // si@241
  int v114; // eax@242
  int v115; // eax@245
  signed int v116; // eax@245
  unsigned __int16 v117; // ax@251
  unsigned int v118; // ecx@251
  signed int v119; // ebx@251
  char *v120; // edx@252
  unsigned __int16 v121; // ax@255
  unsigned int v122; // eax@260
  char *v123; // edx@261
  int v124; // eax@267
  int v125; // [sp-20h] [bp-4Ch]@28
  signed int v126; // [sp-1Ch] [bp-48h]@27
  unsigned int v127; // [sp-18h] [bp-44h]@27
  signed int v128; // [sp-14h] [bp-40h]@27
  signed int v129; // [sp-10h] [bp-3Ch]@27
  int v130; // [sp-Ch] [bp-38h]@27
  unsigned int v131; // [sp-8h] [bp-34h]@27
  char v132; // [sp-8h] [bp-34h]@131
  int v133; // [sp-4h] [bp-30h]@27
  char v134; // [sp-4h] [bp-30h]@131
  signed int v135; // [sp-4h] [bp-30h]@217
  int v136; // [sp+Ch] [bp-20h]@208
  int v137; // [sp+10h] [bp-1Ch]@208
  signed int v138; // [sp+14h] [bp-18h]@207
  signed int v139; // [sp+18h] [bp-14h]@208
  char *v140; // [sp+1Ch] [bp-10h]@61
  signed int v141; // [sp+1Ch] [bp-10h]@117
  unsigned int v142; // [sp+1Ch] [bp-10h]@158
  signed int v143; // [sp+1Ch] [bp-10h]@172
  char *v144; // [sp+1Ch] [bp-10h]@192
  signed int v145; // [sp+20h] [bp-Ch]@1
  signed int v146; // [sp+20h] [bp-Ch]@60
  int v147; // [sp+20h] [bp-Ch]@72
  signed int v148; // [sp+20h] [bp-Ch]@158
  int v149; // [sp+20h] [bp-Ch]@198
  unsigned __int16 v150; // [sp+20h] [bp-Ch]@208
  int v151; // [sp+24h] [bp-8h]@1
  signed int v152; // [sp+24h] [bp-8h]@208
  unsigned int v153; // [sp+28h] [bp-4h]@1

  v153 = uLayingItemID;
  v2 = &pSpriteObjects[uLayingItemID];
  v3 = &pObjectList->pObjects[v2->uObjectDescID];
  v145 = a2;
  v151 = PID_TYPE(a2);
  if ( PID_TYPE(a2) == OBJECT_Actor)
  {
    if ( PID_TYPE(v2->spell_caster_pid) == OBJECT_Actor && !pActors[PID_ID(v2->spell_caster_pid)].GetActorsRelation(&pActors[PID_ID(a2)]) )
      return 1;
  }
  else
  {
    if ( PID_TYPE(a2) == OBJECT_Player && PID_TYPE(v2->spell_caster_pid) == OBJECT_Player)
      return 1;
  }
  if ( pParty->bTurnBasedModeOn == 1 )
  {
    v5 = v2->uAttributes;
    if ( v5 & 4 )
    {
      --pTurnEngine->field_1C;
      v2->uAttributes = v5 & 0xFFFB;
    }
  }
  if ( v151 == OBJECT_BModel && PID_TYPE(v2->spell_caster_pid) != OBJECT_Player)
    BYTE2(pActors[PID_ID(v2->spell_caster_pid)].uAttributes) |= 4u;
  v6 = v2->uType;
  v7 = v2->uType;
  if ( v7 > 3060 )
  {
    if ( v7 > 6090 )
    {
      if ( v7 > 8090 )
      {
        if ( v7 == 9010 )
          goto LABEL_247;
        if ( v7 != 9030 )
        {
          if ( v7 != 9040 )
          {
            if ( v7 != 9080 )
              return 0;
LABEL_191:
            v98 = v6 + 1;
            v99 = pObjectList->uNumObjects;
            v32 = 0;
            v2->uType = v98;
            v146 = 0;
            if ( (signed int)v99 > 0 )
            {
              v144 = (char *)&pObjectList->pObjects->uObjectID;
              while ( v98 != *(short *)v144 )
              {
                ++v146;
                v144 += 56;
                if ( v146 >= (signed int)v99 )
                  goto LABEL_195;
              }
              goto LABEL_80;
            }
LABEL_195:
            v46 = 0;
            goto LABEL_196;
          }
          goto LABEL_93;
        }
LABEL_172:
        v143 = 17030;
        switch ( v6 )
        {
          case 0x1798u:
            v143 = 15040;
            break;
          case 0xFAAu:
            v143 = 13010;
            break;
          case 0x2346u:
            v143 = 18030;
            break;
        }
        v138 = 1;
        if ( v151 != OBJECT_Actor)
        {
          if ( v6 != 9030 || v2->spell_skill != 4 )
            goto LABEL_246;
          v2->_46BEF1_apply_spells_aoe();
LABEL_233:
          if ( !v138 )
          {
            v109 = pObjectList->uNumObjects;
            ++v2->uType;
            v110 = 0;
            if ( (signed int)v109 <= 0 )
            {
LABEL_238:
              v112 = 0;
            }
            else
            {
              v111 = (char *)&pObjectList->pObjects->uObjectID;
              while ( v2->uType != *(short *)v111 )
              {
                ++v110;
                v111 += 56;
                if ( v110 >= (signed int)v109 )
                  goto LABEL_238;
              }
              v112 = v110;
            }
            v2->uObjectDescID = v112;
            if ( !v112 )
              SpriteObject::OnInteraction(v153);
            v2->vVelocity.z = 0;
            v2->vVelocity.y = 0;
            v2->vVelocity.x = 0;
            v2->uSpriteFrameID = 0;
            v113 = v2->uSoundID;
            if ( v113 )
              v114 = (signed __int16)v113 + 4;
            else
              v114 = 0;
            v133 = 0;
            v131 = 0;
            v130 = v114;
            v115 = 8 * v153;
            v129 = 0;
            v128 = -1;
            LOBYTE(v115) = PID(OBJECT_Item,v153);
            v127 = 0;
            v126 = v115;
            v116 = v143;
            goto LABEL_269;
          }
LABEL_246:
          SpriteObject::OnInteraction(v153);
          return 0;
        }
        v106 = v145;
        v150 = 0;
        v139 = PID_ID(v106);
        v137 = v2->spell_level;
        v152 = v2->spell_skill;
        v136 = v2->spell_id;
        if ( v6 == 9030 )
        {
          v150 = 2;
          if ( v152 == 2 )
          {
            v150 = 3;
          }
          else
          {
            if ( v152 >= 3 )
              v150 = 4;
          }
          BYTE2(pActors[v139].uAttributes) |= 8u;
        }
        if ( v7 == 6040 )
        {
          v135 = 7;
        }
        else
        {
          if ( v7 == 8030 )
          {
            v135 = 9;
          }
          else
          {
            if ( v7 != 9030 )
            {
              v107 = v136;
LABEL_222:
              if ( v6 != 9030 || v152 != 4 )
              {
                v108 = v139;
                if ( stru_50C198.GetMagicalResistance(&pActors[v139], v107) )
                {
                  v138 = 0;
                  if ( v2->uType == 8030 )
                  {
                    pActors[v108].uAIState = Standing;
                    pActors[v108].UpdateAnimation();
                  }
                  pActors[v108].pActorBuffs[v136].Apply(
                    pParty->uTimePlayed + (signed int)(signed __int64)((double)(v137 << 7) * 0.033333335),
                    v152,
                    v150,
                    0,
                    0);
                }
              }
              else
              {
                v2->_46BEF1_apply_spells_aoe();
              }
              v2->spell_level = 0;
              v2->spell_skill = 0;
              v2->spell_id = 0;
              goto LABEL_233;
            }
            v135 = 10;
          }
        }
        v107 = v135;
        goto LABEL_222;
      }
      if ( v7 == 8090 || v7 == 7030 || v7 == 7090 || v7 == 8000 )
        goto LABEL_93;
      if ( v7 == 8010 )
      {
        if ( v151 == 3
          && MonsterStats::BelongsToSupertype(pActors[PID_ID(v145)].pMonsterInfo.uID, MONSTER_SUPERTYPE_UNDEAD) )
          sub_43A97E(v153, v145);
        v93 = pObjectList->uNumObjects;
        ++v2->uType;
        v9 = 0;
        v52 = 0;
        if ( (signed int)v93 > 0 )
        {
          v94 = (char *)&pObjectList->pObjects->uObjectID;
          while ( v2->uType != *(short *)v94 )
          {
            ++v52;
            v94 += 56;
            if ( v52 >= (signed int)v93 )
              goto LABEL_181;
          }
          goto LABEL_202;
        }
        goto LABEL_181;
      }
      v79 = v7 == 8030;
    }
    else
    {
      if ( v7 == 6090 )
        goto LABEL_93;
      if ( v7 <= 4070 )
      {
        if ( v7 != 4070 )
        {
          v48 = v7 - 3090;
          if ( v48 )
          {
            v49 = v48 - 2;
            if ( v49 )
            {
              v50 = v49 - 908;
              if ( !v50 )
                goto LABEL_93;
              v45 = v50 - 30;
              v44 = v45 == 0;
              goto LABEL_91;
            }
            v54 = v6 - 1;
            v55 = pObjectList->uNumObjects;
            v9 = 0;
            v56 = 0;
            v44 = pObjectList->uNumObjects == 0;
            v20 = (pObjectList->uNumObjects & 0x80000000u) != 0;
            v2->uType = v54;
            if ( v20 | v44 )
            {
LABEL_102:
              v58 = 0;
            }
            else
            {
              v57 = (char *)&pObjectList->pObjects->uObjectID;
              while ( v54 != *(short *)v57 )
              {
                ++v56;
                v57 += 56;
                if ( v56 >= (signed int)v55 )
                  goto LABEL_102;
              }
              v58 = v56;
            }
            v2->uObjectDescID = v58;
            if ( !v58 )
              SpriteObject::OnInteraction(v153);
            v14 = v153;
            v2->vVelocity.z = 0;
            v2->vVelocity.y = 0;
            v2->vVelocity.x = 0;
            v2->uSpriteFrameID = 0;
            sub_43A97E(v153, v145);
LABEL_35:
            v15 = v2->uSoundID;
            if ( v15 == (short)v9 )
              v16 = 0;
            else
              v16 = (signed __int16)v15 + 4;
            v133 = v9;
            v131 = v9;
            v130 = v16;
            v92 = v14;
LABEL_267:
            v124 = 8 * v92;
            v129 = v9;
            v128 = -1;
            LOBYTE(v124) = v124 | 2;
            v127 = v9;
            v126 = v124;
LABEL_268:
            v116 = word_4EE088_sound_ids[v2->spell_id];
LABEL_269:
            v125 = v116 + 1;
            goto LABEL_29;
          }
          v59 = v6 + 2;
          v60 = pObjectList->uNumObjects;
          v9 = 0;
          v61 = 0;
          v44 = pObjectList->uNumObjects == 0;
          v20 = (pObjectList->uNumObjects & 0x80000000u) != 0;
          v2->uType = v59;
          if ( v20 | v44 )
          {
LABEL_111:
            v63 = 0;
          }
          else
          {
            v62 = (char *)&pObjectList->pObjects->uObjectID;
            while ( v59 != *(short *)v62 )
            {
              ++v61;
              v62 += 56;
              if ( v61 >= (signed int)v60 )
                goto LABEL_111;
            }
            v63 = v61;
          }
          v2->uObjectDescID = v63;
          if ( !v63 )
            SpriteObject::OnInteraction(v153);
          v64 = v2->uFacing - stru_5C6E00->uIntegerDoublePi;
          v44 = v2->spell_skill == 4;
          v2->vVelocity.z = 0;
          v2->vVelocity.y = 0;
          v2->vVelocity.x = 0;
          v65 = 7;
          if ( v44 )
            v65 = 9;
          if ( v65 > 0 )
          {
            v141 = v65;
            do
            {
              v64 += (signed int)stru_5C6E00->uIntegerHalfPi >> 1;
              v2->Create(v64, 0, 1000, 0);
              --v141;
            }
            while ( v141 );
          }
LABEL_160:
          v14 = v153;
LABEL_34:
          SpriteObject::OnInteraction(v14);
          goto LABEL_35;
        }
        if ( v151 == 6 || v151 == 5 || (v66 = 0, !v151) )
          return 1;
        v67 = v6 + 1;
        v68 = pObjectList->uNumObjects;
        v69 = 0;
        v44 = pObjectList->uNumObjects == 0;
        v20 = (pObjectList->uNumObjects & 0x80000000u) != 0;
        v2->uType = v67;
        if ( v20 | v44 )
        {
LABEL_128:
          v71 = 0;
        }
        else
        {
          v70 = (char *)&pObjectList->pObjects->uObjectID;
          while ( v67 != *(short *)v70 )
          {
            ++v69;
            v70 += 56;
            if ( v69 >= (signed int)v68 )
              goto LABEL_128;
          }
          v71 = v69;
        }
        v2->uObjectDescID = v71;
        if ( !v71 )
          SpriteObject::OnInteraction(v153);
        v134 = 0;
        v72 = v153;
        v132 = 0;
LABEL_132:
        v73 = v2->vPosition.z;
        v74 = v2->vPosition.y;
        v75 = PID(OBJECT_Item,v72);
        v2->vVelocity.z = v66;
        v2->vVelocity.y = v66;
        v76 = v2->vPosition.x;
        v2->vVelocity.x = v66;
        v2->uSpriteFrameID = v66;
        stru_50FE08.Add(v75, 512, v76, v74, v73, v132, v134);
        v77 = v2->uSoundID;
        if ( v77 == (short)v66 )
          v78 = 0;
        else
          v78 = (signed __int16)v77 + 4;
        v133 = v66;
        v131 = v66;
        v130 = v78;
        v129 = v66;
        v128 = -1;
        v127 = v66;
        v126 = v75;
        goto LABEL_268;
      }
      if ( v7 == 4090 )
      {
        v84 = v6 + 2;
        v85 = pObjectList->uNumObjects;
        v9 = 0;
        v86 = 0;
        v44 = pObjectList->uNumObjects == 0;
        v20 = (pObjectList->uNumObjects & 0x80000000u) != 0;
        v2->uType = v84;
        if ( v20 | v44 )
        {
LABEL_155:
          v88 = 0;
        }
        else
        {
          v87 = (char *)&pObjectList->pObjects->uObjectID;
          while ( v84 != *(short *)v87 )
          {
            ++v86;
            v87 += 56;
            if ( v86 >= (signed int)v85 )
              goto LABEL_155;
          }
          v88 = v86;
        }
        v2->uObjectDescID = v88;
        if ( !v88 )
          SpriteObject::OnInteraction(v153);
        v89 = v2->uFacing - stru_5C6E00->uIntegerDoublePi;
        v2->vVelocity.z = 0;
        v2->vVelocity.y = 0;
        v2->vVelocity.x = 0;
        v142 = v89;
        v148 = 7;
        do
        {
          pRnd->SetRange(-128, 128);
          v90 = pRnd->GetInRange();
          pRnd->SetRange(5, 500);
          v91 = pRnd->GetInRange();
          v142 += (signed int)stru_5C6E00->uIntegerHalfPi >> 1;
          v2->Create(v90 + v142, 0, v91, 0);
          --v148;
        }
        while ( v148 );
        goto LABEL_160;
      }
      if ( v7 == 4092 )
      {
        v80 = pObjectList->uNumObjects;
        v66 = 0;
        v81 = 0;
        v44 = pObjectList->uNumObjects == 0;
        v20 = (pObjectList->uNumObjects & 0x80000000u) != 0;
        v2->uType = 4091;
        if ( v20 | v44 )
        {
LABEL_144:
          v83 = 0;
        }
        else
        {
          v82 = (char *)&pObjectList->pObjects->uObjectID;
          while ( *(short *)v82 != 4091 )
          {
            ++v81;
            v82 += 56;
            if ( v81 >= (signed int)v80 )
              goto LABEL_144;
          }
          v83 = v81;
        }
        v2->uObjectDescID = v83;
        if ( !v83 )
          SpriteObject::OnInteraction(v153);
        v134 = 0;
        v72 = v153;
        v132 = v2->field_61;
        goto LABEL_132;
      }
      if ( v7 == 4100 || v7 == 6010 )
        goto LABEL_93;
      v79 = v7 == 6040;
    }
    if ( !v79 )
      return 0;
    goto LABEL_172;
  }
  if ( v7 == 3060 )
    goto LABEL_93;
  if ( v7 <= 555 )
  {
    if ( v7 == 555 )
    {
      sub_43A97E(v153, v145);
      v23 = pObjectList->uNumObjects;
      ++v2->uType;
      v18 = 0;
      v24 = 0;
      if ( (signed int)v23 <= 0 )
      {
LABEL_41:
        v22 = 0;
      }
      else
      {
        v25 = (char *)&pObjectList->pObjects->uObjectID;
        while ( v2->uType != *(short *)v25 )
        {
          ++v24;
          v25 += 56;
          if ( v24 >= (signed int)v23 )
            goto LABEL_41;
        }
        v22 = v24;
      }
LABEL_42:
      v2->uObjectDescID = v22;
      if ( v22 == v18 )
        SpriteObject::OnInteraction(v153);
      v2->vVelocity.z = v18;
      v2->vVelocity.y = v18;
      v2->vVelocity.x = v18;
      v2->uSpriteFrameID = v18;
    }
    else
    {
      switch ( v7 )
      {
        case 500:
        case 505:
        case 510:
        case 515:
        case 520:
        case 525:
        case 530:
        case 535:
        case 540:
          sub_43A97E(v153, v145);
          v8 = pObjectList->uNumObjects;
          ++v2->uType;
          v9 = 0;
          v10 = 0;
          if ( (signed int)v8 <= 0 )
            goto LABEL_23;
          v11 = (char *)&pObjectList->pObjects->uObjectID;
          break;
        case 545:
        case 550:
          if ( v2->stru_24.uItemID != 405 && v2->stru_24.uSpecEnchantmentType != 3 )
          {
            v14 = v153;
            v9 = 0;
            v2->vVelocity.z = 0;
            v2->vVelocity.y = 0;
            v2->vVelocity.x = 0;
            v2->uSpriteFrameID = 0;
            sub_43A97E(v153, v145);
            goto LABEL_34;
          }
          v17 = pObjectList->uNumObjects;
          v18 = 0;
          v19 = 0;
          v44 = pObjectList->uNumObjects == 0;
          v20 = (pObjectList->uNumObjects & 0x80000000u) != 0;
          v2->uType = 600;
          if ( v20 | v44 )
            goto LABEL_41;
          v21 = (char *)&pObjectList->pObjects->uObjectID;
          while ( *(short *)v21 != 600 )
          {
            ++v19;
            v21 += 56;
            if ( v19 >= (signed int)v17 )
              goto LABEL_41;
          }
          v22 = v19;
          goto LABEL_42;
        default:
          return 0;
      }
      while ( v2->uType != *(short *)v11 )
      {
        ++v10;
        v11 += 56;
        if ( v10 >= (signed int)v8 )
        {
LABEL_23:
          v12 = 0;
          goto LABEL_24;
        }
      }
      v12 = v10;
LABEL_24:
      v2->uObjectDescID = v12;
      if ( !v12 )
        SpriteObject::OnInteraction(v153);
      v44 = v2->uType == 555;
      v2->vVelocity.z = 0;
      v2->vVelocity.y = 0;
      v2->vVelocity.x = 0;
      v2->uSpriteFrameID = 0;
      if ( !v44 )
        goto LABEL_27;
    }
    return 0;
  }
  if ( v7 > 1100 )
  {
    v41 = v7 - 2030;
    if ( !v41 )
      goto LABEL_247;
    v42 = v41 - 30;
    if ( v42 )
    {
      v43 = v42 - 40;
      if ( !v43 )
        goto LABEL_59;
      v45 = v43 - 910;
      v44 = v45 == 0;
LABEL_91:
      if ( !v44 && v45 != 20 )
        return 0;
    }
LABEL_93:
    sub_43A97E(v153, v145);
    v51 = pObjectList->uNumObjects;
    ++v2->uType;
    v9 = 0;
    v52 = 0;
    if ( (signed int)v51 > 0 )
    {
      v53 = (char *)&pObjectList->pObjects->uObjectID;
      while ( v2->uType != *(short *)v53 )
      {
        ++v52;
        v53 += 56;
        if ( v52 >= (signed int)v51 )
          goto LABEL_181;
      }
      goto LABEL_202;
    }
LABEL_181:
    v95 = 0;
LABEL_182:
    v2->uObjectDescID = v95;
    if ( v95 == (short)v9 )
      SpriteObject::OnInteraction(v153);
    v96 = v2->uSoundID;
    v2->vVelocity.z = v9;
    v2->vVelocity.y = v9;
    v2->vVelocity.x = v9;
    v2->uSpriteFrameID = v9;
    if ( v96 == (short)v9 )
      v97 = 0;
    else
      v97 = (signed __int16)v96 + 4;
    v133 = v9;
    v131 = v9;
    v130 = v97;
    v92 = v153;
    goto LABEL_267;
  }
  if ( v7 == 1100 )
    goto LABEL_93;
  v26 = v7 - 600;
  if ( !v26 )
  {
    v33 = pObjectList->uNumObjects;
    v34 = 0;
    v44 = pObjectList->uNumObjects == 0;
    v20 = (pObjectList->uNumObjects & 0x80000000u) != 0;
    v2->uType = 601;
    if ( v20 | v44 )
    {
LABEL_69:
      v36 = 0;
    }
    else
    {
      v35 = (char *)&pObjectList->pObjects->uObjectID;
      while ( *(short *)v35 != 601 )
      {
        ++v34;
        v35 += 56;
        if ( v34 >= (signed int)v33 )
          goto LABEL_69;
      }
      v36 = v34;
    }
    v2->uObjectDescID = v36;
    if ( !v36 )
      SpriteObject::OnInteraction(v153);
    v37 = v2->vPosition.z;
    v2->vVelocity.z = 0;
    v38 = 8 * v153;
    v39 = v2->vPosition.y;
    LOBYTE(v38) = PID(OBJECT_Item,v153);
    v2->vVelocity.y = 0;
    v2->vVelocity.x = 0;
    v40 = v2->vPosition.x;
    v2->uSpriteFrameID = 0;
    v147 = v38;
    stru_50FE08.Add(v38, 512, v40, v39, v37, 0, 0);
    if ( HIBYTE(v3->uFlags) & 1 )
      array_5118E8._440E91(v2->vPosition.x, v2->vPosition.y, v2->vPosition.z, 0, v3->uParticleTrailColor);
    v133 = 0;
    v131 = 0;
    v130 = 0;
    v129 = 0;
    v128 = -1;
    v127 = 0;
    v126 = v147;
    goto LABEL_28;
  }
  v27 = v26 - 410;
  if ( !v27 )
    goto LABEL_93;
  v28 = v27 - 40;
  if ( !v28 )
    goto LABEL_191;
  v29 = v28 - 10;
  if ( v29 )
  {
    if ( v29 != 20 )
      return 0;
LABEL_59:
    if ( v151 != 3 )
    {
      v30 = v6 + 1;
      v31 = pObjectList->uNumObjects;
      v32 = 0;
      v2->uType = v30;
      v146 = 0;
      if ( (signed int)v31 > 0 )
      {
        v140 = (char *)&pObjectList->pObjects->uObjectID;
        while ( v30 != *(short *)v140 )
        {
          ++v146;
          v140 += 56;
          if ( v146 >= (signed int)v31 )
            goto LABEL_195;
        }
LABEL_80:
        v46 = v146;
LABEL_196:
        v2->uObjectDescID = v46;
        if ( v46 == (short)v32 )
          SpriteObject::OnInteraction(v153);
        v100 = v2->field_61;
        v101 = v2->vPosition.z;
        v2->uSpriteFrameID = v32;
        v102 = 8 * v153;
        v103 = v2->vPosition.y;
        LOBYTE(v102) = PID(OBJECT_Item,v153);
        v2->vVelocity.x = v32;
        v2->vVelocity.y = v32;
        v104 = v2->vPosition.x;
        v2->vVelocity.z = v32;
        v149 = v102;
        stru_50FE08.Add(v102, 512, v104, v103, v101, v100, v32);
        if ( HIBYTE(v3->uFlags) & 1 )
          array_5118E8._440E91(
            v2->vPosition.x,
            v2->vPosition.y,
            v2->vPosition.z,
            v32,
            v3->uParticleTrailColor);
        v105 = v2->uSoundID;
        if ( v105 == (short)v32 )
          v47 = 0;
        else
          v47 = (signed __int16)v105 + 4;
        v133 = v32;
        v131 = v32;
        v130 = v47;
        v129 = v32;
        v128 = -1;
        v127 = v32;
        v126 = v149;
        goto LABEL_268;
      }
      goto LABEL_195;
    }
    return 1;
  }
LABEL_247:
  if ( v151 == 6 || v151 == 5 || (v9 = 0, !v151) )
    return 1;
  if ( v151 != 2 )
  {
    sub_43A97E(v153, v145);
    v122 = pObjectList->uNumObjects;
    ++v2->uType;
    v52 = 0;
    if ( (signed int)v122 > 0 )
    {
      v123 = (char *)&pObjectList->pObjects->uObjectID;
      while ( v2->uType != *(short *)v123 )
      {
        ++v52;
        v123 += 56;
        if ( v52 >= (signed int)v122 )
          goto LABEL_181;
      }
LABEL_202:
      v95 = v52;
      goto LABEL_182;
    }
    goto LABEL_181;
  }
  v117 = v6 + 1;
  v118 = pObjectList->uNumObjects;
  v119 = 0;
  v44 = pObjectList->uNumObjects == 0;
  v20 = (pObjectList->uNumObjects & 0x80000000u) != 0;
  v2->uType = v117;
  if ( v20 | v44 )
  {
LABEL_255:
    v121 = 0;
  }
  else
  {
    v120 = (char *)&pObjectList->pObjects->uObjectID;
    while ( v117 != *(short *)v120 )
    {
      ++v119;
      v120 += 56;
      if ( v119 >= (signed int)v118 )
        goto LABEL_255;
    }
    v121 = v119;
  }
  v2->uObjectDescID = v121;
  if ( !v121 )
    SpriteObject::OnInteraction(v153);
  v2->vVelocity.z = 0;
  v2->vVelocity.y = 0;
  v2->vVelocity.x = 0;
  v2->uSpriteFrameID = 0;
LABEL_27:
  v133 = v9;
  v131 = v9;
  v130 = v9;
  v13 = 8 * v153;
  v129 = v9;
  v128 = -1;
  LOBYTE(v13) = PID(OBJECT_Item,v153);
  v127 = v9;
  v126 = v13;
LABEL_28:
  v125 = 8;
LABEL_29:
  pAudioPlayer->PlaySound((SoundID)v125, v126, v127, v128, v129, v130, v131, v133);
  return 0;
}