view mm7_3.cpp @ 898:10fa7dad1391

DrawPaperdoll clean
author Ritor1
date Mon, 15 Apr 2013 16:36:56 +0600
parents d3228f46ef68
children 8cd0b155bebe
line wrap: on
line source

#include <assert.h>

#include "MapInfo.h"
#include "Game.h"
#include "GUIWindow.h"
#include "GUIFont.h"
#include "GUIProgressBar.h"
#include "Party.h"
#include "AudioPlayer.h"
#include "Outdoor.h"
#include "IndoorCamera.h"
#include "Overlays.h"
#include "Monsters.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 "stru287.h"
#include "Time.h"
#include "IconFrameTable.h"
#include "TurnEngine.h"
#include "Awards.h"
#include "Autonotes.h"
#include "stru160.h"
#include "stru279.h"
#include "Weather.h"
#include "stru220.h"
#include "Events2D.h"
#include "stru176.h"
#include "stru159.h"
#include "stru298.h"
#include "texts.h"
#include "Log.h"

#include "MM7.h"
#include "mm7_data.h"

//----- (0046E44E) --------------------------------------------------------
int __thiscall _46E44E_collide_against_faces_and_portals(unsigned int b1)
{
  BLVSector *pSector; // edi@1
  signed int v2; // ebx@1
  BLVFace *pFace; // esi@2
  __int16 pNextSector; // si@10
  int pArrayNum; // ecx@12
  unsigned __int8 v6; // sf@12
  unsigned __int8 v7; // of@12
  int result; // eax@14
  //BLVSector *v9; // ebx@15
  int v10; // ecx@15
  int pFloor; // eax@16
  //BLVFace *v12; // ebp@16
  int v13; // eax@24
  int v14; // esi@24
  int v15; // eax@24
  int v16; // edx@25
  int v17; // eax@29
  unsigned int v18; // eax@33
  int v19; // eax@35
  int v20; // edx@35
  int v21; // eax@35
  int v22; // ecx@36
  int v23; // eax@40
  unsigned int v24; // eax@44
  int a3; // [sp+10h] [bp-48h]@28
  int v26; // [sp+14h] [bp-44h]@15
  int i; // [sp+18h] [bp-40h]@1
  int a10; // [sp+1Ch] [bp-3Ch]@1
  int v29; // [sp+20h] [bp-38h]@14
  int v30; // [sp+24h] [bp-34h]@35
  int v31; // [sp+28h] [bp-30h]@24
  int v32; // [sp+2Ch] [bp-2Ch]@15
  int pSectorsArray[10]; // [sp+30h] [bp-28h]@1

  pSector = &pIndoor->pSectors[stru_721530.uSectorID];
  v2 = 0;
  a10 = b1;
  pSectorsArray[0] = stru_721530.uSectorID;
  for ( i = 1; v2 < pSector->uNumPortals; ++v2 )
  {
    pFace = &pIndoor->pFaces[pSector->pPortals[v2]];
    if ( stru_721530.sMaxX <= pFace->pBounding.x2
      && stru_721530.sMinX >= pFace->pBounding.x1
      && stru_721530.sMaxY <= pFace->pBounding.y2
      && stru_721530.sMinY >= pFace->pBounding.y1
      && stru_721530.sMaxZ <= pFace->pBounding.z2
      && stru_721530.sMinZ >= pFace->pBounding.z1
      && abs((pFace->pFacePlane_old.dist
            + stru_721530.normal.x * pFace->pFacePlane_old.vNormal.x
            + stru_721530.normal.y * pFace->pFacePlane_old.vNormal.y
            + stru_721530.normal.z * pFace->pFacePlane_old.vNormal.z) >> 16) <= stru_721530.field_6C + 16 )
    {
      pNextSector = pFace->uSectorID == stru_721530.uSectorID ? pFace->uBackSectorID : pFace->uSectorID;//FrontSectorID
      pArrayNum = i++;
      v7 = i < 10;
      v6 = i - 10 < 0;
      pSectorsArray[pArrayNum] = pNextSector;
      if ( !(v6 ^ v7) )
        break;
    }
  }
  result = 0;
  v29 = 0;
  if ( i > 0 )
  {
    while ( 1 )
    {
      pSector = &pIndoor->pSectors[pSectorsArray[result]];
      v10 = 0;
      v32 = pSector->uNumFloors + pSector->uNumWalls + pSector->uNumCeilings;
      v26 = 0;
      if ( v32 > 0 )
        break;
LABEL_46:
      result = v29++ + 1;
      if ( v29 >= i )
        return result;
    }
    while ( 1 )
    {
      pFloor = pSector->pFloors[v10];
      pFace = &pIndoor->pFaces[pFloor];
      if ( pFace->Portal()
        || stru_721530.sMaxX > pFace->pBounding.x2
        || stru_721530.sMinX < pFace->pBounding.x1
        || stru_721530.sMaxY > pFace->pBounding.y2
        || stru_721530.sMinY < pFace->pBounding.y1
        || stru_721530.sMaxZ > pFace->pBounding.z2
        || stru_721530.sMinZ < pFace->pBounding.z1
        || pFloor == stru_721530.field_84 )
        goto LABEL_45;
      v13 = pFace->pFacePlane_old.vNormal.y;
      v14 = pFace->pFacePlane_old.dist;
      v31 = v13;
      v15 = (stru_721530.normal.x * pFace->pFacePlane_old.vNormal.x + v14 + stru_721530.normal.y * v13
           + stru_721530.normal.z * pFace->pFacePlane_old.vNormal.z) >> 16;
      if ( v15 > 0 )
      {
        v16 = (stru_721530.normal2.y * v31 + pFace->pFacePlane_old.dist + stru_721530.normal2.z * pFace->pFacePlane_old.vNormal.z
             + stru_721530.normal2.x * pFace->pFacePlane_old.vNormal.x) >> 16;
        if ( v15 <= stru_721530.prolly_normal_d || v16 <= stru_721530.prolly_normal_d )
        {
          if ( v16 <= v15 )
          {
            a3 = stru_721530.field_6C;
            if ( sub_47531C(stru_721530.prolly_normal_d, &a3, stru_721530.normal.x, stru_721530.normal.y, stru_721530.normal.z,
                   stru_721530.field_58.x, stru_721530.field_58.y, stru_721530.field_58.z, pFace, a10) )
            {
              v17 = a3;
            }
            else
            {
              a3 = stru_721530.field_6C + stru_721530.prolly_normal_d;
              if ( !sub_475D85(&stru_721530.normal, &stru_721530.field_58, &a3, pFace) )
                goto LABEL_34;
              v17 = a3 - stru_721530.prolly_normal_d;
              a3 -= stru_721530.prolly_normal_d;
            }
            if ( v17 < stru_721530.field_7C )
            {
              stru_721530.field_7C = v17;
              v18 = 8 * pSector->pFloors[v26];
              LOBYTE(v18) = v18 | 6;
              stru_721530.uFaceID = v18;
            }
          }
        }
      }
LABEL_34:
      if ( !(stru_721530.field_0 & 1)
        || (v19 = pFace->pFacePlane_old.vNormal.x,
            v20 = pFace->pFacePlane_old.vNormal.y,
            v30 = v19,
            v21 = (stru_721530.field_34.x * v19 + pFace->pFacePlane_old.dist + stru_721530.field_34.y * v20
                 + stru_721530.field_34.z * pFace->pFacePlane_old.vNormal.z) >> 16,
            v21 <= 0)
        || (v22 = (stru_721530.field_4C * v30 + pFace->pFacePlane_old.dist + stru_721530.field_50 * v20
                 + stru_721530.field_54 * pFace->pFacePlane_old.vNormal.z) >> 16,
            v21 > stru_721530.prolly_normal_d)
        && v22 > stru_721530.prolly_normal_d
        || v22 > v21 )
        goto LABEL_45;
      a3 = stru_721530.field_6C;
      if ( sub_47531C(stru_721530.field_8, &a3, stru_721530.field_34.x, stru_721530.field_34.y, stru_721530.field_34.z,
             stru_721530.field_58.x, stru_721530.field_58.y, stru_721530.field_58.z, pFace, a10) )
      {
        v23 = a3;
        goto LABEL_43;
      }
      a3 = stru_721530.field_6C + stru_721530.field_8;
      if ( sub_475D85(&stru_721530.field_34, &stru_721530.field_58, &a3, pFace) )
      {
        v23 = a3 - stru_721530.prolly_normal_d;
        a3 -= stru_721530.prolly_normal_d;
LABEL_43:
        if ( v23 < stru_721530.field_7C )
        {
          stru_721530.field_7C = v23;
          v24 = 8 * pSector->pFloors[v26];
          LOBYTE(v24) = v24 | 6;
          stru_721530.uFaceID = v24;
        }
      }
LABEL_45:
      v10 = v26++ + 1;
      if ( v26 >= v32 )
        goto LABEL_46;
    }
  }
  return result;
}
// 46E44E: using guessed type int var_28[10];

//----- (0046E889) --------------------------------------------------------
int __fastcall _46E889_collide_against_bmodels(unsigned int ecx0)
{
  int result; // eax@1
  BSPModel *v2; // ecx@3
  int v3; // ebx@9
  ODMFace *v4; // eax@11
  int v5; // edi@17
  int v6; // esi@17
  unsigned int v7; // ecx@17
  int v8; // eax@19
  int v9; // ecx@20
  int v10; // eax@24
  int v11; // ST18_4@25
  int v12; // ST1C_4@25
  int v13; // ST0C_4@25
  unsigned int v14; // eax@28
  int v15; // eax@30
  int v16; // ecx@31
  unsigned int v17; // eax@36
  int v18; // ST18_4@41
  int v19; // ST1C_4@41
  int v20; // ST0C_4@41
  int v21; // eax@42
  unsigned int v22; // eax@43
  //BLVFace f; // [sp+Ch] [bp-7Ch]@1
  int v24; // [sp+6Ch] [bp-1Ch]@9
  int a11; // [sp+70h] [bp-18h]@1
  unsigned int v26; // [sp+74h] [bp-14h]@2
  unsigned int v27; // [sp+78h] [bp-10h]@10
  BSPModel *v28; // [sp+7Ch] [bp-Ch]@3
  int a10; // [sp+80h] [bp-8h]@1
  int a2; // [sp+84h] [bp-4h]@23

  a11 = ecx0;

  BLVFace f; // [sp+Ch] [bp-7Ch]@1
  //BLVFace::BLVFace(&f);

  result = 0;
  a10 = 0;
  if ( (signed int)pOutdoor->uNumBModels > 0 )
  {
    v26 = 0;
    while ( 1 )
    {
      v2 = &pOutdoor->pBModels[v26 / 0xBC];
      v28 = &pOutdoor->pBModels[v26 / 0xBC];
      if ( stru_721530.sMaxX <= pOutdoor->pBModels[v26 / 0xBC].sMaxX )
      {
        if ( stru_721530.sMinX >= v2->sMinX )
        {
          if ( stru_721530.sMaxY <= v2->sMaxY )
          {
            if ( stru_721530.sMinY >= v2->sMinY )
            {
              if ( stru_721530.sMaxZ <= v2->sMaxZ )
              {
                if ( stru_721530.sMinZ >= v2->sMinZ )
                {
                  v3 = 0;
                  v24 = v2->uNumFaces;
                  if ( v24 > 0 )
                    break;
                }
              }
            }
          }
        }
      }
LABEL_39:
      ++a10;
      v26 += 188;
      result = a10;
      if ( a10 >= (signed int)pOutdoor->uNumBModels )
        return result;
    }
    v27 = 0;
    while ( 1 )
    {
      v4 = &v2->pFaces[v27 / 0x134];
      if ( stru_721530.sMaxX > v4->pBoundingBox.x2
        || stru_721530.sMinX < v4->pBoundingBox.x1
        || stru_721530.sMaxY > v4->pBoundingBox.y2
        || stru_721530.sMinY < v4->pBoundingBox.y1
        || stru_721530.sMaxZ > v4->pBoundingBox.z2
        || stru_721530.sMinZ < v4->pBoundingBox.z1 )
        goto LABEL_38;
      f.pFacePlane_old.vNormal.x = v4->pFacePlane.vNormal.x;
      f.pFacePlane_old.vNormal.y = v4->pFacePlane.vNormal.y;
      v5 = v4->pFacePlane.vNormal.z;
      f.pFacePlane_old.vNormal.z = v4->pFacePlane.vNormal.z;
      v6 = v4->pFacePlane.dist;
      f.pFacePlane_old.dist = v4->pFacePlane.dist;
      v7 = v4->uAttributes;
      f.uAttributes = v7;
      f.pBounding.x1 = v4->pBoundingBox.x1;
      f.pBounding.y1 = v4->pBoundingBox.y1;
      f.pBounding.z1 = v4->pBoundingBox.z1;
      f.pBounding.x2 = v4->pBoundingBox.x2;
      f.pBounding.y2 = v4->pBoundingBox.y2;
      f.pBounding.z2 = v4->pBoundingBox.z2;
      f.zCalc1 = v4->zCalc1;
      f.zCalc2 = v4->zCalc2;
      f.zCalc3 = v4->zCalc3;
      f.pXInterceptDisplacements = v4->pXInterceptDisplacements;
      f.pYInterceptDisplacements = v4->pYInterceptDisplacements;
      f.pZInterceptDisplacements = v4->pZInterceptDisplacements;
      f.uPolygonType = (PolygonType)v4->uPolygonType;
      f.uNumVertices = v4->uNumVertices;
      f.uBitmapID = v4->uTextureID;
      f.pVertexIDs = v4->pVertexIDs;
      if ( !(v7 & 0x20000000) )
      {
        if ( !(v7 & 1) )
          break;
      }
LABEL_37:
      v2 = v28;
LABEL_38:
      v27 += 308;
      ++v3;
      if ( v3 >= v24 )
        goto LABEL_39;
    }
    v8 = (v5 * stru_721530.normal.z
        + v6
        + f.pFacePlane_old.vNormal.y * stru_721530.normal.y
        + f.pFacePlane_old.vNormal.x * stru_721530.normal.x) >> 16;
    if ( v8 > 0 )
    {
      v9 = (v5 * stru_721530.normal2.z
          + v6
          + f.pFacePlane_old.vNormal.y * stru_721530.normal2.y
          + f.pFacePlane_old.vNormal.x * stru_721530.normal2.x) >> 16;
      if ( v8 <= stru_721530.prolly_normal_d || v9 <= stru_721530.prolly_normal_d )
      {
        if ( v9 <= v8 )
        {
          a2 = stru_721530.field_6C;
          if ( sub_4754BF(
                 stru_721530.prolly_normal_d,
                 &a2,
                 stru_721530.normal.x,
                 stru_721530.normal.y,
                 stru_721530.normal.z,
                 stru_721530.field_58.x,
                 stru_721530.field_58.y,
                 stru_721530.field_58.z,
                 &f,
                 a10,
                 a11) )
          {
            v10 = a2;
          }
          else
          {
            v11 = stru_721530.field_58.y;
            v12 = stru_721530.field_58.z;
            v13 = stru_721530.normal.y;
            a2 = stru_721530.prolly_normal_d + stru_721530.field_6C;
            if ( !sub_475F30(
                    &a2,
                    &f,
                    stru_721530.normal.x,
                    v13,
                    stru_721530.normal.z,
                    stru_721530.field_58.x,
                    v11,
                    v12,
                    a10) )
              goto LABEL_29;
            v10 = a2 - stru_721530.prolly_normal_d;
            a2 -= stru_721530.prolly_normal_d;
          }
          if ( v10 < stru_721530.field_7C )
          {
            stru_721530.field_7C = v10;
            v14 = 8 * (v3 | (a10 << 6));
            LOBYTE(v14) = v14 | 6;
            stru_721530.uFaceID = v14;
          }
        }
      }
    }
LABEL_29:
    if ( stru_721530.field_0 & 1 )
    {
      v15 = (f.pFacePlane_old.vNormal.z * stru_721530.field_34.z
           + f.pFacePlane_old.dist
           + f.pFacePlane_old.vNormal.y * stru_721530.field_34.y
           + f.pFacePlane_old.vNormal.x * stru_721530.field_34.x) >> 16;
      if ( v15 > 0 )
      {
        v16 = (f.pFacePlane_old.vNormal.z * stru_721530.field_54
             + f.pFacePlane_old.dist
             + f.pFacePlane_old.vNormal.y * stru_721530.field_50
             + f.pFacePlane_old.vNormal.x * stru_721530.field_4C) >> 16;
        if ( v15 <= stru_721530.prolly_normal_d || v16 <= stru_721530.prolly_normal_d )
        {
          if ( v16 <= v15 )
          {
            a2 = stru_721530.field_6C;
            if ( sub_4754BF(
                   stru_721530.field_8,
                   &a2,
                   stru_721530.field_34.x,
                   stru_721530.field_34.y,
                   stru_721530.field_34.z,
                   stru_721530.field_58.x,
                   stru_721530.field_58.y,
                   stru_721530.field_58.z,
                   &f,
                   a10,
                   a11) )
            {
              if ( a2 < stru_721530.field_7C )
              {
                stru_721530.field_7C = a2;
                v17 = 8 * (v3 | (a10 << 6));
                LOBYTE(v17) = v17 | 6;
                stru_721530.uFaceID = v17;
              }
            }
            else
            {
              v18 = stru_721530.field_58.y;
              v19 = stru_721530.field_58.z;
              v20 = stru_721530.field_34.y;
              a2 = stru_721530.field_6C + stru_721530.field_8;
              if ( sub_475F30(
                     &a2,
                     &f,
                     stru_721530.field_34.x,
                     v20,
                     stru_721530.field_34.z,
                     stru_721530.field_58.x,
                     v18,
                     v19,
                     a10) )
              {
                v2 = v28;
                v21 = a2 - stru_721530.prolly_normal_d;
                a2 -= stru_721530.prolly_normal_d;
                if ( a2 < stru_721530.field_7C )
                {
                  stru_721530.field_7C = v21;
                  v22 = 8 * (v3 | (a10 << 6));
                  LOBYTE(v22) = v22 | 6;
                  stru_721530.uFaceID = v22;
                }
                goto LABEL_38;
              }
            }
          }
        }
      }
    }
    goto LABEL_37;
  }
  return result;
}

//----- (0046ED1B) --------------------------------------------------------
int collide_against_floor(int x, int y, int z, unsigned int *pSectorID, unsigned int *pFaceID)
{
  uint uFaceID = -1;
  int floor_level = BLV_GetFloorLevel(x, y, z, *pSectorID, &uFaceID);

  if (floor_level != -30000 && floor_level <= z + 50)
  {
    *pFaceID = uFaceID;
    return floor_level;
  }

  uint uSectorID = pIndoor->GetSector(x, y, z);
  *pSectorID = uSectorID;

  floor_level = BLV_GetFloorLevel(x, y, z, uSectorID, &uFaceID);
  if (uSectorID && floor_level != -30000)
    *pFaceID = uFaceID;
  else return -30000;
  return floor_level;
}

//----- (0046ED8A) --------------------------------------------------------
void __fastcall _46ED8A_collide_against_sprite_objects(unsigned int _this)
{
  int v1; // ebx@2
  ObjectDesc *v2; // edx@4
  int v3; // esi@5
  int v4; // ecx@5
  int v5; // eax@7
  int v6; // edi@9
  int v7; // edx@9
  int v8; // edi@11
  int v9; // ebx@11
  int v10; // ecx@12
  int v11; // esi@13
  signed int v12; // [sp+0h] [bp-14h]@1
  int v13; // [sp+4h] [bp-10h]@9
  char *v14; // [sp+8h] [bp-Ch]@2
  unsigned int v15; // [sp+10h] [bp-4h]@1

  v15 = 0;
  v12 = _this;
  if ( (signed int)uNumSpriteObjects > 0 )
  {
    v1 = (int)&pSpriteObjects[0].uObjectDescID;
    v14 = (char *)&pSpriteObjects[0].uObjectDescID;
    do
    {
      if ( *(short *)v1 )
      {
        v2 = &pObjectList->pObjects[*(short *)v1];
        if ( !(v2->uFlags & 2) )
        {
          v3 = v2->uRadius;
          v4 = *(int *)(v1 + 2);
          if ( stru_721530.sMaxX <= v4 + v3 )
          {
            if ( stru_721530.sMinX >= v4 - v3 )
            {
              v5 = *(int *)(v1 + 6);
              if ( stru_721530.sMaxY <= v5 + v3 )
              {
                if ( stru_721530.sMinY >= v5 - v3 )
                {
                  v6 = v2->uHeight;
                  v7 = *(int *)(v1 + 10);
                  v13 = v6;
                  if ( stru_721530.sMaxZ <= v7 + v6 )
                  {
                    if ( stru_721530.sMinZ >= v7 )
                    {
                      v8 = v4 - stru_721530.normal.x;
                      v9 = v5 - stru_721530.normal.y;
                      if ( abs(((v4 - stru_721530.normal.x) * stru_721530.field_58.y
                              - (v5 - stru_721530.normal.y) * stru_721530.field_58.x) >> 16) <= v3
                                                                                              + stru_721530.prolly_normal_d )
                      {
                        v10 = (v8 * stru_721530.field_58.x + v9 * stru_721530.field_58.y) >> 16;
                        if ( v10 > 0 )
                        {
                          v11 = stru_721530.normal.z
                              + ((unsigned __int64)(stru_721530.field_58.z * (signed __int64)v10) >> 16);
                          if ( v11 >= *(int *)(v14 + 10) - stru_721530.prolly_normal_d )
                          {
                            if ( v11 <= v13 + stru_721530.prolly_normal_d + *(int *)(v14 + 10) )
                            {
                              if ( v10 < stru_721530.field_7C )
                                sub_46DEF2(v12, v15);
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
      ++v15;
      v1 = (int)(v14 + 112);
      v14 += 112;
    }
    while ( (signed int)v15 < (signed int)uNumSpriteObjects );
  }
}

//----- (0046EF01) --------------------------------------------------------
int __thiscall _46EF01_collision_chech_player(int a1)
{
  int v1; // edx@1
  int result; // eax@1
  int v3; // ebx@7
  int v4; // esi@7
  int v5; // edi@8
  int v6; // ecx@9
  int v7; // edi@12
  int v8; // [sp+Ch] [bp-10h]@1
  unsigned int v9; // [sp+10h] [bp-Ch]@1
  int v10; // [sp+14h] [bp-8h]@7
  int v11; // [sp+18h] [bp-4h]@7

  v8 = a1;
  v1 = 2 * pParty->field_14;
  result = pParty->vPosition.x;
  v9 = pParty->uPartyHeight;
  if ( stru_721530.sMaxX <= pParty->vPosition.x + 2 * pParty->field_14 )
  {
    if ( stru_721530.sMinX >= pParty->vPosition.x - v1 )
    {
      if ( stru_721530.sMaxY <= pParty->vPosition.y + v1 )
      {
        if ( stru_721530.sMinY >= pParty->vPosition.y - v1 )
        {
          if ( stru_721530.sMaxZ <= (signed int)(pParty->vPosition.z + pParty->uPartyHeight) )
          {
            if ( stru_721530.sMinZ >= pParty->vPosition.z )
            {
              v3 = stru_721530.prolly_normal_d + v1;
              v11 = pParty->vPosition.x - stru_721530.normal.x;
              v4 = ((pParty->vPosition.x - stru_721530.normal.x) * stru_721530.field_58.y
                  - (pParty->vPosition.y - stru_721530.normal.y) * stru_721530.field_58.x) >> 16;
              v10 = pParty->vPosition.y - stru_721530.normal.y;
              result = abs(((pParty->vPosition.x - stru_721530.normal.x) * stru_721530.field_58.y
                          - (pParty->vPosition.y - stru_721530.normal.y) * stru_721530.field_58.x) >> 16);
              if ( result <= v3 )
              {
                result = v10 * stru_721530.field_58.y;
                v5 = (v10 * stru_721530.field_58.y + v11 * stru_721530.field_58.x) >> 16;
                if ( v5 > 0 )
                {
                  v6 = ((unsigned __int64)(stru_721530.field_58.z * (signed __int64)v5) >> 16) + stru_721530.normal.z;
                  result = pParty->vPosition.z;
                  if ( v6 >= pParty->vPosition.z )
                  {
                    result = v9 + pParty->vPosition.z;
                    if ( v6 <= (signed int)(v9 + pParty->vPosition.z) || v8 )
                    {
                      result = integer_sqrt(v3 * v3 - v4 * v4);
                      v7 = v5 - result;
                      if ( v7 < 0 )
                        v7 = 0;
                      if ( v7 < stru_721530.field_7C )
                      {
                        stru_721530.field_7C = v7;
                        stru_721530.uFaceID = 4;
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  return result;
}

//----- (0046F04E) --------------------------------------------------------
signed int __cdecl _46F04E_collide_against_portals()
{
  BLVSector *v0; // ecx@1
  unsigned int v1; // eax@1
  int v2; // eax@2
  BLVFace *v3; // eax@3
  int v4; // ecx@9
  int v5; // edx@9
  signed int result; // eax@21
  BLVFace *v7; // eax@22
  signed int v8; // [sp+0h] [bp-14h]@1
  BLVSector *v9; // [sp+4h] [bp-10h]@1
  unsigned int v10; // [sp+8h] [bp-Ch]@1
  int a3; // [sp+Ch] [bp-8h]@13
  int v12; // [sp+10h] [bp-4h]@15

  v8 = 0;
  v0 = &pIndoor->pSectors[stru_721530.uSectorID];
  v1 = 0xFFFFFFu;
  v10 = 0xFFFFFFu;
  v9 = v0;
  if ( v0->uNumPortals > 0 )
  {
    do
    {
      v2 = v0->pPortals[v8];
      if ( v2 != stru_721530.field_80 )
      {
        v3 = &pIndoor->pFaces[v2];
        if ( stru_721530.sMaxX <= v3->pBounding.x2 )
        {
          if ( stru_721530.sMinX >= v3->pBounding.x1
            && stru_721530.sMaxY <= v3->pBounding.y2
            && stru_721530.sMinY >= v3->pBounding.y1
            && stru_721530.sMaxZ <= v3->pBounding.z2
            && stru_721530.sMinZ >= v3->pBounding.z1 )
          {
            v4 = (stru_721530.normal.x * v3->pFacePlane_old.vNormal.x
                + v3->pFacePlane_old.dist
                + stru_721530.normal.y * v3->pFacePlane_old.vNormal.y
                + stru_721530.normal.z * v3->pFacePlane_old.vNormal.z) >> 16;
            v5 = (stru_721530.normal2.z * v3->pFacePlane_old.vNormal.z
                + v3->pFacePlane_old.dist
                + stru_721530.normal2.x * v3->pFacePlane_old.vNormal.x
                + stru_721530.normal2.y * v3->pFacePlane_old.vNormal.y) >> 16;
            if ( (v4 < stru_721530.prolly_normal_d || v5 < stru_721530.prolly_normal_d)
              && (v4 > -stru_721530.prolly_normal_d || v5 > -stru_721530.prolly_normal_d)
              && (a3 = stru_721530.field_6C, sub_475D85(&stru_721530.normal, &stru_721530.field_58, &a3, v3))
              && a3 < (signed int)v10 )
            {
              v0 = v9;
              v10 = a3;
              v12 = v9->pPortals[v8];
            }
            else
            {
              v0 = v9;
            }
          }
        }
      }
      ++v8;
    }
    while ( v8 < v0->uNumPortals );
    v1 = v10;
  }
  if ( stru_721530.field_7C >= (signed int)v1 && (signed int)v1 <= stru_721530.field_6C )
  {
    stru_721530.field_80 = v12;
    v7 = &pIndoor->pFaces[v12];
    if ( v7->uSectorID == stru_721530.uSectorID )
      stru_721530.uSectorID = v7->uBackSectorID;
    else
      stru_721530.uSectorID = v7->uSectorID;
    stru_721530.field_7C = 268435455;
    result = 0;
  }
  else
  {
    result = 1;
  }
  return result;
}

//----- (0047050A) --------------------------------------------------------
int stru141::_47050A(int a2)
{
  stru141 *v2; // esi@1
  signed int v3; // eax@1
  int v4; // ecx@1
  int v5; // edx@1
  int v6; // edx@1
  int v7; // eax@1
  int v8; // eax@3
  signed int result; // eax@4
  int v10; // eax@5
  int v11; // eax@5
  int v12; // ebx@5
  int v13; // edx@5
  int v14; // edi@5
  int v15; // ecx@5
  int v16; // eax@5
  int v17; // eax@5
  int v18; // eax@7
  int v19; // edx@9
  int v20; // edi@9
  int v21; // eax@9
  int v22; // eax@11
  int v23; // edx@13
  int v24; // eax@13
  int v25; // eax@14
  int v26; // eax@16
  int v27; // eax@17
  int v28; // [sp+14h] [bp+8h]@5

  v2 = this;
  v3 = integer_sqrt(this->field_24 * this->field_24 + this->field_20 * this->field_20 + this->field_1C * this->field_1C);
  v4 = v3 | 1;
  v5 = v2->field_1C;
  v2->field_64 = v3 | 1;
  v2->field_58.x = 65536 / (v3 | 1) * v5;
  v2->field_58.y = 65536 / (v3 | 1) * v2->field_20;
  v6 = 65536 / (v3 | 1) * v2->field_24;
  v2->field_68 = 65536 / (v3 | 1);
  v7 = a2;
  v2->field_58.z = v6;
  if ( !a2 )
    v7 = pEventTimer->dt_in_some_format;
  v8 = ((unsigned __int64)(v7 * (signed __int64)v4) >> 16) - v2->field_70;
  v2->field_6C = v8;
  if ( v8 > 0 )
  {
    v10 = ((unsigned __int64)(v8 * (signed __int64)v2->field_58.x) >> 16) + v2->normal.x;
    v2->field_4C = v10;
    v2->normal2.x = v10;
    v11 = ((unsigned __int64)(v2->field_6C * (signed __int64)v2->field_58.y) >> 16) + v2->normal.y;
    v2->field_50 = v11;
    v2->normal2.y = v11;
    v2->normal2.z = ((unsigned __int64)(v2->field_6C * (signed __int64)v2->field_58.z) >> 16) + v2->normal.z;
    v12 = v2->field_34.z;
    v13 = v2->normal.x;
    v14 = v2->normal2.x;
    v15 = v2->prolly_normal_d;
    v16 = v12 + ((unsigned __int64)(v2->field_6C * (signed __int64)v2->field_58.z) >> 16);
    v28 = v16;
    v2->field_54 = v16;
    v17 = v13;
    if ( v13 >= v14 )
      v17 = v14;
    v2->sMaxX = v17 - v15;
    v18 = v15 + v13;
    if ( v13 <= v14 )
      v18 = v15 + v14;
    v19 = v2->normal.y;
    v20 = v2->normal2.y;
    v2->sMinX = v18;
    v21 = v19;
    if ( v19 >= v20 )
      v21 = v20;
    v2->sMaxY = v21 - v15;
    v22 = v15 + v19;
    if ( v19 <= v20 )
      v22 = v20 + v15;
    v23 = v2->normal2.z;
    v2->sMinY = v22;
    v24 = v2->normal.z;
    if ( v24 >= v23 )
      v25 = v23 - v15;
    else
      v25 = v24 - v15;
    v2->sMaxZ = v25;
    v26 = v2->field_8;
    if ( v12 <= v28 )
      v27 = v28 + v26;
    else
      v27 = v12 + v26;
    v2->uFaceID = 0;
    v2->field_80 = -1;
    v2->field_88 = -1;
    v2->sMinZ = v27;
    v2->field_7C = 0xFFFFFFu;
    result = 0;
  }
  else
  {
    result = 1;
  }
  return result;
}

//----- (004706C6) --------------------------------------------------------
void __cdecl UpdateActors_ODM()
{
  Actor *v0; // esi@2
  AIState uAIState; // ax@2
  //unsigned int v2; // ecx@6
  int v3; // ebx@6
  //int v4; // eax@8
  int v5; // eax@10
  int v6; // ecx@10
  //signed int v7; // ebx@10
  signed int v8; // ebx@17
  //unsigned __int8 v9; // zf@17
  unsigned __int8 v10; // sf@17
  unsigned __int16 v11; // ax@21
  int v12; // eax@29
  unsigned __int64 v13; // qax@29
  int v14; // eax@30
  unsigned __int64 v15; // qax@30
  int v16; // eax@33
  //int v17; // edi@34
  int v18; // edx@42
  int v19; // ecx@42
  __int16 v20; // ax@42
  int v21; // ebx@42
  int v22; // edi@42
  int v23; // ecx@42
  __int16 v24; // ax@42
  int v25; // eax@45
  signed int v26; // ecx@50
  int v27; // eax@52
  int v28; // eax@54
  signed int v29; // ebx@57
  signed int v30; // eax@57
  int v31; // edi@57
  signed int i; // ebx@57
  unsigned int v33; // ecx@58
  //int v34; // ebx@64
  int v35; // edi@64
  int v36; // eax@64
  //unsigned __int16 v37; // cx@66
  signed int v38; // edx@71
  unsigned int v39; // edi@71
  BSPModel *v40; // eax@75
  ODMFace *v41; // edi@75
  int v42; // ebx@76
  int v43; // ecx@77
  int v44; // edx@77
  __int16 v45; // dx@82
  int v46; // ecx@82
  signed int v47; // ebx@85
  int v48; // edi@85
  int v49; // edi@85
  int v50; // eax@85
  unsigned __int64 v51; // qax@85
  //unsigned __int8 v52; // zf@87
  //unsigned __int8 v53; // sf@87
 // unsigned __int8 v54; // of@104
  int v55; // eax@107
  unsigned int v56; // edi@107
  int v57; // ST10_4@107
  unsigned int v58; // edi@107
  unsigned int v59; // ebx@107
  signed int v60; // eax@107
  int v61; // eax@124
  Vec3_int_ v62; // [sp+Ch] [bp-44h]@42
  int v63; // [sp+18h] [bp-38h]@64
  int v64; // [sp+1Ch] [bp-34h]@64
  int v65; // [sp+20h] [bp-30h]@2
  int v66; // [sp+24h] [bp-2Ch]@2
  bool v67; // [sp+28h] [bp-28h]@10
  //unsigned int v68; // [sp+2Ch] [bp-24h]@10
  unsigned int v69; // [sp+30h] [bp-20h]@6
  unsigned int v70; // [sp+34h] [bp-1Ch]@10
  int v71; // [sp+38h] [bp-18h]@62
  int uIsAboveFloor; // [sp+3Ch] [bp-14h]@10
  int v72b;
  int v73; // [sp+40h] [bp-10h]@17
  int uIsFlying; // [sp+44h] [bp-Ch]@8
  unsigned int v75; // [sp+48h] [bp-8h]@1
  int uIsOnWater; // [sp+4Ch] [bp-4h]@10

  for(v75=0;(signed int)v75 < (signed int)uNumActors;++v75)
  {
    v0 = &pActors[v75];
    v66 = v0->vPosition.x;
    v65 = v0->vPosition.y;
    uAIState = v0->uAIState;
    if ( uAIState == Removed || uAIState == Disabled || uAIState == Summoned || !v0->uMovementSpeed )
	{
		continue;
	}
    v3 = 0;
    v69 = 0;
    if ( MonsterStats::BelongsToSupertype(v0->pMonsterInfo.uID, MONSTER_SUPERTYPE_WATER_ELEMENTAL) )
      v3 = 1;
    v0->uSectorID = 0;
    uIsFlying = v0->pMonsterInfo.uFlying;
    if ( !v0->CanAct() )
      uIsFlying = 0;
    v70 = IsTerrainSlopeTooHigh(v0->vPosition.x, v0->vPosition.y);
    v5 = ODM_GetFloorLevel(
           v0->vPosition.x,
           v0->vPosition.y,
           v0->vPosition.z,
           v0->uActorHeight,
           &uIsOnWater,
           (int *)&v69,
           v3);
    v6 = v0->vPosition.z;
    uIsAboveFloor = 0;
    v67 = v69 == 0;
    if ( v6 > v5 + 1 )
      uIsAboveFloor = 1;
    if ( uAIState == Dead && uIsOnWater && !uIsAboveFloor )
    {
      v0->uAIState = Removed;
	  continue;
    }
    if ( v0->uCurrentActionAnimation == ANIM_Walking )
    {
      v8 = v0->uMovementSpeed;
      v73 = v0->uMovementSpeed;
      if ( (signed __int64)v0->pActorBuffs[7].uExpireTime > 0 )
      {
        v8 = (signed __int64)((double)v73 * 0.5);
        v73 = (signed __int64)((double)v73 * 0.5);
      }
      if ( uAIState == Fleeing || uAIState == Pursuing )
      {
        v8 *= 2;
        v73 = v8;
      }
      if ( pParty->bTurnBasedModeOn == 1 && pTurnEngine->field_4 == 1 )
        v8 = (signed __int64)((double)v73 * flt_6BE3AC_debug_recmod1_x_1_6);
      if ( v8 > 1000 )
        v8 = 1000;
      v12 = stru_5C6E00->Cos(v0->uYawAngle);
      v13 = v12 * (signed __int64)v8;
      v73 = v13 >> 16;
      v0->vVelocity.x = WORD1(v13);
      v69 = stru_5C6E00->Sin(v0->uYawAngle);
      v73 = (unsigned __int64)((signed int)v69 * (signed __int64)v8) >> 16;
      v0->vVelocity.y = v69 * v8 >> 16;
      if ( uIsFlying )
      {
        v14 = stru_5C6E00->Sin(v0->uPitchAngle);
        v69 = v14;
        v15 = v14 * (signed __int64)v8;
        v73 = v15 >> 16;
        v0->vVelocity.z = WORD1(v15);
      }
      //v7 = v68;
    }
    else
    {
      v73 = v0->vVelocity.x;
      v69 = 55000;
      v73 = (unsigned __int64)(55000i64 * v73) >> 16;
      v0->vVelocity.x = v73;
      v73 = v0->vVelocity.y;
      v73 = (unsigned __int64)((signed int)v69 * (signed __int64)v73) >> 16;
      v0->vVelocity.y = v73;
      if ( uIsFlying )
      {
        v69 = 55000;
        v73 = v0->vVelocity.z;
        v73 = (unsigned __int64)(55000i64 * v73) >> 16;
        v0->vVelocity.z = v73;
      }
    }
    if ( v0->vPosition.z < v5 )
    {
      v16 = uIsFlying;
      v0->vPosition.z = v5;
      v0->vVelocity.z = v16 != 0 ? 0x14 : 0;
    }
    //v17 = 0;
    if ( !uIsAboveFloor || uIsFlying )
    {
      if ( v70 && !uIsAboveFloor && v67 )
      {
        v18 = v0->vPosition.y;
        v19 = v0->vPosition.x;
        v0->vPosition.z = v5;
        ODM_GetTerrainNormalAt(v19, v18, &v62);
        v20 = GetGravityStrength();
        v21 = v62.y;
        v22 = v62.z;
        v23 = v62.y * v0->vVelocity.y;
        v0->vVelocity.z += -8 * LOWORD(pEventTimer->uTimeElapsed) * v20;
        v73 = abs(v62.x * v0->vVelocity.x + v22 * v0->vVelocity.z + v23) >> 16;
        v72b = v21;
        v0->vVelocity.x += (unsigned int)(v73 * v62.x) >> 16;
        v72b = (unsigned __int64)(v73 * (signed __int64)v72b) >> 16;
        v24 = v72b;
        v72b = v22;
        v0->vVelocity.y += v24;
        v72b = (unsigned __int64)(v73 * (signed __int64)v72b) >> 16;
        v0->vVelocity.z += v72b;
        //v17 = 0;
      }
    }
    else
    {
      v0->vVelocity.z -= LOWORD(pEventTimer->uTimeElapsed) * GetGravityStrength();
    }
    if ( pParty->armageddon_timer != 0 && v0->CanAct() )
    {
      v0->vVelocity.x += rand() % 100 - 50;
      v0->vVelocity.y += rand() % 100 - 50;
      v0->vVelocity.z += rand() % 100 - 20;
      v25 = rand();
      v0->uAIState = Stunned;
      v0->uYawAngle += v25 % 32 - 16;
      v0->UpdateAnimation();
    }
    if ( v0->vVelocity.x * v0->vVelocity.x + v0->vVelocity.y * v0->vVelocity.y < 400 && v70 == 0 )
    {
      v0->vVelocity.y = 0;
      v0->vVelocity.x = 0;
    }
    stru_721530.field_0 = 1;
    if ( !uIsFlying )
      v26 = 40;
    else
      v26 = v0->uActorRadius;
    v27 = v0->uActorHeight;
    stru_721530.field_84 = -1;
    stru_721530.field_8 = v26;
    stru_721530.prolly_normal_d = v26;
    stru_721530.field_C = v27;
    stru_721530.field_70 = 0;
    v69 = 0;
    while ( 1 )
    {
      stru_721530.field_34.x = v0->vPosition.x;
      stru_721530.normal.x = stru_721530.field_34.x;
      stru_721530.field_34.y = v0->vPosition.y;
      stru_721530.normal.y = stru_721530.field_34.y;
      v28 = v0->vPosition.z;
      stru_721530.normal.z = v28 + v26 + 1;
      stru_721530.field_34.z = v28 - v26 + stru_721530.field_C - 1;
      if ( stru_721530.field_34.z < stru_721530.normal.z )
        stru_721530.field_34.z = v28 + v26 + 1;
      stru_721530.field_1C = v0->vVelocity.x;
      stru_721530.uSectorID = 0;
      stru_721530.field_20 = v0->vVelocity.y;
      stru_721530.field_24 = v0->vVelocity.z;
      if ( stru_721530._47050A(0) )
        break;
      _46E889_collide_against_bmodels(1u);
      v29 = WorldPosToGridCellZ(v0->vPosition.y);
      v30 = WorldPosToGridCellX(v0->vPosition.x);
      _46E26D_collide_against_sprites(v30, v29);
      _46EF01_collision_chech_player(0);
      _46ED8A_collide_against_sprite_objects(PID(OBJECT_Actor,v75));
      v31 = 0;
      for ( i = 0; v31 < ai_arrays_size; ++v31 )
      {
        v33 = ai_near_actors_ids[v31];
        if ( v33 != v75 && _46DF1A_collide_against_actor(v33, 40) )
          ++i;
      }
      v71 = i > 1;
      if ( stru_721530.field_7C < stru_721530.field_6C )
        v70 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16;
      //v34 = 0;
      v35 = stru_721530.normal2.z - stru_721530.prolly_normal_d - 1;
      v36 = ODM_GetFloorLevel(
              stru_721530.normal2.x,
              stru_721530.normal2.y,
              stru_721530.normal2.z - stru_721530.prolly_normal_d - 1,
              v0->uActorHeight,
              (int *)&v63,
              &v64,
              0);
      if ( uIsOnWater )
      {
        if ( v35 < v36 + 60 )
        {
          if ( uAIState == Dead || uAIState == Dying || uAIState == Removed || uAIState == Disabled )
          {
            if ( v64 )
              v61 = v36 + 30;
            else
              v61 = v5 + 60;
            sub_42F960_create_object(v0->vPosition.x, v0->vPosition.y, v61);
            v0->uAIState = Removed;
            return;
          }
        }
      }
      if ( stru_721530.field_7C >= stru_721530.field_6C )
      {
        v0->vPosition.x = LOWORD(stru_721530.normal2.x);
        v0->vPosition.y = LOWORD(stru_721530.normal2.y);
        v0->vPosition.z = LOWORD(stru_721530.normal2.z) - LOWORD(stru_721530.prolly_normal_d) - 1;
        break;
      }
      v72b = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.x) >> 16;
      v0->vPosition.x += (unsigned int)(stru_721530.field_7C * stru_721530.field_58.x) >> 16;
      v72b = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.y) >> 16;
      v0->vPosition.y += (unsigned int)(stru_721530.field_7C * stru_721530.field_58.y) >> 16;
      v72b = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16;
      v38 = stru_721530.uFaceID;
      v0->vPosition.z += (unsigned int)(stru_721530.field_7C * stru_721530.field_58.z) >> 16;
      stru_721530.field_70 += stru_721530.field_7C;
	  v39 = PID_ID(v38);
      switch ( PID_TYPE(v38) )
      {
        case OBJECT_Actor:
          if ( pTurnEngine->field_4 != 2 && pTurnEngine->field_4 != 3 || pParty->bTurnBasedModeOn != 1 )
          {
			//if(pParty->bTurnBasedModeOn == 1)
				//v34 = 0;
            if ( v0->pMonsterInfo.uHostilityType )
            {
              if ( v71 == 0 )
			  {
				  Actor::Flee(v75, v38, 0, (AIDirection *)0);
			  }
			  else
			  {
				  Actor::AI_StandOrBored(v75, 4, 0, (AIDirection *)0);
			  }
            }
            else if ( v71 != 0 )
			{
              Actor::AI_StandOrBored(v75, 4, 0, (AIDirection *)0);
			}
			else if ( pActors[v39].pMonsterInfo.uHostilityType == MonsterInfo::Hostility_Friendly )
            {
              Actor::Flee(v75, v38, 0, (AIDirection *)0);
            }
			else
			{
				Actor::FaceObject(v75, v38, 0, (AIDirection *)0);
			}
          }
          break;
        case OBJECT_Player:
          if ( !v0->GetActorsRelation(0) )
          {
            v38 = stru_721530.uFaceID;
            Actor::FaceObject(v75, v38, 0, (AIDirection *)0);
            break;
          }
          //v52 = HIDWORD(pParty->pPartyBuffs[11].uExpireTime) == 0;
          //v53 = SHIDWORD(pParty->pPartyBuffs[11].uExpireTime) < 0;
          v0->vVelocity.y = 0;
          v0->vVelocity.x = 0;
          //if ( !v53 && (!(v53 | v52) || LODWORD(pParty->pPartyBuffs[11].uExpireTime) > 0) )
		  if ( (signed __int64)pParty->pPartyBuffs[11].uExpireTime < 0)
            pParty->pPartyBuffs[11].Reset();
          viewparams->bRedrawGameUI = 1;
          break;
        case OBJECT_Decoration:
          v47 = integer_sqrt(v0->vVelocity.x * v0->vVelocity.x + v0->vVelocity.y * v0->vVelocity.y);
          v48 = stru_5C6E00->Atan2(
                  v0->vPosition.x - pLevelDecorations[v39].vPosition.x,
                  v0->vPosition.y - pLevelDecorations[v39].vPosition.y);
          v71 = stru_5C6E00->Cos(v48);
          v70 = (unsigned __int64)(v71 * (signed __int64)v47) >> 16;
          v49 = v48;
          v0->vVelocity.x = (unsigned int)(v71 * v47) >> 16;
          v50 = stru_5C6E00->Sin(v48);
          v71 = v50;
          v51 = v50 * (signed __int64)v47;
          v70 = v51 >> 16;
          v0->vVelocity.y = WORD1(v51);
          break;
        case OBJECT_BModel:
          v40 = &pOutdoor->pBModels[v38 >> 9];
          v41 = &v40->pFaces[v39 & 0x3F];
          if ( !(BYTE3(v41->uAttributes) & 0x20) )
          {
            v42 = v41->uPolygonType;
            if ( v42 == 3 )
            {
              v43 = v0->vVelocity.y;
              v44 = v0->vVelocity.x;
              v0->vVelocity.z = 0;
              v0->vPosition.z = LOWORD(v40->pVertices.pVertices[v41->pVertexIDs[0]].z) + 1;
              if ( v44 * v44 + v43 * v43 < 400 )
              {
                v0->vVelocity.y = 0;
                v0->vVelocity.x = 0;
              }
            }
            else
            {
              v72b = abs(v41->pFacePlane.vNormal.y * v0->vVelocity.y + v41->pFacePlane.vNormal.z * v0->vVelocity.z
                                                                    + v41->pFacePlane.vNormal.x * v0->vVelocity.x) >> 16;
              if ( stru_721530.field_64 >> 3 > v72b )
                v72b = stru_721530.field_64 >> 3;
              v73 = v41->pFacePlane.vNormal.x;
              v73 = (unsigned __int64)(v72b * (signed __int64)v73) >> 16;
              v71 = v41->pFacePlane.vNormal.y;
              v71 = (unsigned __int64)(v72b * (signed __int64)v71) >> 16;
              v70 = v41->pFacePlane.vNormal.z;
              v70 = (unsigned __int64)(v72b * (signed __int64)(signed int)v70) >> 16;
              v0->vVelocity.x += v73;
              v0->vVelocity.y += v71;
              v0->vVelocity.z += v70;
              if ( v42 != 4 )
              {
                v45 = v0->vPosition.z;
                v46 = stru_721530.prolly_normal_d
                    - ((v41->pFacePlane.dist
                      + v41->pFacePlane.vNormal.x * v0->vPosition.x
                      + v41->pFacePlane.vNormal.y * v0->vPosition.y
                      + v41->pFacePlane.vNormal.z * v0->vPosition.z) >> 16);
                if ( v46 > 0 )
                {
                  v0->vPosition.x += (unsigned int)(v46 * v41->pFacePlane.vNormal.x) >> 16;
                  v0->vPosition.y += (unsigned int)(v46 * v41->pFacePlane.vNormal.y) >> 16;
                  v0->vPosition.z = v45 + ((unsigned int)(v46 * v41->pFacePlane.vNormal.z) >> 16);
                }
                v0->uYawAngle = stru_5C6E00->Atan2(v0->vVelocity.x, v0->vVelocity.y);
              }
            }
          }
          break;
      }
      v70 = v0->vVelocity.x;
      v71 = 58500;
      v70 = (unsigned __int64)(58500i64 * (signed int)v70) >> 16;
      v0->vVelocity.x = v70;
      v70 = v0->vVelocity.y;
      v70 = (unsigned __int64)(v71 * (signed __int64)(signed int)v70) >> 16;
      v71 = 58500;
      v0->vVelocity.y = v70;
      v70 = v0->vVelocity.z;
      v70 = (unsigned __int64)(v71 * (signed __int64)(signed int)v70) >> 16;
      ++v69;
      //v54 = v69 < 100;
      //v10 = (v69 - 100) < 0;
      v0->vVelocity.z = v70;
      if ( v69 >= 100 )
        break;
      v26 = stru_721530.prolly_normal_d;
    }
    v58 = ((unsigned int)~pOutdoor->ActuallyGetSomeOtherTileInfo(WorldPosToGridCellX(v66), WorldPosToGridCellZ(v65) - 1) >> 1) & 1;
    v59 = ((unsigned int)~pOutdoor->ActuallyGetSomeOtherTileInfo(WorldPosToGridCellX(v0->vPosition.x), WorldPosToGridCellZ(v0->vPosition.y) - 1) >> 1) & 1;
    if ( WorldPosToGridCellX(v66) == WorldPosToGridCellX(v0->vPosition.x) 
		&& WorldPosToGridCellZ(v65) == WorldPosToGridCellZ(v0->vPosition.y)
		&& v58 
		|| v67 != 0 )
    {
      if ( MonsterStats::BelongsToSupertype(v0->pMonsterInfo.uID, MONSTER_SUPERTYPE_WATER_ELEMENTAL) )
      {
        v58 = v58 == 0;
        v59 = v59 == 0;
      }
      if ( !uIsFlying && v58 && !v59 )
      {
        v0->vPosition.x = v66;
        v0->vPosition.y = v65;
        if ( v0->CanAct() )
        {
          v0->uYawAngle -= 32;
          v0->uCurrentActionTime = 0;
          v0->uCurrentActionLength = 128;
          v0->uAIState = Fleeing;
        }
      }
    }
  }
}

//----- (0047253E) --------------------------------------------------------
void UpdateObjects()
{
  unsigned int v0; // ebx@0
  //unsigned int v1; // edi@1
  char *v2; // esi@2
  //__int16 v3; // dx@5
  ObjectDesc *v4; // eax@5
  int v5; // ecx@6
  __int16 v6; // cx@7
  signed int v7; // eax@9
  __int16 v8; // cx@14
  __int16 v9; // dx@14
  unsigned int v10; // ecx@16
  signed int v11; // eax@17
  int v12; // edi@27
  int v13; // eax@27
  int v14; // ebx@27
  unsigned int v15; // ecx@27
  unsigned int v16; // edx@30
  unsigned int v17; // edx@32
  int v18; // [sp+4h] [bp-10h]@27
  int v19; // [sp+8h] [bp-Ch]@27
  //signed int v20; // [sp+10h] [bp-4h]@1

  //v1 = 0;
  //v20 = 0;
  for (uint i = 0; i < uNumSpriteObjects; ++i)
  {
    auto item = pSpriteObjects + i;
    v2 = (char *)&item->uSpriteFrameID;
    //do
    //{
      //LOWORD(v0) = item->uAttributes;
    if (item->uAttributes & 0x40)
      item->uAttributes &= 0xFFBF;
    else
    {
              //v3 = item->uObjectDescID;
      v4 = &pObjectList->pObjects[item->uObjectDescID];
      if (item->AttachedToActor())
      {
          v5 = PID_ID(item->spell_target_pid);
          *(int *)(v2 - 26) = pActors[v5].vPosition.x;
          *(int *)(v2 - 22) = pActors[v5].vPosition.y;
          *(int *)(v2 - 18) = pActors[v5].vPosition.z + pActors[v5].uActorHeight;
          if ( !item->uObjectDescID || (v6 = LOWORD(pEventTimer->uTimeElapsed) + *(short *)v2, *(short *)v2 = v6, !(v4->uFlags & 4)) )
            goto LABEL_36;
          if ( v6 >= 0 )
          {
            v7 = v4->uLifetime;
            if (item->uAttributes & 2)
              v7 = *((short *)v2 + 1);
            if ( v6 < v7 )
              goto LABEL_36;
          }
          goto LABEL_34;
      }

        if ( item->uObjectDescID )
        {
          v8 = LOWORD(pEventTimer->uTimeElapsed) + item->uSpriteFrameID;
          item->uSpriteFrameID = v8;
          v9 = v4->uFlags;
          if ( !(v9 & 4) )
            goto LABEL_22;
          if ( v8 < 0 )
          {
            v10 = i;
LABEL_35:
            SpriteObject::OnInteraction(v10);
            goto LABEL_36;
          }
          v11 = v4->uLifetime;
          if (item->uAttributes & 2)
            v11 = *((short *)v2 + 1);
          if ( v8 < v11 )
          {
LABEL_22:
            if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
              SpriteObject::UpdateObject_fn0_BLV(i);
            else
              SpriteObject::UpdateObject_fn0_ODM(i);
            if ( pParty->bTurnBasedModeOn != 1 || !(*(v2 - 4) & 4) )
              goto LABEL_36;
            v12 = abs(pParty->vPosition.x - *(int *)(v2 - 26));
            v18 = abs(pParty->vPosition.y - *(int *)(v2 - 22));
            v19 = abs(pParty->vPosition.z - *(int *)(v2 - 18));
            v13 = v12;
            v14 = v18;
            v15 = v19;
            if ( v12 < v18 )
            {
              v13 = v18;
              v14 = v12;
            }
            if ( v13 < v19 )
            {
              v16 = v13;
              v13 = v19;
              v15 = v16;
            }
            if ( v14 < (signed int)v15 )
            {
              v17 = v15;
              v15 = v14;
              v14 = v17;
            }
            v0 = (unsigned int)(11 * v14) >> 5;
            if ( (signed int)(v0 + (v15 >> 2) + v13) <= 5120 )
              goto LABEL_36;
LABEL_34:
            v10 = i;
            goto LABEL_35;
          }
          v10 = i;
          if ( !(v9 & 0x40) )
            goto LABEL_35;
          _46BFFA_check_object_intercept(i, PID(OBJECT_Item,i));
        }
    }
LABEL_36:
    ;
      //v2 += 112;
      //v1 = v20++ + 1;
    //}
    //while ( v20 < (signed int)uNumSpriteObjects );
  }
}

//----- (0047272C) --------------------------------------------------------
int collide_against_floor_approximate(int x, int y, int z, unsigned int *pSectorID, unsigned int *pFaceID)
{
  signed int v5; // ebx@1
  int result; // eax@1
  int v7; // [sp+10h] [bp-8h]@1
  signed int v8; // [sp+14h] [bp-4h]@1

  v5 = x - 2;
  v7 = x;
  v8 = y;
  *pSectorID = pIndoor->GetSector(x - 2, y, z + 40);
  result = collide_against_floor(v5, v8, z + 40, pSectorID, pFaceID);
  if ( result == -30000 || !*pSectorID )
  {
    *pSectorID = pIndoor->GetSector(v7 + 2, v8, z + 40);
    result = collide_against_floor(v7 + 2, v8, z + 40, pSectorID, pFaceID);
    if ( result == -30000 || !*pSectorID )
    {
      *pSectorID = pIndoor->GetSector(v7, v8 - 2, z + 40);
      result = collide_against_floor(v7, v8 - 2, z + 40, pSectorID, pFaceID);
      if ( result == -30000 || !*pSectorID )
      {
        *pSectorID = pIndoor->GetSector(v7, v8 + 2, z + 40);
        result = collide_against_floor(v7, v8 + 2, z + 40, pSectorID, pFaceID);
        if ( result == -30000 || !*pSectorID )
        {
          *pSectorID = pIndoor->GetSector(v7, v8, z + 140);
          result = collide_against_floor(v7, v8, z + 140, pSectorID, pFaceID);
        }
      }
    }
  }
  return result;
}

//----- (00472866) --------------------------------------------------------
void BLV_ProcessPartyActions()
{
  int v1; // ebx@1
  int v2; // edi@1
  //int v6; // eax@18
  //signed __int64 v8; // qax@27
  //int v9; // eax@27
  double v10; // st7@27
  unsigned int v12; // eax@49
  double v13; // st7@50
  //int v14; // eax@51
  //signed __int64 v15; // qax@53
  //double v16; // st7@54
  int v17; // eax@62
  double v18; // st7@62
  int v19; // ST40_4@62
  int v20; // eax@65
  double v21; // st7@65
  int v22; // ST40_4@65
  int v23; // eax@66
  double v24; // st7@66
  int v25; // ST40_4@66
  int v26; // eax@67
  double v27; // st7@67
  int v28; // ST40_4@67
  unsigned int v35; // eax@74
  int v36; // ecx@88
  int new_party_z; // esi@96
  int v38; // eax@96
  int v39; // ecx@106
  int v40; // eax@106
  Player **v41; // esi@113
  int v42; // eax@120
  signed int v43; // ecx@123
  BLVFace *v44; // esi@126
  PolygonType v45; // al@126
  int v46; // ecx@133
  char v47; // zf@133
  int v48; // eax@133
  int v49; // ST40_4@136
  int v50; // ST40_4@140
  int v51; // eax@140
  int v52; // eax@140
  signed int v53; // edi@146
  int v54; // ebx@146
  int v55; // ST30_4@146
  AudioPlayer *v56; // ecx@162
  SoundID v57; // [sp-20h] [bp-80h]@163
  signed int v58; // [sp-1Ch] [bp-7Ch]@161
  unsigned int v59; // [sp-18h] [bp-78h]@161
  signed int v60; // [sp-14h] [bp-74h]@161
  signed int v61; // [sp-10h] [bp-70h]@161
  int v62; // [sp-Ch] [bp-6Ch]@161
  int v63; // [sp-8h] [bp-68h]@75
  unsigned int v64; // [sp-8h] [bp-68h]@161
  int v65; // [sp-4h] [bp-64h]@75
  int v66; // [sp-4h] [bp-64h]@161
  //int v68; // [sp+10h] [bp-50h]@45
  int v69; // [sp+10h] [bp-50h]@140
  unsigned int uFaceEvent; // [sp+14h] [bp-4Ch]@1
  //signed int v71; // [sp+18h] [bp-48h]@1
  signed int v72; // [sp+1Ch] [bp-44h]@1
  signed int v73; // [sp+20h] [bp-40h]@100
  int v74; // [sp+20h] [bp-40h]@140
  bool bFeatherFall; // [sp+24h] [bp-3Ch]@15
  unsigned int uSectorID; // [sp+28h] [bp-38h]@1
  int v78; // [sp+2Ch] [bp-34h]@1
  unsigned int uFaceID; // [sp+30h] [bp-30h]@1
  int v80; // [sp+34h] [bp-2Ch]@1
  int v81; // [sp+38h] [bp-28h]@47
  int v82; // [sp+3Ch] [bp-24h]@47
  int _view_angle; // [sp+40h] [bp-20h]@47
  int bJumping; // [sp+44h] [bp-1Ch]@1
  int new_party_y; // [sp+48h] [bp-18h]@1
  int new_party_x; // [sp+4Ch] [bp-14h]@1
  int party_z; // [sp+50h] [bp-10h]@1
  //int v89; // [sp+58h] [bp-8h]@1
  int angle; // [sp+5Ch] [bp-4h]@47

  uFaceEvent = 0;
  //v89 = pParty->uFallSpeed;
  v1 = 0;
  v2 = 0;
  new_party_x = pParty->vPosition.x;
  new_party_y = pParty->vPosition.y;
  party_z = pParty->vPosition.z;
  uSectorID = pIndoor->GetSector(pParty->vPosition.x, pParty->vPosition.y, pParty->vPosition.z);
  v72 = 0;
  v78 = 0;
  bJumping = 0;

  uFaceID = -1;
  auto floor_level = collide_against_floor(new_party_x, new_party_y, party_z + 40, &uSectorID, &uFaceID);

  if ( pParty->bFlying )
  {
    pParty->bFlying = false;
    if (pParty->FlyActive())
      pOtherOverlayList->pOverlays[pParty->pPartyBuffs[PARTY_BUFF_FLY].uOverlayID - 1].field_E |= 1;
  }

  if ( floor_level == -30000  || uFaceID == -1)
  {
    floor_level = collide_against_floor_approximate(new_party_x, new_party_y, party_z + 40, &uSectorID, &uFaceID);
    if ( floor_level == -30000 || uFaceID == -1)
    {
      __debugbreak(); // level built with errors 
      pParty->vPosition.x = blv_prev_party_x;
      pParty->vPosition.y = blv_prev_party_z;
      pParty->vPosition.z = blv_prev_party_y;
      pParty->uFallStartY = blv_prev_party_y;
      return;
    }
  }

  for (uint i = 0; i < pIndoor->uNumFaces; ++i)
    pIndoor->pFaces[i].uAttributes &= ~FACE_OUTLINED;
  pIndoor->pFaces[uFaceID].uAttributes |= FACE_OUTLINED;

  blv_prev_party_x = pParty->vPosition.x;
  blv_prev_party_z = pParty->vPosition.y;
  blv_prev_party_y = pParty->vPosition.z;
  if (!pParty->bTurnBasedModeOn)
  {
    auto v67 = GetTickCount() / 500;
    if (dword_720CDC != v67 )
    {
      dword_4F8580[3 * dword_4F8580[0] + 1] = pParty->vPosition.x;
      dword_4F8580[3 * dword_4F8580[0] + 2] = pParty->vPosition.y;
      dword_4F8580[3 * dword_4F8580[0]++ + 3] = pParty->vPosition.z;
      if ( dword_4F8580[0] > 60 )
        dword_4F8580[0] = 1;
    }
    dword_720CDC = v67;
  }

  uint fall_start;
  if (!pParty->FeatherFallActive())
  {
    bFeatherFall = false;
    if (!pParty->pPlayers[0].WearsItem(ITEM_ARTIFACT_LADYS_ESCORT, 16) &&  // grants feather fall
        !pParty->pPlayers[1].WearsItem(ITEM_ARTIFACT_LADYS_ESCORT, 16) &&
        !pParty->pPlayers[2].WearsItem(ITEM_ARTIFACT_LADYS_ESCORT, 16) &&
        !pParty->pPlayers[3].WearsItem(ITEM_ARTIFACT_LADYS_ESCORT, 16))
    {
      fall_start = pParty->uFallStartY;
    }
  }
  else
  {
    fall_start = floor_level;
    bFeatherFall = true;
    pParty->uFallStartY = floor_level;
  }


  if (fall_start - party_z > 512 && !bFeatherFall && party_z <= floor_level + 1)
  {
    assert(~pParty->uFlags & PARTY_FLAGS_1_LANDING); // why land in indoor?
    if (pParty->uFlags & PARTY_FLAGS_1_LANDING)
      pParty->uFlags &= ~PARTY_FLAGS_1_LANDING;
    else for (uint i = 0; i < 4; ++i)
    {                                      // receive falling damage
      auto player = pParty->pPlayers + i;
      if (!player->HasEnchantedItemEquipped(72) && !player->WearsItem(ITEM_ARTIFACT_HERMES_SANDALS, 8))
      {
        player->ReceiveDamage((pParty->uFallStartY - party_z) * (0.1f * player->GetMaxHealth()) / 256, 4);
        v10 = (double)(20 - player->_48EA1B_get_static_effect(player->GetActualEndurance())) * flt_6BE3A4_debug_recmod1 * 2.133333333333333;
        player->SetRecoveryTime((signed __int64)v10);
      }
    }
  }

  if ( party_z > floor_level + 1 )
    bJumping = 1;

  bool jumping_up = false;

  if ( party_z - floor_level <= 32 )
  {
    pParty->uFallStartY = party_z;
    jumping_up = true;
  }

  if (bWalkSound && pParty->walk_sound_timer)
  {
    if (pParty->walk_sound_timer > pEventTimer->uTimeElapsed)
      pParty->walk_sound_timer -= pEventTimer->uTimeElapsed;
    else pParty->walk_sound_timer = 0;
  }


  if (party_z <= floor_level + 1)
  {
    party_z = floor_level + 1;
    pParty->uFallStartY = floor_level + 1;

    if (!bJumping && pParty->floor_face_pid != uFaceID)
    {
      auto pFace = &pIndoor->pFaces[uFaceID];
      if (pFace->uAttributes & FACE_PRESSURE_PLATE)
        uFaceEvent = pIndoor->pFaceExtras[pFace->uFaceExtraID].uEventID;
    }
  }
  if (!bJumping)
    pParty->floor_face_pid = uFaceID;

  bool on_water = false;
  if ( pIndoor->pFaces[uFaceID].Fluid())
    on_water = true;

  v81 = pParty->uWalkSpeed;
  angle = pParty->sRotationY;
  _view_angle = pParty->sRotationX;
  v82 = (unsigned __int64)(pEventTimer->dt_in_some_format * (signed __int64)((signed int)(pParty->y_rotation_speed * stru_5C6E00->uIntegerPi)
                                          / 180)) >> 16;
//LABEL_87:
  while ( pPartyActionQueue->uNumActions )
  {
    switch ( pPartyActionQueue->Next() )
    {
      case PARTY_TurnLeft:
        if (uTurnSpeed)
          angle = stru_5C6E00->uDoublePiMask & (angle + uTurnSpeed);
        else
          angle = stru_5C6E00->uDoublePiMask & (angle + (int)(v82 * fTurnSpeedMultiplier));
        break;
      case PARTY_TurnRight:
        if (uTurnSpeed)
          angle = stru_5C6E00->uDoublePiMask & (angle - uTurnSpeed);
        else
          angle = stru_5C6E00->uDoublePiMask & (angle - (int)(v82 * fTurnSpeedMultiplier));
        break;

      case PARTY_FastTurnLeft:
        if (uTurnSpeed)
          angle = stru_5C6E00->uDoublePiMask & (angle + uTurnSpeed);
        else
          angle = stru_5C6E00->uDoublePiMask & (angle + (int)(2.0f * fTurnSpeedMultiplier * (double)v82));
        break;

      case PARTY_FastTurnRight:
        if (uTurnSpeed)
          angle = stru_5C6E00->uDoublePiMask & (angle - uTurnSpeed);
        else
          angle = stru_5C6E00->uDoublePiMask & (angle - (int)(2.0f * fTurnSpeedMultiplier * (double)v82));
        break;

      case PARTY_StrafeLeft:
        v2 -= (unsigned __int64)(stru_5C6E00->Sin(angle) * (signed __int64)((signed int)(signed __int64)((double)v81 * fWalkSpeedMultiplier) >> 1)) >> 16;
        v1 += (unsigned __int64)(stru_5C6E00->Cos(angle) * (signed __int64)((signed int)(signed __int64)((double)v81 * fWalkSpeedMultiplier) >> 1)) >> 16;
        v78 = 1;
        break;
      case PARTY_StrafeRight:
        v2 += (unsigned __int64)(stru_5C6E00->Sin(angle) * (signed __int64)((signed int)(signed __int64)((double)v81 * fWalkSpeedMultiplier) >> 1)) >> 16;
        v1 -= (unsigned __int64)(stru_5C6E00->Cos(angle) * (signed __int64)((signed int)(signed __int64)((double)v81 * fWalkSpeedMultiplier) >> 1)) >> 16;
        v78 = 1;
        break;
      case PARTY_WalkForward:
        v2 += (unsigned __int64)(stru_5C6E00->Cos(angle) * (signed __int64)(signed int)(signed __int64)(5 * (double)v81 * fWalkSpeedMultiplier)) >> 16;
        v1 += (unsigned __int64)(stru_5C6E00->Sin(angle) * (signed __int64)(signed int)(signed __int64)(5 * (double)v81 * fWalkSpeedMultiplier)) >> 16;
        v78 = 1;
        break;
      case PARTY_WalkBackward:
        v2 -= (unsigned __int64)(stru_5C6E00->Cos(angle) * (signed __int64)(signed int)(signed __int64)((double)v81 * fBackwardWalkSpeedMultiplier)) >> 16;
        v1 -= (unsigned __int64)(stru_5C6E00->Sin(angle) * (signed __int64)(signed int)(signed __int64)((double)v81 * fBackwardWalkSpeedMultiplier)) >> 16;
        v78 = 1;
        break;
      case PARTY_RunForward:
        v2 += (unsigned __int64)(stru_5C6E00->Cos(angle) * (signed __int64)(signed int)(2 * (unsigned __int64)(signed __int64)((double)v81 * fWalkSpeedMultiplier))) >> 16;
        v1 += (unsigned __int64)(stru_5C6E00->Sin(angle) * (signed __int64)(signed int)(2 * (unsigned __int64)(signed __int64)((double)v81 * fWalkSpeedMultiplier))) >> 16;
        v72 = 1;
        break;
      case PARTY_RunBackward:
        //v32 = stru_5C6E00->SinCos(angle);
        //v33 = (double)v81;
        //v88 = (double)v81;
        v2 -= (unsigned __int64)(stru_5C6E00->Cos(angle) * (signed __int64)(signed int)(signed __int64)((double)v81 * fBackwardWalkSpeedMultiplier)) >> 16;
        //v34 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
        v1 -= (unsigned __int64)(stru_5C6E00->Sin(angle) * (signed __int64)(signed int)(signed __int64)((double)v81 * fBackwardWalkSpeedMultiplier)) >> 16;
        v72 = 1;
        break;
      case PARTY_LookUp:
        _view_angle += (signed __int64)(flt_6BE150_look_up_down_dangle * 25.0);
        if ( _view_angle > 128 )
          _view_angle = 128;
        v35 = uActiveCharacter;
        if ( uActiveCharacter )
          pPlayers[v35]->PlaySound((PlayerSpeech)SPEECH_63, 0);
        break;
      case PARTY_LookDown:
        _view_angle += (signed __int64)(flt_6BE150_look_up_down_dangle * -25.0);
        if ( _view_angle < -128 )
          _view_angle = -128;
        v35 = uActiveCharacter;
        if ( uActiveCharacter )
          pPlayers[v35]->PlaySound((PlayerSpeech)SPEECH_64, 0);
        break;
      case PARTY_CenterView:
        _view_angle = 0;
        break;
      case PARTY_Jump:
        if ( (!bJumping || party_z <= floor_level + 6 && pParty->uFallSpeed <= 0) && pParty->field_24 )
        {
          bJumping = 1;
          pParty->uFallSpeed = (signed __int64)((double)(pParty->field_24 << 6) * 1.5 + (double)pParty->uFallSpeed);
        }
        break;
      default:
        break;
    }
  }
  v36 = 0;
  pParty->sRotationY = angle;
  pParty->sRotationX = _view_angle;
  if ( bJumping )
  {
    pParty->uFallSpeed += -2 * pEventTimer->uTimeElapsed * GetGravityStrength();
  }
  else
  {
    if ( pIndoor->pFaces[uFaceID].pFacePlane_old.vNormal.z < 32768 )
    {
      pParty->uFallSpeed -= pEventTimer->uTimeElapsed * GetGravityStrength();
      goto LABEL_92;
    }
    if (pParty->uFlags & PARTY_FLAGS_1_LANDING)
      goto LABEL_92;
    pParty->uFallSpeed = 0;
  }
  if ( bJumping != v36 && pParty->uFallSpeed <= v36 )
  {
    if ( pParty->uFallSpeed < -500 && !pParty->bFlying )
    {
      v41 = &pPlayers[1];
      do
      {
        if ( !(*v41)->HasEnchantedItemEquipped(72) && !(*v41)->WearsItem(ITEM_ARTIFACT_HERMES_SANDALS, 8) )
          (*v41)->PlayEmotion(CHARACTER_EXPRESSION_SCARED, 0);
        ++v41;
      }
      while ( (signed int)v41 <= (signed int)&pPlayers[4] );
    }
    goto LABEL_93;
  }
LABEL_92:
  pParty->uFallStartY = party_z;
LABEL_93:
  if ( v2 * v2 + v1 * v1 < 400 )
  {
    v1 = 0;
    v2 = 0;
  }
  stru_721530.field_84 = -1;
  stru_721530.field_70 = 0;
  stru_721530.prolly_normal_d = pParty->field_14;
  stru_721530.field_8 = pParty->field_14 >> 1;
  auto v83 = 0;
  stru_721530.field_0 = 1;
  stru_721530.field_C = pParty->uPartyHeight - 32;
  while ( 1 )
  {
    new_party_z = party_z;
    stru_721530.field_34.x = new_party_x;
    stru_721530.normal.x = new_party_x;
    stru_721530.field_1C = v2;
    stru_721530.field_34.y = new_party_y;
    stru_721530.normal.y = new_party_y;
    stru_721530.field_20 = v1;
    stru_721530.normal.z = stru_721530.prolly_normal_d + party_z + 1;
    stru_721530.field_34.z = stru_721530.field_C + party_z + 1;
    stru_721530.field_24 = pParty->uFallSpeed;
    stru_721530.uSectorID = uSectorID;
    v38 = 0;
    if ( pParty->bTurnBasedModeOn == 1 && pTurnEngine->field_4 == 3 )
      v38 = 13312;
    if ( stru_721530._47050A(v38) )
      break;
    v73 = 0;
    do
    {
      _46E44E_collide_against_faces_and_portals(1u);
      _46E0B2_collide_against_decorations();
      for ( v80 = 0; v80 < (signed int)uNumActors; ++v80 )
        _46DF1A_collide_against_actor(v80, 0);
      if ( _46F04E_collide_against_portals() )
        break;
      ++v73;
    }
    while ( v73 < 100 );
    if ( stru_721530.field_7C >= stru_721530.field_6C )
    {
      v39 = stru_721530.normal2.x;
      uSectorID = stru_721530.normal2.y;
      v40 = stru_721530.normal2.z - stru_721530.prolly_normal_d - 1;
    }
    else
    {
      v39 = ((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.x) >> 16) + new_party_x;
      uSectorID = new_party_y + ((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.y) >> 16);
      v40 = new_party_z + ((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16);
    }
    v42 = collide_against_floor(v39, uSectorID, v40 + 40, &stru_721530.uSectorID, &uFaceID);
    if ( v42 == -30000 || v42 - new_party_z > 128 )
      return;
    if ( stru_721530.field_7C >= stru_721530.field_6C )
    {
      new_party_x = stru_721530.normal2.x;
      new_party_y = stru_721530.normal2.y;
      new_party_z = stru_721530.normal2.z - stru_721530.prolly_normal_d - 1;
      break;
    }
    new_party_x += (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.x) >> 16;
    new_party_y += (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.y) >> 16;
    v43 = stru_721530.uFaceID;
    uSectorID = stru_721530.uSectorID;
    stru_721530.field_70 += stru_721530.field_7C;
    auto v87 = ((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16) + new_party_z;
    if ( PID_TYPE(stru_721530.uFaceID) == OBJECT_Actor)
    {
      if ( SHIDWORD(pParty->pPartyBuffs[11].uExpireTime) >= 0
        && (SHIDWORD(pParty->pPartyBuffs[11].uExpireTime) > 0 || LODWORD(pParty->pPartyBuffs[11].uExpireTime)) )
        pParty->pPartyBuffs[11].Reset();
      viewparams->bRedrawGameUI = 1;
      goto LABEL_152;
    }
    if ( PID_TYPE(stru_721530.uFaceID) == OBJECT_Decoration)
    {
      v53 = integer_sqrt(v2 * v2 + v1 * v1);
      v80 = v53;
      v54 = stru_5C6E00->Atan2(new_party_x - pLevelDecorations[stru_721530.uFaceID >> 3].vPosition.x,
              new_party_y - pLevelDecorations[stru_721530.uFaceID >> 3].vPosition.y);
      v2 = (unsigned __int64)(stru_5C6E00->Cos(v54) * (signed __int64)v53) >> 16;
      v55 = stru_5C6E00->Sin(v54);
      v1 = (unsigned __int64)(v55 * (signed __int64)v80) >> 16;
    }
    else
    {
      if ( PID_TYPE(stru_721530.uFaceID) == OBJECT_BModel)
      {
        v44 = &pIndoor->pFaces[(signed int)stru_721530.uFaceID >> 3];
        v45 = v44->uPolygonType;
        if ( v45 == 3 )
        {
          if ( pParty->uFallSpeed < 0 )
            pParty->uFallSpeed = 0;
          v87 = pIndoor->pVertices[*v44->pVertexIDs].z + 1;
          if ( pParty->uFallStartY - v87 < 512 )
            pParty->uFallStartY = v87;
          if ( v2 * v2 + v1 * v1 < 400 )
          {
            v1 = 0;
            v2 = 0;
          }
          if ( pParty->floor_face_pid != PID_ID(v43) && BYTE3(v44->uAttributes) & 4 )
            uFaceEvent = pIndoor->pFaceExtras[v44->uFaceExtraID].uEventID;
          goto LABEL_152;
        }
        v46 = pParty->uFallSpeed * v44->pFacePlane_old.vNormal.z;
        v47 = v45 == 4;
        v48 = v44->pFacePlane_old.vNormal.x;
        if ( !v47 )
        {
          v80 = abs(v1 * v44->pFacePlane_old.vNormal.y + v46 + v2 * v48) >> 16;
          if ( stru_721530.field_64 >> 3 > v80 )
            v80 = stru_721530.field_64 >> 3;
          v50 = (unsigned __int64)(v80 * (signed __int64)v44->pFacePlane_old.vNormal.x) >> 16;
          v81 = v44->pFacePlane_old.vNormal.y;
          v81 = (unsigned __int64)(v80 * (signed __int64)v81) >> 16;
          v82 = v44->pFacePlane_old.vNormal.z;
          v82 = (unsigned __int64)(v80 * (signed __int64)v82) >> 16;
          v2 += v50;
          pParty->uFallSpeed += v82;
          v74 = v44->pFacePlane_old.vNormal.z;
          v51 = v44->pFacePlane_old.vNormal.y;
          v69 = v44->pFacePlane_old.vNormal.x;
          v80 = v51;
          v1 += v81;
          v52 = stru_721530.prolly_normal_d - ((v44->pFacePlane_old.dist + v87 * v74 + new_party_y * v51 + new_party_x * v69) >> 16);
          if ( v52 > 0 )
          {
            new_party_x += v52 * v69 >> 16;
            new_party_y += v52 * v80 >> 16;
            v87 += v52 * v74 >> 16;
          }
          v43 = stru_721530.uFaceID;
          if ( pParty->floor_face_pid != PID_ID(v43) && BYTE3(v44->uAttributes) & 4 )
            uFaceEvent = pIndoor->pFaceExtras[v44->uFaceExtraID].uEventID;
          goto LABEL_152;
        }
        v80 = abs(v1 * v44->pFacePlane_old.vNormal.y + v46 + v2 * v48) >> 16;
        if ( stru_721530.field_64 >> 3 > v80 )
          v80 = stru_721530.field_64 >> 3;
        v49 = (unsigned __int64)(v80 * (signed __int64)v44->pFacePlane_old.vNormal.x) >> 16;
        v81 = v44->pFacePlane_old.vNormal.y;
        v81 = (unsigned __int64)(v80 * (signed __int64)v81) >> 16;
        v82 = v44->pFacePlane_old.vNormal.z;
        v82 = (unsigned __int64)(v80 * (signed __int64)v82) >> 16;
        v2 += v49;
        v1 += v81;
        pParty->uFallSpeed += v82;
        if ( v2 * v2 + v1 * v1 >= 400 )
        {
          v43 = stru_721530.uFaceID;
          if ( pParty->floor_face_pid != PID_ID(v43) && BYTE3(v44->uAttributes) & 4 )
            uFaceEvent = pIndoor->pFaceExtras[v44->uFaceExtraID].uEventID;
          goto LABEL_152;
        }
        v2 = 0;
        v1 = 0;
        pParty->uFallSpeed = 0;
      }
    }
LABEL_152:
    v2 = (unsigned __int64)(58500i64 * v2) >> 16;
    v1 = (unsigned __int64)(58500i64 * v1) >> 16;
    ++v83;
    pParty->uFallSpeed = (unsigned __int64)(58500i64 * pParty->uFallSpeed) >> 16;
    if ( v83 >= 100 )
    {
      new_party_z = v87;
      break;
    }
  }
  if ( bWalkSound && !pParty->walk_sound_timer)
  {
    if ( integer_sqrt((pParty->vPosition.x - new_party_x) * (pParty->vPosition.x - new_party_x) + (pParty->vPosition.y - new_party_y)
         * (pParty->vPosition.y - new_party_y) + (pParty->vPosition.z - new_party_z)
         * (pParty->vPosition.z - new_party_z)) <= 16 )
      goto LABEL_188;
    if ( v72 && (!bJumping || jumping_up) )
    {
      v66 = 0;
      v64 = 0;
      v62 = 0;
      v61 = 0;
      v60 = -1;
      v59 = 1;
      v58 = 804;
      if ( !on_water )
      {
        v56 = pAudioPlayer;
        if ( BYTE2(pIndoor->pFaces[uFaceID].uAttributes) & 0x20 )
          v57 = (SoundID)50;
        else
          v57 = (SoundID)64;
        goto LABEL_175;
      }
      v57 = (SoundID)63;
      v56 = pAudioPlayer;
      goto LABEL_175;
    }
    if ( v78 && (!bJumping || jumping_up) )
    {
      v66 = 0;
      v64 = 0;
      v62 = 0;
      v61 = 0;
      v60 = -1;
      v59 = 1;
      v58 = 804;
      if ( on_water )
      {
        v57 = (SoundID)102;
        v56 = pAudioPlayer;
        goto LABEL_175;
      }
      v56 = pAudioPlayer;
      if ( BYTE2(pIndoor->pFaces[uFaceID].uAttributes) & 0x20 )
        v57 = (SoundID)89;
      else
        v57 = (SoundID)103;
LABEL_175:
      pAudioPlayer->PlaySound(v57, v58, v59, v60, v61, v62, v64, v66);
    }
    else
    {
LABEL_188:
      pAudioPlayer->_4AA258(804);
      pParty->walk_sound_timer = 64;
    }
  }
  if ( !bJumping || jumping_up )
    pParty->uFlags &= ~PARTY_FLAGS_1_FALLING;
  else
    pParty->uFlags |= PARTY_FLAGS_1_FALLING;
  pParty->uFlags &= ~0x200;
  pParty->vPosition.x = new_party_x;
  pParty->vPosition.z = new_party_z;
  pParty->vPosition.y = new_party_y;
  //pParty->uFallSpeed = v89;
  if ( !bJumping && BYTE3(pIndoor->pFaces[uFaceID].uAttributes) & 0x40 )
    pParty->uFlags |= 0x200;
  if (uFaceEvent)
    EventProcessor(uFaceEvent, 0, 1);
}

//----- (00473893) --------------------------------------------------------
void __cdecl ODM_ProcessPartyActions()
{
  //int _zero; // esi@1
  int v1; // edi@1
  int v2; // ebx@1
  int v3; // eax@14
  //Player **v4; // esi@21
  //int v5; // eax@24
  int v6; // esi@45
  ODMFace *v7; // ecx@45
  //unsigned int v8; // eax@71
  //double v9; // st7@72
  //signed __int64 v10; // qax@74
  //double v11; // st7@75
  //int v12; // ecx@77
  //int v13; // eax@84
  //double v14; // st7@84
  //int v15; // eax@87
  //double v16; // st7@87
  //int v17; // eax@88
  //double v18; // st7@88
  //int v19; // eax@89
  //double v20; // st7@89
  //int v21; // eax@92
  //double v22; // st7@92
  //int v23; // eax@96
  //double v24; // st7@96
  //int v25; // eax@97
  //double v26; // st7@97
  //int v27; // eax@98
  //double v28; // st7@98
  //signed __int64 v29; // qax@98
  //unsigned int v30; // eax@103
  int v31; // eax@130
  //int v32; // ecx@141
  signed int v33; // eax@143
  int v34; // esi@143
  int v35; // esi@147
  int v36; // eax@155
  signed int v37; // esi@159
  signed int v38; // eax@159
  signed int i; // esi@159
  int v40; // esi@162
  //Player **v41; // esi@172
  bool v42; // eax@180
  signed int v43; // ecx@184
  signed int v44; // edx@184
  int v45; // ecx@200
  BSPModel *v46; // eax@203
  ODMFace *v47; // esi@203
  int v48; // eax@203
  char v49; // zf@203
  char v50; // sf@203
  unsigned __int8 v51; // of@203
  int v52; // eax@203
  unsigned __int8 v53; // dl@205
  BSPModel *v54; // eax@215
  int v55; // eax@217
  signed int v56; // ebx@228
  int v57; // eax@228
  BSPModel *v58; // eax@228
  unsigned __int64 v59; // qax@228
  BSPModel *v60; // eax@228
  unsigned __int64 v61; // qax@228
  int v62; // eax@241
  signed int v63; // ST04_4@255
  signed int v64; // eax@255
  unsigned int v65; // ebx@263
  unsigned int v66; // esi@263
  int v67; // eax@263
  signed int v68; // ecx@263
  int v69; // eax@263
  int v70; // ebx@271
  int v71; // esi@271
  int v72; // edi@271
  int v73; // eax@271
  Player **v74; // esi@283
  int v75; // eax@284
  unsigned int v76; // edi@293
  bool v77; // edx@297
  bool v78; // ecx@303
  int v79; // ecx@314
  __int16 v80; // dx@317
  int v81; // ebx@318
  int v82; // ecx@318
  int v83; // eax@321
  Player **v84; // esi@333
  int v85; // eax@334
  int v86; // [sp-20h] [bp-B4h]@246
  int v87; // [sp-20h] [bp-B4h]@248
  signed int v88; // [sp-1Ch] [bp-B0h]@246
  unsigned int v89; // [sp-18h] [bp-ACh]@246
  signed int v90; // [sp-14h] [bp-A8h]@246
  signed int v91; // [sp-10h] [bp-A4h]@246
  int v92; // [sp-Ch] [bp-A0h]@246
  //int v93; // [sp-8h] [bp-9Ch]@104
  unsigned int v94; // [sp-8h] [bp-9Ch]@246
  //int v95; // [sp-4h] [bp-98h]@104
  int v96; // [sp-4h] [bp-98h]@246
  int v97; // [sp+Ch] [bp-88h]@180
  Vec3_int_ v98;
  //int v98; // [sp+10h] [bp-84h]@147
  //int v99; // [sp+14h] [bp-80h]@147
  //int v100; // [sp+18h] [bp-7Ch]@147
  bool v101; // [sp+1Ch] [bp-78h]@33
  int v102; // [sp+20h] [bp-74h]@1
  int v103; // [sp+24h] [bp-70h]@1
  int bFeatherFall; // [sp+28h] [bp-6Ch]@4
  int v105; // [sp+2Ch] [bp-68h]@24
  int bWaterWalk; // [sp+30h] [bp-64h]@1
  bool v107; // [sp+34h] [bp-60h]@30
  int v108; // [sp+38h] [bp-5Ch]@1
  int v109; // [sp+3Ch] [bp-58h]@28
  int v110; // [sp+40h] [bp-54h]@180
  int v111; // [sp+44h] [bp-50h]@14
  int bJumping; // [sp+48h] [bp-4Ch]@1
  int v113; // [sp+4Ch] [bp-48h]@1
  unsigned int v114; // [sp+50h] [bp-44h]@1
  int _walk_speed; // [sp+54h] [bp-40h]@48
  int pX; // [sp+58h] [bp-3Ch]@1
  int pY; // [sp+5Ch] [bp-38h]@1
  int v118; // [sp+60h] [bp-34h]@1
  //Player **v119; // [sp+64h] [bp-30h]@4
  int _angle_x; // [sp+68h] [bp-2Ch]@48
  int v121; // [sp+6Ch] [bp-28h]@1
  unsigned int v122; // [sp+70h] [bp-24h]@180
  int pZ; // [sp+74h] [bp-20h]@1
  int v124; // [sp+78h] [bp-1Ch]@1
  int _angle_y; // [sp+7Ch] [bp-18h]@48
  int v126; // [sp+80h] [bp-14h]@48
  BSPModel *v127; // [sp+84h] [bp-10h]@1
  int v128; // [sp+88h] [bp-Ch]@1
  int v129; // [sp+8Ch] [bp-8h]@92
  int v130; // [sp+90h] [bp-4h]@14

  v121 = pParty->uFallSpeed;
  pZ = pParty->vPosition.z;
  v1 = 0;
  v103 = 0;
  v2 = 0;
  *(float *)&v128 = 0.0;
  pX = pParty->vPosition.x;
  pY = pParty->vPosition.y;
  v113 = pParty->field_6F0;
  bJumping = 0;
  auto partyAtHighSlope = IsTerrainSlopeTooHigh(pParty->vPosition.x, pParty->vPosition.y);
  v114 = 0;
  v124 = 0;
  v108 = 0;
  v102 = 0;
  v127 = 0;
  bWaterWalk = 0;
  if (!pParty->FeatherFallActive())
      //SHIDWORD(pParty->pPartyBuffs[5].uExpireTime) < 0
      //|| SHIDWORD(pParty->pPartyBuffs[5].uExpireTime) <= 0 && LODWORD(pParty->pPartyBuffs[5].uExpireTime) <= 0 )
  {
    bFeatherFall = 0;
    /*v119 = &pPlayers[1];
    while ( !(*v119)->WearsItem(536, 16) )
    {
      ++v119;
      if ( (signed int)v119 > (signed int)&pPlayers[4] )
        goto LABEL_9;
    }*/
    for (int i = 0; i < 4; ++i)
      if (pParty->pPlayers[i].WearsItem(536, 16))  // seems like flying boots
      {
        bFeatherFall = 1;
        break;
      }
  }
  else
  {
	bFeatherFall = 1;
  }
//LABEL_9:
  pParty->uFlags &= ~PARTY_FLAGS_1_STANDING_ON_WATER;
  if (pParty->WaterWalkActive())
  {
    //LOBYTE(pParty->uFlags) &= 0x7Fu;
    bWaterWalk = 1;
    *(short *)&stru_5E4C90._decor_events[20 * pParty->pPartyBuffs[18].uOverlayID + 119] |= 1u;
    if (!(pParty->pPartyBuffs[PARTY_BUFF_WATER_WALK].uFlags & 1) &&
		pParty->pPlayers[pParty->pPartyBuffs[PARTY_BUFF_WATER_WALK].uCaster-1].sMana <= 0 )
		//*(int *)&pParty->pArtifactsFound[6972 * pParty->pPartyBuffs[18].uCaster + 10] <= 0 )
      bWaterWalk = 0;
  }
  v3 = ODM_GetFloorLevel(pX, pY, pZ, pParty->uPartyHeight, &v130, &v108, bWaterWalk);
  v111 = v3;
  if ( bFeatherFall )
    pParty->uFallStartY = v3;
  else
    v3 = pParty->uFallStartY;
  if ( v3 - pZ > 512 && !bFeatherFall && pZ <= v111 + 1 )
  {
    if (pParty->uFlags & PARTY_FLAGS_1_LANDING)
    {
      pParty->uFlags &= ~PARTY_FLAGS_1_LANDING;
    }
    else for (int _i = 0; _i < 4; ++_i)     // receive falling damage
    {
      auto player = pParty->pPlayers + _i;

      if ( !player->HasEnchantedItemEquipped(72) && !player->WearsItem(529, 8) )
      {
        player->ReceiveDamage(
            (signed int)((pParty->uFallStartY - pZ) * (unsigned __int64)(player->GetMaxHealth() / 10)) / 256,
            4);
        v105 = 20 - player->_48EA1B_get_static_effect(player->GetActualEndurance());
        player->SetRecoveryTime((signed __int64)((double)v105 * flt_6BE3A4_debug_recmod1 * 2.133333333333333));
      }
      //}
      //while ( (signed int)v4 <= (signed int)&pPlayers[4] );
    }
  }
  v109 = -1;
  if ( pParty->bFlying )
    v109 = sub_46D8E3(pX, pY, pZ + pParty->uPartyHeight, (int)&v102);
  v107 = v108 == 0;
  v105 = v111 + 1;
  if ( pZ <= v111 + 1 )
  {
    v109 = -1;
    pParty->bFlying = false;
  }
  else
  {
    bJumping = 1;
  }
  v101 = pZ - v111 <= 32;
  if ( bWalkSound && pParty->walk_sound_timer)
  {
    if (pParty->walk_sound_timer >= pEventTimer->uTimeElapsed)
      pParty->walk_sound_timer -= pEventTimer->uTimeElapsed;
    else pParty->walk_sound_timer = 0;
  }
  if (!bUnderwater
    && SHIDWORD(pParty->pPartyBuffs[7].uExpireTime) <= 0
    && (SHIDWORD(pParty->pPartyBuffs[7].uExpireTime) < 0 || LODWORD(pParty->pPartyBuffs[7].uExpireTime) <= 0) )
    pParty->bFlying = false;
  if (!bJumping)
  {
    if ( pParty->floor_face_pid != PID(OBJECT_BModel, v108) )
    {
      if (v108)
      {
        if ( v108 >> 6 < pOutdoor->uNumBModels )
        {
          v7 = pOutdoor->pBModels[v108 >> 6].pFaces;
          v6 = v108 & 0x3F;
          /*if ( *(char *)(v7->pFacePlane.vNormal.x + 308 * v6 + 31) & 4 )
          {
            pParty->field_6F4_packedid = PID(OBJECT_BModel,v108);
            v103 = *(short *)(v7->pFacePlane.vNormal.x + 308 * v6 + 292);
          }*/
		  if ( BYTE3(v7[v6].uAttributes) & 4 )
          {
            pParty->floor_face_pid = PID(OBJECT_BModel, v108);
            v103 = v7[v6].sCogTriggeredID;
          }
        }
      }
    }
    pParty->floor_face_pid = PID(OBJECT_BModel, v108);
  }
  _walk_speed = pParty->uWalkSpeed;
  _angle_y = pParty->sRotationY;
  _angle_x = pParty->sRotationX;
  v126 = pEventTimer->dt_in_some_format;
  /*v119 = (Player **)((unsigned __int64)(pEventTimer->dt_in_some_format
                                      * (signed __int64)((signed int)(pParty->field_20_prolly_turn_speed
                                                                    * stru_5C6E00->uIntegerPi)
                                                       / 180)) >> 16);*/
  __int64 dturn = (unsigned __int64)(pEventTimer->dt_in_some_format * (signed __int64)((signed int)(pParty->y_rotation_speed * stru_5C6E00->uIntegerPi) / 180)) >> 16;
  while (pPartyActionQueue->uNumActions)
  {
    switch (pPartyActionQueue->Next())
    {
      case PARTY_FlyUp:
      {
        if (!pParty->FlyActive() && !bUnderwater)
          break;

        pParty->bFlying = false;
        if (bUnderwater ||
            pParty->pPartyBuffs[PARTY_BUFF_FLY].uFlags & 1 ||
            pParty->pPlayers[pParty->pPartyBuffs[PARTY_BUFF_FLY].uCaster - 1].sMana > 0 )
          {
            if ( pParty->vPosition.z < 4000 || bJumping )
            {
              pZ += 30;
              v113 += 30;
              pParty->bFlying = 1;
              if ( pZ > 4000 )
              {
                pZ = 4000;
                v113 = 4000;
              }
              v1 = 0;
              v2 = 0;
              v121 = 0;
              *(float *)&v128 = 0.0;
              if ( v102 && pZ < v109 && (signed int)(pParty->uPartyHeight + pZ) >= v109 )
              {
                pParty->field_6E0 = 0;
                pParty->field_6E4 = 0;
                pPartyActionQueue->uNumActions = 0;
                pParty->uFlags |= PARTY_FLAGS_1_LANDING;
                pParty->vPosition.z = v109 - pParty->uPartyHeight - 31;
                pParty->field_6F0 = pZ;
                pParty->bFlying = 0;
                pZ = v109 - pParty->uPartyHeight - 31;
                v113 = pParty->field_6F0;
              }
              pParty->uFallSpeed = 0;
              v127 = (BSPModel *)1;
            }
          }
      }
      break;

      case PARTY_FlyDown:
        if (pParty->FlyActive() || bUnderwater)
        {
          pParty->bFlying = 0;
          if ( bUnderwater
            || pParty->pPartyBuffs[7].uFlags & 1
            || pParty->pPlayers[pParty->pPartyBuffs[7].uCaster - 1].sMana > 0 )//*(int *)&pParty->pArtifactsFound[6972 * pParty->pPartyBuffs[7].uCaster + 10] > 0 )
          {
            pZ -= 30;
            v113 -= 30;
            pParty->uFallSpeed = 0;
            v121 = 0;
            pParty->bFlying = 1;
            v127 = (BSPModel *)1;
            if ( pZ <= v111 )
            {
              pParty->bFlying = 0;
              pPartyActionQueue->uNumActions = 0;
            }
          }
        }
        break;

      case PARTY_TurnLeft:
        if (uTurnSpeed)
          _angle_y += uTurnSpeed;   //descrete turn
        else
          _angle_y += dturn * fTurnSpeedMultiplier;  // time-based smooth turn

        _angle_y &= stru_5C6E00->uDoublePiMask;
      break;

      case PARTY_TurnRight:
        if (uTurnSpeed)
          _angle_y -= uTurnSpeed;
        else
          _angle_y -= dturn * fTurnSpeedMultiplier;

        _angle_y &= stru_5C6E00->uDoublePiMask;
      break;

      case PARTY_FastTurnLeft:
        if (uTurnSpeed)
          _angle_y += uTurnSpeed;
        else
          _angle_y += 2.0f * fTurnSpeedMultiplier * (double)dturn;

        _angle_y &= stru_5C6E00->uDoublePiMask;
      break;

      case PARTY_FastTurnRight:
        if (!uTurnSpeed)
          _angle_y -= 2.0f * fTurnSpeedMultiplier * (double)dturn;
        else
          _angle_y -= uTurnSpeed;

        _angle_y &= stru_5C6E00->uDoublePiMask;
      break;

      case PARTY_StrafeLeft:
      {
        *(float *)&v128 = pParty->uWalkSpeed;

        float sin_y = sinf(2 * 3.141592653589 * _angle_y / 2048.0);
        int dx = sin_y * pParty->uWalkSpeed * fWalkSpeedMultiplier;
        v2 -= 3 * dx / 4;
        
        float cos_y = cosf(2 * 3.141592653589 * _angle_y / 2048.0);
        int dy = cos_y * pParty->uWalkSpeed * fWalkSpeedMultiplier;
        v1 += 3 * dy / 4;

        v128 = v1;
        v124 = 1;
      }
      break;

      case PARTY_StrafeRight:
      {
        *(float *)&v128 = pParty->uWalkSpeed;

        float sin_y = sinf(2 * 3.141592653589 * _angle_y / 2048.0);
        int dx = sin_y * pParty->uWalkSpeed * fWalkSpeedMultiplier;
        v2 += 3 * dx / 4;
        
        float cos_y = cosf(2 * 3.141592653589 * _angle_y / 2048.0);
        int dy = cos_y * pParty->uWalkSpeed * fWalkSpeedMultiplier;
        v1 -= 3 * dy / 4;

        v128 = v1;
        v124 = 1;
      }
      break;

      case PARTY_WalkForward:
      {
        *(float *)&v128 = _walk_speed;

        float sin_y = sinf(2 * 3.141592653589 * _angle_y / 2048.0),
              cos_y = cosf(2 * 3.141592653589 * _angle_y / 2048.0);

        int dx = cos_y * pParty->uWalkSpeed * fWalkSpeedMultiplier;
        v2 += dx * 12;
        
        int dy = sin_y * pParty->uWalkSpeed * fWalkSpeedMultiplier;
        v1 += dy * 12;

        v128 = v1;
        v124 = 1;
      }
      break;

      case PARTY_RunForward:
      {
        *(float *)&v128 = _walk_speed;

        float sin_y = sinf(2 * 3.141592653589 * _angle_y / 2048.0),
              cos_y = cosf(2 * 3.141592653589 * _angle_y / 2048.0);

        int dx = cos_y * pParty->uWalkSpeed * fWalkSpeedMultiplier;        
        int dy = sin_y * pParty->uWalkSpeed * fWalkSpeedMultiplier;

        if (pParty->bFlying)
        {
          v2 += 4 * dx;
          v1 += 4 * dy;

          v128 = v1;
        }
        else if (partyAtHighSlope && !v108)
        {
          v2 += dx;
          v1 += dy;

          v128 = v1;
          v124 = 1;
        }
        else
        {
          v2 += 2 * dx;
          v1 += 2 * dy;
          
          v128 = v1;
          v114 = 1;
        }
      }
      break;


      case PARTY_WalkBackward:
      {
        *(float *)&v128 = _walk_speed;

        float sin_y = sinf(2 * 3.141592653589 * _angle_y / 2048.0),
              cos_y = cosf(2 * 3.141592653589 * _angle_y / 2048.0);

        int dx = cos_y * pParty->uWalkSpeed * fBackwardWalkSpeedMultiplier;
        v2 -= dx;
        
        int dy = sin_y * pParty->uWalkSpeed * fBackwardWalkSpeedMultiplier;
        v1 -= dy;

        v128 = v1;
        v124 = 1;
      }
      break;


      case PARTY_RunBackward:
      {
        float sin_y = sinf(2 * 3.141592653589 * _angle_y / 2048.0),
              cos_y = cosf(2 * 3.141592653589 * _angle_y / 2048.0);

        int dx = cos_y * pParty->uWalkSpeed * fBackwardWalkSpeedMultiplier;        
        int dy = sin_y * pParty->uWalkSpeed * fBackwardWalkSpeedMultiplier;

        if (pParty->bFlying)
        {
          v2 -= 4 * dx;
          v1 -= 4 * dy;
          v128 = v1;
        }
        else
        {
          v2 -= dx;
          v1 -= dy;

          v128 = v1;
          v124 = 1;
        }
      }
      break;

      
      case PARTY_CenterView:
        _angle_x = 0;
      break;

      case PARTY_LookUp:
        _angle_x += (signed __int64)(flt_6BE150_look_up_down_dangle * 25.0);
        if ( _angle_x > 128 )
          _angle_x = 128;
        if (uActiveCharacter)
          pPlayers[uActiveCharacter]->PlaySound(SPEECH_63, 0);
      break;

      case PARTY_LookDown:
        _angle_x += (signed __int64)(flt_6BE150_look_up_down_dangle * -25.0);
        if ( _angle_x < -128 )
          _angle_x = -128;
        if (uActiveCharacter)
          pPlayers[uActiveCharacter]->PlaySound(SPEECH_64, 0);
      break;

      case PARTY_Jump:
        if ( (!partyAtHighSlope || v108) && !bJumping && pParty->field_24 && !(pParty->uFlags & 4) && !(BYTE1(pParty->uFlags) & 2) )
        {
          v126 = pParty->field_24 << 6;
          bJumping = 1;
          v121 = (signed __int64)((double)(pParty->field_24 << 6) * 1.5 + (double)v121);
        }
      break;

      default:
        assert(false);

      case PARTY_Land:
        if (pParty->bFlying)
        {
          pParty->uFlags |= PARTY_FLAGS_1_LANDING;
          pParty->uFallSpeed = 0;
        }
        pParty->bFlying = false;
        pPartyActionQueue->uNumActions = 0;
      break;
    }
  }

LABEL_123:
  pParty->sRotationY = _angle_y;
  pParty->sRotationX = _angle_x;
  if ( pZ < v111 )
  {
    if ( pParty->bFlying )
    {
LABEL_130:
      v31 = GetTickCount();
      v126 = stru_5C6E00->Cos(v31);
      v129 = (unsigned __int64)(4i64 * v126) >> 16;
      pZ = v113 + v129;
      if ( v127 )
        pZ = v113;
      if (pParty->FlyActive())
        stru_5E4C90._decor_events[20 * pParty->pPartyBuffs[7].uOverlayID + 119] &= 0xFEu;
      pParty->uFallStartY = pZ;
      goto LABEL_141;
    }
    if ( v130 && v121 )
      sub_42F960_create_object(pX, pY, v111);
    v121 = 0;
    pZ = v111;
    pParty->uFallStartY = v111;
  }
  if ( pParty->bFlying )
    goto LABEL_130;
  v113 = pZ;
  if (pParty->FlyActive())
    stru_5E4C90._decor_events[20 * pParty->pPartyBuffs[7].uOverlayID + 119] |= 1u;

LABEL_141:
  if (bJumping && !pParty->bFlying)
  {
    v33 = -(pEventTimer->uTimeElapsed * GetGravityStrength());
    v34 = v121 + 2 * v33;
    v121 += 2 * v33;
    goto LABEL_164;
  }
  if (!partyAtHighSlope)
  {
    v34 = v121;
    if (!bJumping)
      goto LABEL_150;
    goto LABEL_164;
  }
  if (!bJumping)
  {
    if ( v108 )
      goto LABEL_150;

    // rolling down the hill
    // how it's done: you get a little bit pushed in the air along terrain normal, getting in the air
    // and falling to the gravity, gradually sliding downwards. nice trick
    pZ = v111;
    ODM_GetTerrainNormalAt(pX, pY, &v98);
    v35 = v121 + -8 * pEventTimer->uTimeElapsed * GetGravityStrength();
    v129 = abs((signed __int64)v2 * v98.x + (signed __int64)v1 * v98.y + (signed __int64)v35 * v98.z) >> 16;
    v2 += (unsigned __int64)(v129 * (signed __int64)v98.x) >> 16;
    v1 += (unsigned __int64)(v129 * (signed __int64)v98.y) >> 16;
    v34 = v35 + ((unsigned __int64)(v129 * (signed __int64)v98.z) >> 16);
    v128 = v1;
    v121 = v34;
    if (!bJumping)
      goto LABEL_150;
    goto LABEL_164;
  }
  v34 = v121;

LABEL_164:
  if ( !bUnderwater && v34 <= 0)
  {
    if ( v34 < -500
      && !pParty->bFlying
      && pParty->vPosition.z - v111 > 1000
      && !pParty->FeatherFallActive())
    { // falling scream
      for (int i = 0; i < 4; ++i)
      {
        auto player = pParty->pPlayers + i;
        if (!player->HasEnchantedItemEquipped(72) && !player->WearsItem(529, 8) && player->CanAct())
          player->PlaySound(SPEECH_66, 0);
      }
    }
  }
  else
  {
LABEL_150:
  pParty->uFallStartY = pZ;
  }

  if ( v2 * v2 + v1 * v1 < 400 && !partyAtHighSlope )
  {
    *(float *)&v128 = 0.0;
    v2 = 0;
  }
  stru_721530.field_84 = -1;
  stru_721530.field_70 = 0;
  stru_721530.prolly_normal_d = pParty->field_14;
  stru_721530.field_8 = pParty->field_14 >> 1;
  v126 = 0;
  stru_721530.field_0 = 1;
  stru_721530.field_C = pParty->uPartyHeight - 32;
  do
  {
    stru_721530.field_34.x = pX;
    stru_721530.normal.x = pX;
    stru_721530.field_1C = v2;
    stru_721530.field_34.y = pY;
    stru_721530.normal.y = pY;
    stru_721530.normal.z = stru_721530.prolly_normal_d + pZ + 1;
    stru_721530.field_34.z = stru_721530.field_C + pZ + 1;
    stru_721530.field_20 = v128;
    stru_721530.field_24 = v121;
    v36 = 0;
    stru_721530.uSectorID = 0;
    if ( pParty->bTurnBasedModeOn == 1 && pTurnEngine->field_4 == 3 )
      v36 = 13312;
    if ( stru_721530._47050A(v36) )
      break;
    _46E889_collide_against_bmodels(1u);
    v37 = WorldPosToGridCellZ(pParty->vPosition.y);
    v38 = WorldPosToGridCellX(pParty->vPosition.x);
    _46E26D_collide_against_sprites(v38, v37);
    _46ED8A_collide_against_sprite_objects(4u);
    for ( i = 0; i < (signed int)uNumActors; ++i )
      _46DF1A_collide_against_actor(i, 0);
    if ( stru_721530.field_7C >= stru_721530.field_6C )
    {
      _angle_x = stru_721530.normal2.x;
      _angle_y = stru_721530.normal2.y;
      v40 = stru_721530.normal2.z - stru_721530.prolly_normal_d - 1;
    }
    else
    {
      _angle_x = pX + ((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.x) >> 16);
      _angle_y = pY + ((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.y) >> 16);
      v127 = (BSPModel *)((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16);
      v40 = ((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16) + pZ;
    }
    v122 = v40;
    ODM_GetFloorLevel(_angle_x, _angle_y, v40, pParty->uPartyHeight, &v130, &v108, 0);
    v129 = ODM_GetFloorLevel(_angle_x, pY, v40, pParty->uPartyHeight, &v130, &v97, 0);
    auto v119 = ODM_GetFloorLevel(pX, _angle_y, v40, pParty->uPartyHeight, &v130, &v110, 0);
    v127 = (BSPModel *)IsTerrainSlopeTooHigh(_angle_x, pY);
    v42 = IsTerrainSlopeTooHigh(pX, _angle_y);
    v107 = 0;
    v118 = v42;
    if ( !v97 && !v110 && !v108 )
      v107 = 1;
    v43 = 1;
    v44 = 1;
    if ( bUnderwater || !v107 )
      goto LABEL_197;
    if ( v127 && v129 > pZ )
      v44 = 0;
    if ( v118 && v119 > pZ )
      v43 = 0;
    if ( v44 )
      goto LABEL_197;
    if ( v43 )
      goto LABEL_198;
    v127 = (BSPModel *)ODM_GetFloorLevel(_angle_x, _angle_y, v40, pParty->uPartyHeight, &v130, &v108, 0);
    if ( IsTerrainSlopeTooHigh(_angle_x, _angle_y) && (signed int)v127 <= pZ )
    {
      v43 = 1;
LABEL_197:
      pX = _angle_x;
      if ( !v43 )
        goto LABEL_199;
LABEL_198:
      pY = _angle_y;
    }
LABEL_199:
    if ( stru_721530.field_7C >= stru_721530.field_6C )
    {
      if ( !v107 )
      {
        pX = stru_721530.normal2.x;
        pY = stru_721530.normal2.y;
      }
      pZ = stru_721530.normal2.z - stru_721530.prolly_normal_d - 1;
      break;
    }
    stru_721530.field_70 += stru_721530.field_7C;
    pX = _angle_x;
    pY = _angle_y;
    v45 = stru_721530.uFaceID;
    pZ = v40;
    if ( PID_TYPE(stru_721530.uFaceID) == OBJECT_Actor)
    {
      if (pParty->Invisible())
        pParty->pPartyBuffs[PARTY_BUFF_INVISIBILITY].Reset();

      viewparams->bRedrawGameUI = 1;
      goto LABEL_234;
    }
    if ( PID_TYPE(stru_721530.uFaceID) == OBJECT_Decoration)
    {
      v56 = integer_sqrt(v2 * v2 + v128 * v128);
      v118 = v56;
      v57 = stru_5C6E00->Atan2(
              _angle_x - pLevelDecorations[(signed int)stru_721530.uFaceID >> 3].vPosition.x,
              _angle_y - pLevelDecorations[(signed int)stru_721530.uFaceID >> 3].vPosition.y);
      v129 = v57;
      v58 = (BSPModel *)stru_5C6E00->Cos(v57);
      v127 = v58;
      v59 = (signed int)v58 * (signed __int64)v56;
      v122 = v59 >> 16;
      v2 = v59 >> 16;
      v60 = (BSPModel *)stru_5C6E00->Sin(v129);
      v127 = v60;
      v61 = (signed int)v60 * (signed __int64)v118;
      v122 = v61 >> 16;
      v128 = v61 >> 16;
    }
    else
    {
      if ( PID_TYPE(stru_721530.uFaceID) == OBJECT_BModel)
      {
        pParty->bFlying = 0;
        v46 = &pOutdoor->pBModels[(signed int)stru_721530.uFaceID >> 9];
        v127 = v46;
		v47 = &v46->pFaces[((signed int)stru_721530.uFaceID >> 3) & 0x3F];
        v48 = v47->pBoundingBox.z2 - v47->pBoundingBox.z1;
        v51 = __OFSUB__(v48, 32);
        v49 = v48 == 32;
        v50 = v48 - 32 < 0;
        v52 = v47->pFacePlane.vNormal.z;
        v129 = (unsigned __int8)(v50 ^ v51 | v49);
        v119 = v52 < 46378;
        if ( bUnderwater == 1 )
          v119 = 0;
        v53 = v47->uPolygonType;
        if ( v53 == 3 )
        {
          if ( v121 < 0 )
            v121 = 0;
          pZ = v127->pVertices.pVertices[v47->pVertexIDs[0]].z + 1;
          if ( v2 * v2 + v128 * v128 < 400 )
          {
            v2 = 0;
            *(float *)&v128 = 0.0;
          }
          goto LABEL_221;
        }
        if ( !v129 && (v53 != 4 || v119) )
        {
          v118 = abs(v128 * v47->pFacePlane.vNormal.y + v121 * v52 + v2 * v47->pFacePlane.vNormal.x) >> 16;
          if ( stru_721530.field_64 >> 3 > v118 )
            v118 = stru_721530.field_64 >> 3;
          v129 = v47->pFacePlane.vNormal.x;
          v129 = (unsigned __int64)(v118 * (signed __int64)v129) >> 16;
          _walk_speed = v47->pFacePlane.vNormal.y;
          _walk_speed = (unsigned __int64)(v118 * (signed __int64)_walk_speed) >> 16;
          v54 = 0;
          if ( !v119 )
          {
            v127 = (BSPModel *)v47->pFacePlane.vNormal.z;
            v127 = (BSPModel *)((unsigned __int64)(v118 * (signed __int64)(signed int)v127) >> 16);
            v54 = v127;
          }
          v121 += (int)v54;
          v128 += _walk_speed;
          v2 += v129;
          v55 = stru_721530.prolly_normal_d
              - ((signed int)(v47->pFacePlane.dist
                            + v122 * v47->pFacePlane.vNormal.z
                            + _angle_y * v47->pFacePlane.vNormal.y
                            + _angle_x * v47->pFacePlane.vNormal.x) >> 16);
          if ( v55 > 0 )
          {
            pX = _angle_x + (v47->pFacePlane.vNormal.x * v55 >> 16);
            pY = _angle_y + (v47->pFacePlane.vNormal.y * v55 >> 16);
            if ( !v119 )
              pZ = v122 + (v47->pFacePlane.vNormal.z * v55 >> 16);
          }
LABEL_220:
          v45 = stru_721530.uFaceID;
LABEL_221:
          if ( pParty->floor_face_pid != v45 && BYTE3(v47->uAttributes) & 4 )
          {
            pParty->floor_face_pid = v45;
            v103 = v47->sCogTriggeredID;
          }
          goto LABEL_234;
        }
        v118 = abs(v128 * v47->pFacePlane.vNormal.y + v121 * v52 + v2 * v47->pFacePlane.vNormal.x) >> 16;
        if ( stru_721530.field_64 >> 3 > v118 )
          v118 = stru_721530.field_64 >> 3;
        v122 = v47->pFacePlane.vNormal.x;
        v122 = (unsigned __int64)(v118 * (signed __int64)(signed int)v122) >> 16;
        v127 = (BSPModel *)v47->pFacePlane.vNormal.y;
        v127 = (BSPModel *)((unsigned __int64)(v118 * (signed __int64)(signed int)v127) >> 16);
        v129 = v47->pFacePlane.vNormal.z;
        v129 = (unsigned __int64)(v118 * (signed __int64)v129) >> 16;
        v121 += v129;
        v2 += v122;
        v128 += (int)v127;
        if ( v2 * v2 + v128 * v128 >= 400 )
          goto LABEL_220;
        v2 = 0;
        v121 = 0;
        *(float *)&v128 = 0.0;
      }
    }
LABEL_234:
    v2 = (unsigned __int64)(58500i64 * v2) >> 16;
    v127 = (BSPModel *)58500;
    v128 = (unsigned __int64)(58500i64 * v128) >> 16;
    v122 = (unsigned __int64)(58500i64 * v121) >> 16;
    ++v126;
    v121 = (unsigned __int64)(58500i64 * v121) >> 16;
  }
  while ( v126 < 100 );
  if ( bWalkSound && pParty->walk_sound_timer <= 0 )
  {
    v122 = abs(pParty->vPosition.x - pX);
    v126 = abs(pParty->vPosition.y - pY);
    v62 = abs(pParty->vPosition.z - pZ);
    if ( integer_sqrt(v122 * v122 + v126 * v126 + v62 * v62) < 8 )
      goto LABEL_344;
    if ( v114 && (!bJumping || v101) )
    {
      if ( !v107
        && !(BYTE1(pOutdoor->pBModels[pParty->floor_face_pid >> 9].pFaces[(pParty->floor_face_pid >> 3) & 0x3F].uAttributes) & 0x20) )
      {
        
        v90 = -1;
        v89 = 1;
        v88 = 804;
        v87 = 64;
        goto LABEL_257;
      }
     
      v90 = -1;
      v89 = 1;
      v88 = 804;
      v86 = 1;
LABEL_255:
      v63 = WorldPosToGridCellZ(pParty->vPosition.y) - 1;
      v64 = WorldPosToGridCellX(pParty->vPosition.x);
      v87 = pOutdoor->GetSoundIdByPosition(v64, v63, v86);
      goto LABEL_257;
    }
    if ( v124 && (!bJumping || v101) )
    {
      if ( v107
        || BYTE1(pOutdoor->pBModels[pParty->floor_face_pid >> 9].pFaces[(pParty->floor_face_pid >> 3) & 0x3F].uAttributes) & 0x20 )
      {
        
        v90 = -1;
        v89 = 1;
        v88 = 804;
        v86 = 0;
        goto LABEL_255;
      }
      v90 = -1;
      v89 = 1;
      v88 = 804;
      v87 = 103;
LABEL_257:
      pAudioPlayer->PlaySound((SoundID)v87, v88, v89, v90, 0, 0, 0, 0);
    }
    else
    {
LABEL_344:
      pAudioPlayer->_4AA258(804);
      pParty->walk_sound_timer = 64;
    }
  }
  if ( !bJumping || v101 )
    pParty->uFlags &= ~PARTY_FLAGS_1_FALLING;
  else
    pParty->uFlags |= PARTY_FLAGS_1_FALLING;
  v126 = WorldPosToGridCellX(pParty->vPosition.x);
  v65 = WorldPosToGridCellZ(pParty->vPosition.y) - 1;
  v114 = WorldPosToGridCellX(pX);
  v66 = WorldPosToGridCellZ(pY) - 1;
  v127 = (BSPModel *)(((unsigned int)~pOutdoor->ActuallyGetSomeOtherTileInfo(v126, v65) >> 1) & 1);
  v122 = ((unsigned int)~pOutdoor->ActuallyGetSomeOtherTileInfo(v114, v65) >> 1) & 1;
  v67 = pOutdoor->ActuallyGetSomeOtherTileInfo(v126, v66);
  v68 = 0;
  v69 = ((unsigned int)~v67 >> 1) & 1;
  if ( v114 == v126 && v66 == v65 && v122 && v69 )
    v68 = 1;
  if ( !v107 )
    v68 = 1;
  if ( v68 )
  {
    v70 = pZ;
    v71 = pX;
    v72 = pY;
    pParty->uFallSpeed = v121;
    v73 = pZ;
    pParty->vPosition.x = pX;
    pParty->vPosition.y = pY;
    pParty->vPosition.z = pZ;
    pParty->field_6F0 = v113;
    if ( pZ > 8160 )
    {
      v73 = 8160;
      pParty->uFallStartY = 8160;
      pParty->vPosition.z = 8160;
    }
    if ( !v103
      || (EventProcessor(v103, 0, 1), pParty->vPosition.x == v71)
      && pParty->vPosition.y == v72
      && (v73 = pParty->vPosition.z, pParty->vPosition.z == v70) )
    {
      if ( v73 < v111 )
      {
        pParty->uFallSpeed = 0;
        v73 = v105;
        pParty->vPosition.z = v105;
        if ( pParty->uFallStartY - v70 > 512 && !bFeatherFall && v70 <= v105 && !bUnderwater )
        {
          if ( pParty->uFlags & PARTY_FLAGS_1_LANDING )
          {
            pParty->uFlags &= ~PARTY_FLAGS_1_LANDING;
          }
          else
          {
            v74 = &pPlayers[1];
            do
            {
              v110 = (*v74)->GetMaxHealth();
              (*v74)->ReceiveDamage(
                (signed int)((pParty->uFallStartY - v70) * (unsigned __int64)(signed __int64)((double)v110 * 0.1)) / 256,
                4);
              v75 = (*v74)->GetActualEndurance();
              v110 = 20 - (*v74)->_48EA1B_get_static_effect(v75);
              (*v74)->SetRecoveryTime(
                (signed __int64)((double)v110 * flt_6BE3A4_debug_recmod1 * 2.133333333333333));
              ++v74;
            }
            while ( (signed int)v74 <= (signed int)&pPlayers[4] );
            v73 = pParty->vPosition.z;
          }
        }
        pParty->uFallStartY = v70;
      }
      if ( v102 && v73 < v109 )
      {
        if ( (signed int)(pParty->uPartyHeight + v73) >= v109 )
        {
          pParty->vPosition.z = v109 - pParty->uPartyHeight - 1;
          pParty->field_6F0 = v109 - pParty->uPartyHeight - 1;
        }
      }
      pParty->uFlags &= ~0x204;
    }
    return;
  }
  v76 = pParty->bFlying;
  if ( pParty->bFlying || v101 == 0 || bWaterWalk || !v127 )
    v77 = 1;
  else
    v77 = v122 != 0;
  v114 = 0;
  if ( !pParty->bFlying && v101 != 0 && !bWaterWalk )
  {
    if ( v127 )
    {
      v78 = v69 != 0;
      goto LABEL_306;
    }
    v114 = 1;
  }
  v78 = 1;
LABEL_306:
  if ( v77 )
  {
    pParty->vPosition.x = pX;
    if ( !v78 )
      goto LABEL_313;
    goto LABEL_312;
  }
  if ( v78 )
  {
LABEL_312:
    pParty->vPosition.y = pY;
LABEL_313:
    if ( bWaterWalk )
    {
      pParty->uFlags &= ~PARTY_FLAGS_1_STANDING_ON_WATER;
      //v79 = 20 * pParty->pPartyBuffs[18].uOverlayID + 6180178;
      //*(short *)&stru_5E4C90._decor_events[20 * pParty->pPartyBuffs[18].uOverlayID + 119] |= 1u;
      v79 = (int)&stru_5E4C90._decor_events[20 * pParty->pPartyBuffs[18].uOverlayID + 119];
      *(short *)v79 |= 1u;
      if ( !v122 || !v69 )
      {
        if ( !v76 )
        {
          v80 = *(short *)v79;
          pParty->uFlags |= PARTY_FLAGS_1_STANDING_ON_WATER;
          *(short *)v79 = v80 & 0xFFFE;
        }
      }
    }
    goto LABEL_318;
  }
  if ( bWalkSound && pParty->walk_sound_timer <= 0 )
  {
    pAudioPlayer->_4AA258(804);
    pParty->walk_sound_timer = 64;
  }
LABEL_318:
  v81 = pZ;
  v82 = pZ;
  pParty->vPosition.z = pZ;
  if ( pZ > 8160 )
  {
    v82 = 8160;
    pParty->uFallStartY = 8160;
    pParty->vPosition.z = 8160;
  }
  LOWORD(pParty->uFlags) &= 0xFDFBu;
  pParty->uFallSpeed = v121;
  pParty->field_6F0 = v113;
  if ( v114 )
  {
    v83 = GetTerrainHeightsAroundParty2(pParty->vPosition.x, pParty->vPosition.y, &v110, 1);
    v82 = pParty->vPosition.z;
    if ( pParty->vPosition.z <= v83 )
      pParty->uFlags |= 4u;
  }
  if ( !v103
    || (EventProcessor(v103, 0, 1), pParty->vPosition.x == pX)
    && pParty->vPosition.y == pY
    && (v82 = pParty->vPosition.z, pParty->vPosition.z == v81) )
  {
    if ( v82 < v111 )
    {
      v82 = v105;
      pParty->uFallSpeed = 0;
      pParty->vPosition.z = v105;
      if ( pParty->uFallStartY - v81 > 512 && !bFeatherFall && v81 <= v105 && !bUnderwater )
      {
        if ( pParty->uFlags & PARTY_FLAGS_1_LANDING )
        {
          pParty->uFlags &= ~PARTY_FLAGS_1_LANDING;
        }
        else
        {
          v84 = &pPlayers[1];
          do
          {
            v110 = (*v84)->GetMaxHealth();
            (*v84)->ReceiveDamage(
              (signed int)((pParty->uFallStartY - v81) * (unsigned __int64)(signed __int64)((double)v110 * 0.1)) / 256,
              4);
            v85 = (*v84)->GetActualEndurance();
            v110 = 20 - (*v84)->_48EA1B_get_static_effect(v85);
            (*v84)->SetRecoveryTime((signed __int64)((double)v110 * flt_6BE3A4_debug_recmod1 * 2.133333333333333));
            ++v84;
          }
          while ( (signed int)v84 <= (signed int)&pPlayers[4] );
          v82 = pParty->vPosition.z;
        }
      }
      pParty->uFallStartY = v81;
    }
    if ( v102 && v82 < v109 && (signed int)(pParty->uPartyHeight + v82) >= v109 )
    {
      pParty->vPosition.z = v82 + pParty->uPartyHeight - v109 + 1;
      pParty->field_6F0 = v82 + pParty->uPartyHeight - v109 + 1;
    }
  }
}

//----- (0047531C) --------------------------------------------------------
bool __fastcall sub_47531C(int a1, int *a2, int a3, int a4, int a5, int a6, int a7, int a8, BLVFace *a9, int a10)
{
  BLVFace *v10; // ebx@1
  int v11; // ST1C_4@3
  int v12; // edi@3
  int v13; // esi@3
  int v14; // edi@4
  signed __int64 v15; // qtt@6
  __int16 v16; // si@7
  int *v18; // [sp+Ch] [bp-Ch]@1
  int v19; // [sp+10h] [bp-8h]@1
  int a7a; // [sp+30h] [bp+18h]@7
  int a9b; // [sp+38h] [bp+20h]@3
  int a9a; // [sp+38h] [bp+20h]@3
  int a10b; // [sp+3Ch] [bp+24h]@3
  signed int a10a; // [sp+3Ch] [bp+24h]@4
  int a10c; // [sp+3Ch] [bp+24h]@5

  v10 = a9;
  v18 = a2;
  v19 = a1;
  if ( a10 && BYTE3(a9->uAttributes) & 0x20 )
    return 0;
  v11 = (unsigned __int64)(a6 * (signed __int64)a9->pFacePlane_old.vNormal.x) >> 16;
  a10b = (unsigned __int64)(a7 * (signed __int64)a9->pFacePlane_old.vNormal.y) >> 16;
  a9b = (unsigned __int64)(a8 * (signed __int64)a9->pFacePlane_old.vNormal.z) >> 16;
  v12 = v11 + a9b + a10b;
  a9a = v11 + a9b + a10b;
  v13 = (a1 << 16)
      - a3 * v10->pFacePlane_old.vNormal.x
      - a4 * v10->pFacePlane_old.vNormal.y
      - a5 * v10->pFacePlane_old.vNormal.z
      - v10->pFacePlane_old.dist;
  if ( abs((a1 << 16)
         - a3 * v10->pFacePlane_old.vNormal.x
         - a4 * v10->pFacePlane_old.vNormal.y
         - a5 * v10->pFacePlane_old.vNormal.z - v10->pFacePlane_old.dist) >= a1 << 16 )
  {
    a10c = abs(v13) >> 14;
    if ( a10c > abs(v12) )
      return 0;
    LODWORD(v15) = v13 << 16;
    HIDWORD(v15) = v13 >> 16;
    v14 = v19;
    a10a = v15 / a9a;
  }
  else
  {
    a10a = 0;
    v14 = abs(v13) >> 16;
  }
  v16 = a4 + ((unsigned int)((unsigned __int64)(a10a * (signed __int64)a7) >> 16) >> 16);
  LOWORD(a7a) = (short)a3
              + ((unsigned int)((unsigned __int64)(a10a * (signed __int64)a6) >> 16) >> 16)
              - ((unsigned int)(v14 * v10->pFacePlane_old.vNormal.x) >> 16);
  HIWORD(a7a) = v16 - ((unsigned int)(v14 * v10->pFacePlane_old.vNormal.y) >> 16);
  if ( !sub_475665(
          v10,
          a7a,
          (short)a5
        + ((unsigned int)((unsigned __int64)(a10a * (signed __int64)a8) >> 16) >> 16)
        - ((unsigned int)(v14 * v10->pFacePlane_old.vNormal.z) >> 16)) )
    return 0;
  *v18 = a10a >> 16;
  if ( a10a >> 16 < 0 )
    *v18 = 0;
  return 1;
}

//----- (004754BF) --------------------------------------------------------
bool __fastcall sub_4754BF(int a1, int *a2, int a3, int a4, int a5, int a6, int a7, int a8, BLVFace *a9, int a10, int a11)
{
  BLVFace *v11; // ebx@1
  int v12; // ST1C_4@3
  int v13; // edi@3
  int v14; // esi@3
  int v15; // edi@4
  signed __int64 v16; // qtt@6
  __int16 v17; // si@7
  int *v19; // [sp+Ch] [bp-Ch]@1
  int v20; // [sp+10h] [bp-8h]@1
  int a7a; // [sp+30h] [bp+18h]@7
  int a1b; // [sp+38h] [bp+20h]@3
  int a1a; // [sp+38h] [bp+20h]@3
  int a11b; // [sp+40h] [bp+28h]@3
  signed int a11a; // [sp+40h] [bp+28h]@4
  int a11c; // [sp+40h] [bp+28h]@5

  v11 = a9;
  v19 = a2;
  v20 = a1;
  if ( a11 && BYTE3(a9->uAttributes) & 0x20 )
    return 0;
  v12 = (unsigned __int64)(a6 * (signed __int64)a9->pFacePlane_old.vNormal.x) >> 16;
  a11b = (unsigned __int64)(a7 * (signed __int64)a9->pFacePlane_old.vNormal.y) >> 16;
  a1b = (unsigned __int64)(a8 * (signed __int64)a9->pFacePlane_old.vNormal.z) >> 16;
  v13 = v12 + a1b + a11b;
  a1a = v12 + a1b + a11b;
  v14 = (a1 << 16)
      - a3 * v11->pFacePlane_old.vNormal.x
      - a4 * v11->pFacePlane_old.vNormal.y
      - a5 * v11->pFacePlane_old.vNormal.z
      - v11->pFacePlane_old.dist;
  if ( abs((a1 << 16)
         - a3 * v11->pFacePlane_old.vNormal.x
         - a4 * v11->pFacePlane_old.vNormal.y
         - a5 * v11->pFacePlane_old.vNormal.z - v11->pFacePlane_old.dist) >= a1 << 16 )
  {
    a11c = abs(v14) >> 14;
    if ( a11c > abs(v13) )
      return 0;
    LODWORD(v16) = v14 << 16;
    HIDWORD(v16) = v14 >> 16;
    v15 = v20;
    a11a = v16 / a1a;
  }
  else
  {
    a11a = 0;
    v15 = abs(v14) >> 16;
  }
  v17 = a4 + ((unsigned int)((unsigned __int64)(a11a * (signed __int64)a7) >> 16) >> 16);
  LOWORD(a7a) = (short)a3
              + ((unsigned int)((unsigned __int64)(a11a * (signed __int64)a6) >> 16) >> 16)
              - ((unsigned int)(v15 * v11->pFacePlane_old.vNormal.x) >> 16);
  HIWORD(a7a) = v17 - ((unsigned int)(v15 * v11->pFacePlane_old.vNormal.y) >> 16);
  if ( !sub_4759C9(
          v11,
          a10,
          a7a,
          (short)a5
        + ((unsigned int)((unsigned __int64)(a11a * (signed __int64)a8) >> 16) >> 16)
        - ((unsigned int)(v15 * v11->pFacePlane_old.vNormal.z) >> 16)) )
    return 0;
  *v19 = a11a >> 16;
  if ( a11a >> 16 < 0 )
    *v19 = 0;
  return 1;
}

//----- (00475665) --------------------------------------------------------
signed int __thiscall sub_475665(BLVFace *_this, int a2, __int16 a3)
{
  unsigned int v3; // eax@1
  Vec3_short_ *v4; // edx@3
  signed int v5; // eax@4
  int v6; // esi@4
  signed int v7; // eax@7
  Vec3_short_ *v8; // edx@8
  signed int v9; // eax@9
  int v10; // esi@9
  signed int v11; // eax@11
  Vec3_short_ *v12; // edx@12
  signed int v13; // eax@13
  int v14; // esi@13
  int v15; // esi@14
  bool v16; // edi@14
  int v17; // ecx@16
  signed int v18; // edx@16
  int v19; // eax@17
  signed int v20; // ebx@18
  int v21; // edi@20
  signed int v22; // ST14_4@22
  signed __int64 v23; // qtt@22
  signed int result; // eax@25
  int v25; // [sp+14h] [bp-10h]@14
  int v26; // [sp+1Ch] [bp-8h]@2
  signed int v27; // [sp+20h] [bp-4h]@2
  signed int v28; // [sp+30h] [bp+Ch]@2
  signed int v29; // [sp+30h] [bp+Ch]@7
  signed int v30; // [sp+30h] [bp+Ch]@11
  signed int v31; // [sp+30h] [bp+Ch]@14

  v3 = _this->uAttributes;
  if ( BYTE1(v3) & 1 )
  {
    v28 = 0;
    v26 = (signed __int16)a2;
    v27 = SHIWORD(a2);
    if ( _this->uNumVertices )
    {
      v4 = pIndoor->pVertices;
      do
      {
        v5 = v28;
        v6 = 2 * v28;
        word_720C10_intercepts_xs[2 * v28] = _this->pXInterceptDisplacements[v28] + v4[_this->pVertexIDs[v28]].x;
        word_720B40_intercepts_zs[2 * v28] = _this->pYInterceptDisplacements[v5] + v4[_this->pVertexIDs[v5]].y;
        word_720C10_intercepts_xs[2 * v28++ + 1] = _this->pXInterceptDisplacements[v5 + 1]
                                                 + v4[_this->pVertexIDs[v5 + 1]].x;
        word_720B40_intercepts_zs[v6 + 1] = _this->pYInterceptDisplacements[v5 + 1] + v4[_this->pVertexIDs[v5 + 1]].y;
      }
      while ( v28 < _this->uNumVertices );
    }
  }
  else
  {
    if ( BYTE1(v3) & 2 )
    {
      v26 = (signed __int16)a2;
      v7 = a3;
      v29 = 0;
      v27 = v7;
      if ( _this->uNumVertices )
      {
        v8 = pIndoor->pVertices;
        do
        {
          v9 = v29;
          v10 = 2 * v29;
          word_720C10_intercepts_xs[2 * v29] = _this->pXInterceptDisplacements[v29] + v8[_this->pVertexIDs[v29]].x;
          word_720B40_intercepts_zs[2 * v29] = _this->pZInterceptDisplacements[v9] + v8[_this->pVertexIDs[v9]].z;
          word_720C10_intercepts_xs[2 * v29++ + 1] = _this->pXInterceptDisplacements[v9 + 1] + v8[_this->pVertexIDs[v9 + 1]].x;
          word_720B40_intercepts_zs[v10 + 1] = _this->pZInterceptDisplacements[v9 + 1] + v8[_this->pVertexIDs[v9 + 1]].z;
        }
        while ( v29 < _this->uNumVertices );
      }
    }
    else
    {
      v26 = SHIWORD(a2);
      v11 = a3;
      v30 = 0;
      v27 = v11;
      if ( _this->uNumVertices )
      {
        v12 = pIndoor->pVertices;
        do
        {
          v13 = v30;
          v14 = 2 * v30;
          word_720C10_intercepts_xs[2 * v30] = _this->pYInterceptDisplacements[v30] + v12[_this->pVertexIDs[v30]].y;
          word_720B40_intercepts_zs[2 * v30] = _this->pZInterceptDisplacements[v13] + v12[_this->pVertexIDs[v13]].z;
          word_720C10_intercepts_xs[2 * v30++ + 1] = _this->pYInterceptDisplacements[v13 + 1] + v12[_this->pVertexIDs[v13 + 1]].y;
          word_720B40_intercepts_zs[v14 + 1] = _this->pZInterceptDisplacements[v13 + 1] + v12[_this->pVertexIDs[v13 + 1]].z;
        }
        while ( v30 < _this->uNumVertices );
      }
    }
  }
  v15 = 2 * _this->uNumVertices;
  v31 = 0;
  word_720C10_intercepts_xs[2 * _this->uNumVertices] = word_720C10_intercepts_xs[0];
  word_720B40_intercepts_zs[v15] = word_720B40_intercepts_zs[0];
  v25 = 0;
  v16 = word_720B40_intercepts_zs[0] >= v27;
  if ( v15 <= 0 )
    goto LABEL_29;
  do
  {
    if ( v31 >= 2 )
      break;
    v17 = v25;
    v18 = word_720B40_intercepts_zs[v25 + 1];
    if ( v16 ^ v18 >= v27 )
    {
      v19 = word_720C10_intercepts_xs[v17 + 1];
      if ( v19 >= v26 )
        v20 = 0;
      else
        v20 = 2;
      v21 = v20 | word_720C10_intercepts_xs[v17] < v26;
      if ( v21 != 3 )
      {
        if ( !v21
          || (v22 = v19 - word_720C10_intercepts_xs[v17],
              LODWORD(v23) = v22 << 16,
              HIDWORD(v23) = v22 >> 16,
              word_720C10_intercepts_xs[v17]
            + ((signed int)(((unsigned __int64)(v23
                                              / (v18 - word_720B40_intercepts_zs[v17])
                                              * ((v27 - (signed int)word_720B40_intercepts_zs[v17]) << 16)) >> 16)
                          + 32768) >> 16) >= v26) )
          ++v31;
      }
    }
    ++v25;
    v16 = v18 >= v27;
  }
  while ( v25 < v15 );
  result = 1;
  if ( v31 != 1 )
LABEL_29:
    result = 0;
  return result;
}

//----- (004759C9) --------------------------------------------------------
bool __fastcall sub_4759C9(BLVFace *a1, int a2, int a3, __int16 a4)
{
  unsigned int v4; // eax@1
  int v5; // edx@4
  __int16 v6; // si@4
  int v7; // edx@9
  __int16 v8; // si@9
  int v9; // edx@13
  __int16 v10; // si@13
  int v11; // esi@14
  bool v12; // edi@14
  int v13; // ecx@16
  signed int v14; // edx@16
  int v15; // eax@17
  signed int v16; // ebx@18
  int v17; // edi@20
  signed int v18; // ST14_4@22
  signed __int64 v19; // qtt@22
  bool result; // eax@25
  int v21; // [sp+14h] [bp-10h]@14
  signed int v22; // [sp+18h] [bp-Ch]@1
  int v23; // [sp+1Ch] [bp-8h]@2
  signed int v24; // [sp+20h] [bp-4h]@2
  Vec3_int_ **a4a; // [sp+30h] [bp+Ch]@3
  Vec3_int_ **a4b; // [sp+30h] [bp+Ch]@8
  Vec3_int_ **a4c; // [sp+30h] [bp+Ch]@12
  signed int a4d; // [sp+30h] [bp+Ch]@14

  v4 = a1->uAttributes;
  v22 = 0;
  if ( BYTE1(v4) & 1 )
  {
    v23 = (signed __int16)a3;
    v24 = SHIWORD(a3);
    if ( a1->uNumVertices )
    {
      a4a = &pOutdoor->pBModels[a2].pVertices.pVertices;
      do
      {
        v5 = 2 * v22;
        word_720A70_intercepts_xs_plus_xs[2 * v22] = a1->pXInterceptDisplacements[v22] + LOWORD((*a4a)[a1->pVertexIDs[v22]].x);
        word_7209A0_intercepts_ys_plus_ys[2 * v22] = a1->pYInterceptDisplacements[v22] + LOWORD((*a4a)[a1->pVertexIDs[v22]].y);
        word_720A70_intercepts_xs_plus_xs[2 * v22 + 1] = a1->pXInterceptDisplacements[v22 + 1] + LOWORD((*a4a)[a1->pVertexIDs[v22 + 1]].x);
        word_7209A0_intercepts_ys_plus_ys[v5 + 1] = v6 = a1->pYInterceptDisplacements[v22 + 1] + LOWORD((*a4a)[a1->pVertexIDs[v22 + 1]].y);
        ++v22;
      }
      while ( v22 < a1->uNumVertices );
    }
  }
  else
  {
    if ( BYTE1(v4) & 2 )
    {
      v23 = (signed __int16)a3;
      v24 = a4;
      if ( a1->uNumVertices )
      {
        a4b = &pOutdoor->pBModels[a2].pVertices.pVertices;
        do
        {
          v7 = 2 * v22;
          word_720A70_intercepts_xs_plus_xs[2 * v22] = a1->pXInterceptDisplacements[v22] + LOWORD((*a4b)[a1->pVertexIDs[v22]].x);
          word_7209A0_intercepts_ys_plus_ys[2 * v22] = a1->pZInterceptDisplacements[v22] + LOWORD((*a4b)[a1->pVertexIDs[v22]].z);
          word_720A70_intercepts_xs_plus_xs[2 * v22 + 1] = a1->pXInterceptDisplacements[v22 + 1] + LOWORD((*a4b)[a1->pVertexIDs[v22 + 1]].x);
          word_7209A0_intercepts_ys_plus_ys[v7 + 1] = v8 = a1->pZInterceptDisplacements[v22 + 1] + LOWORD((*a4b)[a1->pVertexIDs[v22 + 1]].z);
          ++v22;
        }
        while ( v22 < a1->uNumVertices );
      }
    }
    else
    {
      v23 = SHIWORD(a3);
      v24 = a4;
      if ( a1->uNumVertices )
      {
        a4c = &pOutdoor->pBModels[a2].pVertices.pVertices;
        do
        {
          v9 = 2 * v22;
          word_720A70_intercepts_xs_plus_xs[2 * v22] = a1->pYInterceptDisplacements[v22] + LOWORD((*a4c)[a1->pVertexIDs[v22]].y);
          word_7209A0_intercepts_ys_plus_ys[2 * v22] = a1->pZInterceptDisplacements[v22] + LOWORD((*a4c)[a1->pVertexIDs[v22]].z);
          word_720A70_intercepts_xs_plus_xs[2 * v22 + 1] = a1->pYInterceptDisplacements[v22 + 1] + LOWORD((*a4c)[a1->pVertexIDs[v22 + 1]].y);
          word_7209A0_intercepts_ys_plus_ys[v9 + 1] = v10 = a1->pZInterceptDisplacements[v22 + 1] + LOWORD((*a4c)[a1->pVertexIDs[v22 + 1]].z);
          ++v22;
        }
        while ( v22 < a1->uNumVertices );
      }
    }
  }
  v11 = 2 * a1->uNumVertices;
  a4d = 0;
  word_720A70_intercepts_xs_plus_xs[2 * a1->uNumVertices] = word_720A70_intercepts_xs_plus_xs[0];
  word_7209A0_intercepts_ys_plus_ys[v11] = word_7209A0_intercepts_ys_plus_ys[0];
  v21 = 0;
  v12 = word_7209A0_intercepts_ys_plus_ys[0] >= v24;
  if ( v11 <= 0 )
    goto LABEL_29;
  do
  {
    if ( a4d >= 2 )
      break;
    v13 = v21;
    v14 = word_7209A0_intercepts_ys_plus_ys[v21 + 1];
    if ( v12 ^ v14 >= v24 )
    {
      v15 = word_720A70_intercepts_xs_plus_xs[v13 + 1];
      if ( v15 >= v23 )
        v16 = 0;
      else
        v16 = 2;
      v17 = v16 | word_720A70_intercepts_xs_plus_xs[v13] < v23;
      if ( v17 != 3 )
      {
        if ( !v17
          || (v18 = v15 - word_720A70_intercepts_xs_plus_xs[v13],
              LODWORD(v19) = v18 << 16,
              HIDWORD(v19) = v18 >> 16,
              word_720A70_intercepts_xs_plus_xs[v13]
            + ((signed int)(((unsigned __int64)(v19
                                              / (v14 - word_7209A0_intercepts_ys_plus_ys[v13])
                                              * ((v24 - (signed int)word_7209A0_intercepts_ys_plus_ys[v13]) << 16)) >> 16)
                          + 32768) >> 16) >= v23) )
          ++a4d;
      }
    }
    ++v21;
    v12 = v14 >= v24;
  }
  while ( v21 < v11 );
  result = 1;
  if ( a4d != 1 )
LABEL_29:
    result = 0;
  return result;
}

//----- (00475D85) --------------------------------------------------------
bool __fastcall sub_475D85(Vec3_int_ *a1, Vec3_int_ *a2, int *a3, BLVFace *a4)
{
  BLVFace *v4; // ebx@1
  int v5; // ST24_4@2
  int v6; // ST28_4@2
  int v7; // edi@2
  int v8; // eax@5
  signed int v9; // esi@5
  signed __int64 v10; // qtt@10
  Vec3_int_ *v11; // esi@11
  int v12; // ST14_4@11
  Vec3_int_ *v14; // [sp+Ch] [bp-18h]@1
  Vec3_int_ *v15; // [sp+14h] [bp-10h]@1
  int v16; // [sp+18h] [bp-Ch]@2
  int v17; // [sp+20h] [bp-4h]@10
  int a4b; // [sp+30h] [bp+Ch]@2
  int a4c; // [sp+30h] [bp+Ch]@9
  signed int a4a; // [sp+30h] [bp+Ch]@10

  v4 = a4;
  v15 = a2;
  v14 = a1;
  if ( BYTE3(a4->uAttributes) & 0x20
    || (v5 = (unsigned __int64)(a2->x * (signed __int64)a4->pFacePlane_old.vNormal.x) >> 16,
        a4b = (unsigned __int64)(a2->y * (signed __int64)a4->pFacePlane_old.vNormal.y) >> 16,
        v6 = (unsigned __int64)(a2->z * (signed __int64)v4->pFacePlane_old.vNormal.z) >> 16,
        v7 = v5 + v6 + a4b,
        (v16 = v5 + v6 + a4b) == 0)
    || v7 > 0 && !v4->Portal())
    return 0;
  v8 = v4->pFacePlane_old.vNormal.z * a1->z;
  v9 = -(v4->pFacePlane_old.dist + v8 + a1->y * v4->pFacePlane_old.vNormal.y + a1->x * v4->pFacePlane_old.vNormal.x);
  if ( v7 <= 0 )
  {
    if ( v4->pFacePlane_old.dist + v8 + a1->y * v4->pFacePlane_old.vNormal.y + a1->x * v4->pFacePlane_old.vNormal.x < 0 )
      return 0;
  }
  else
  {
    if ( v9 < 0 )
      return 0;
  }
  a4c = abs(-(v4->pFacePlane_old.dist + v8 + a1->y * v4->pFacePlane_old.vNormal.y + a1->x * v4->pFacePlane_old.vNormal.x)) >> 14;
  if ( a4c > abs(v7)
    || (LODWORD(v10) = v9 << 16, HIDWORD(v10) = v9 >> 16, a4a = v10 / v16, v17 = v10 / v16, v17 > *a3 << 16)
    || (v11 = v14,
        LOWORD(v12) = LOWORD(v14->x)
                    + (((unsigned int)((unsigned __int64)(v17 * (signed __int64)v15->x) >> 16) + 32768) >> 16),
        HIWORD(v12) = LOWORD(v11->y)
                    + (((unsigned int)((unsigned __int64)(v17 * (signed __int64)v15->y) >> 16) + 32768) >> 16),
        !sub_475665(
           v4,
           v12,
           LOWORD(v11->z) + (((unsigned int)((unsigned __int64)(v17 * (signed __int64)v15->z) >> 16) + 32768) >> 16))) )
    return 0;
  *a3 = a4a >> 16;
  return 1;
}

//----- (00475F30) --------------------------------------------------------
bool __fastcall sub_475F30(int *a1, BLVFace *a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9)
{
  BLVFace *v9; // ebx@1
  int v10; // ST20_4@2
  int v11; // ST28_4@2
  int v12; // ST24_4@2
  char v13; // zf@2
  int v14; // edi@2
  int v15; // eax@5
  signed int v16; // esi@5
  int v17; // ST20_4@9
  signed __int64 v18; // qtt@10
  int v19; // ST14_4@11
  int *v21; // [sp+14h] [bp-10h]@1
  int v22; // [sp+1Ch] [bp-8h]@2
  int v23; // [sp+1Ch] [bp-8h]@10
  signed int v24; // [sp+20h] [bp-4h]@10

  v9 = a2;
  v21 = a1;
  if ( BYTE3(a2->uAttributes) & 0x20
    || (v10 = (unsigned __int64)(a6 * (signed __int64)a2->pFacePlane_old.vNormal.x) >> 16,
        v11 = (unsigned __int64)(a7 * (signed __int64)a2->pFacePlane_old.vNormal.y) >> 16,
        v12 = (unsigned __int64)(a8 * (signed __int64)a2->pFacePlane_old.vNormal.z) >> 16,
        v13 = v10 + v12 + v11 == 0,
        v14 = v10 + v12 + v11,
        v22 = v10 + v12 + v11,
        v13)
    || v14 > 0 && !a2->Portal())
    return 0;
  v15 = a4 * a2->pFacePlane_old.vNormal.y;
  v16 = -(a2->pFacePlane_old.dist + v15 + a3 * a2->pFacePlane_old.vNormal.x + a5 * a2->pFacePlane_old.vNormal.z);
  if ( v14 <= 0 )
  {
    if ( a2->pFacePlane_old.dist + v15 + a3 * a2->pFacePlane_old.vNormal.x + a5 * a2->pFacePlane_old.vNormal.z < 0 )
      return 0;
  }
  else
  {
    if ( v16 < 0 )
      return 0;
  }
  v17 = abs(-(a2->pFacePlane_old.dist + v15 + a3 * a2->pFacePlane_old.vNormal.x + a5 * a2->pFacePlane_old.vNormal.z)) >> 14;
  if ( v17 > abs(v14)
    || (LODWORD(v18) = v16 << 16, HIDWORD(v18) = v16 >> 16, v24 = v18 / v22, v23 = v18 / v22, v23 > *v21 << 16)
    || (LOWORD(v19) = a3 + (((unsigned int)((unsigned __int64)(v23 * (signed __int64)a6) >> 16) + 32768) >> 16),
        HIWORD(v19) = a4 + (((unsigned int)((unsigned __int64)(v23 * (signed __int64)a7) >> 16) + 32768) >> 16),
        !sub_4759C9(
           v9,
           a9,
           v19,
           a5 + (((unsigned int)((unsigned __int64)(v23 * (signed __int64)a8) >> 16) + 32768) >> 16))) )
    return 0;
  *v21 = v24 >> 16;
  return 1;
}

//----- (004760D5) --------------------------------------------------------
PartyAction ActionQueue::Next()
{
  if (!uNumActions)
    return PARTY_INVALID;

  auto result = pActions[0];
  for (unsigned int i = 0; i < uNumActions - 1; ++i)
    pActions[i] = pActions[i + 1];
  --uNumActions;

  return result;
}
// 47730C: using guessed type int __stdcall const_1(int);

//----- (0047752B) --------------------------------------------------------
int __cdecl GetPartyReputation()
{
  DDM_DLV_Header *v0; // ebx@1
  signed int v1; // esi@3

  v0 = &pOutdoor->ddm;
  if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor )
    v0 = &pIndoor->dlv;
  v1 = 0;
  if ( CheckHiredNPCSpeciality(Pirate) )
    v1 += 5;
  if ( CheckHiredNPCSpeciality(Burglar) )
    v1 += 5;
  if ( CheckHiredNPCSpeciality(Gypsy) )
    v1 += 5;
  if ( CheckHiredNPCSpeciality(Duper) )
    v1 += 5;
  if ( CheckHiredNPCSpeciality(FallenWizard) )
    v1 += 5;
  return v1 + v0->uReputation;
}

//----- (004775ED) --------------------------------------------------------
int stru6_stru1_indoor_sw_billboard::_4775ED(float a2)
{
  char *v2; // edi@1
  int v3; // eax@1
  char *v4; // edx@2
  char *v5; // esi@3
  double v6; // st7@6
  signed __int64 v7; // ST84_8@6
  double v8; // ST0C_8@6
  int v9; // esi@6
  double v10; // ST44_8@6
  int v11; // ecx@6
  double v12; // ST34_8@6
  int v13; // ecx@6
  double v14; // ST14_8@6
  double v15; // st7@8
  unsigned int v16; // ecx@8
  signed __int64 v17; // ST64_8@8
  double v18; // ST24_8@8
  int v19; // edi@8
  double v20; // ST3C_8@8
  int v21; // ecx@8
  double v22; // ST2C_8@8
  int v23; // ST9C_4@8
  double v24; // ST1C_8@8
  int *v25; // edi@8
  int v26; // esi@8
  int *v27; // edi@10
  int v28; // esi@10
  int result; // eax@12
  __int64 v30; // [sp+A8h] [bp-30h]@8
  float v31; // [sp+B0h] [bp-28h]@6
  float v32; // [sp+B4h] [bp-24h]@6
  int v33; // [sp+B8h] [bp-20h]@6
  int v34; // [sp+BCh] [bp-1Ch]@2
  stru6_stru1_indoor_sw_billboard *v35; // [sp+C0h] [bp-18h]@1
  float v36; // [sp+C4h] [bp-14h]@6
  int v37; // [sp+C8h] [bp-10h]@6
  int v38; // [sp+CCh] [bp-Ch]@1
  float v39; // [sp+D0h] [bp-8h]@6
  int *v40; // [sp+D4h] [bp-4h]@2

  v2 = (char *)&this->field_14[4 * this->field_10 + 20];
  v38 = 0;
  *(int *)v2 = this->field_14[20];
  v2 += 4;
  *(int *)v2 = this->field_14[21];
  v2 += 4;
  *(int *)v2 = this->field_14[22];
  *((int *)v2 + 1) = this->field_14[23];
  v3 = this->field_10;
  v35 = this;
  if ( v3 > 0 )
  {
    v40 = &this->field_14[40];
    v4 = (char *)&this->field_14[23] + 3;
    v34 = v3;
    while ( 1 )
    {
      v5 = v4 - 15;
      if ( *(float *)(v4 - 15) <= (double)a2 && *(float *)(v4 + 1) <= (double)a2 )
        goto LABEL_11;
      if ( *(float *)v5 <= (double)a2 )
        break;
      if ( *(float *)(v4 + 1) <= (double)a2 )
      {
        v15 = (a2 - *(float *)v5) / (*(float *)(v4 + 1) - *(float *)v5);
        v16 = (unsigned __int8)*v4;
        HIDWORD(v30) = LODWORD(a2);
        v17 = (unsigned __int8)v4[16] - v16;
        v36 = v15;
        v31 = (*(float *)(v4 + 5) - *(float *)(v4 - 11)) * v15 + *(float *)(v4 - 11);
        v32 = (*(float *)(v4 + 9) - *(float *)(v4 - 7)) * v15 + *(float *)(v4 - 7);
        v39 = (double)v17 * v15;
        v18 = v39 + 6.7553994e15;
        v19 = (unsigned __int8)*v4;
        v39 = (double)((unsigned __int8)v4[15] - (unsigned int)(unsigned __int8)*(v4 - 1)) * v36;
        v20 = v39 + 6.7553994e15;
        v21 = (unsigned __int8)*(v4 - 2);
        v37 = LODWORD(v20) + (unsigned __int8)*(v4 - 1);
        v39 = (double)((unsigned int)(unsigned __int8)v4[14] - v21) * v36;
        v22 = v39 + 6.7553994e15;
        v23 = LODWORD(v22) + (unsigned __int8)*(v4 - 2);
        v39 = (double)((*(int *)(v4 + 13) & 0xFF) - (*(int *)(v4 - 3) & 0xFFu)) * v36;
        v24 = v39 + 6.7553994e15;
        v33 = (LODWORD(v24) + (*(int *)(v4 - 3) & 0xFF)) | ((v23 | ((v37 | ((LODWORD(v18) + v19) << 8)) << 8)) << 8);
        v25 = v40;
        *v40 = *(int *)v5;
        v26 = (int)(v5 + 4);
        ++v25;
        *v25 = *(int *)v26;
        v26 += 4;
        ++v25;
        ++v38;
        v40 += 4;
        *v25 = *(int *)v26;
        v25[1] = *(int *)(v26 + 4);
        goto LABEL_9;
      }
LABEL_10:
      v27 = v40;
      ++v38;
      *v40 = *(int *)v5;
      v28 = (int)(v5 + 4);
      ++v27;
      *v27 = *(int *)v28;
      v28 += 4;
      ++v27;
      v40 += 4;
      *v27 = *(int *)v28;
      v27[1] = *(int *)(v28 + 4);
LABEL_11:
      v4 += 16;
      --v34;
      if ( !v34 )
        goto LABEL_12;
    }
    v6 = (a2 - *(float *)v5) / (*(float *)(v4 + 1) - *(float *)v5);
    v7 = (unsigned __int8)v4[16] - (unsigned int)(unsigned __int8)*v4;
    v36 = v6;
    v31 = (*(float *)(v4 + 5) - *(float *)(v4 - 11)) * v6 + *(float *)(v4 - 11);
    v32 = (*(float *)(v4 + 9) - *(float *)(v4 - 7)) * v6 + *(float *)(v4 - 7);
    *(float *)&v37 = (double)v7 * v6;
    v8 = *(float *)&v37 + 6.7553994e15;
    v9 = (unsigned __int8)*v4;
    *(float *)&v37 = (double)((unsigned __int8)v4[15] - (unsigned int)(unsigned __int8)*(v4 - 1)) * v36;
    v10 = *(float *)&v37 + 6.7553994e15;
    v11 = (unsigned __int8)*(v4 - 2);
    v37 = LODWORD(v10) + (unsigned __int8)*(v4 - 1);
    v39 = (double)((unsigned int)(unsigned __int8)v4[14] - v11) * v36;
    v12 = v39 + 6.7553994e15;
    v13 = LODWORD(v12) + (unsigned __int8)*(v4 - 2);
    v39 = (double)((*(int *)(v4 + 13) & 0xFF) - (*(int *)(v4 - 3) & 0xFFu)) * v36;
    v14 = v39 + 6.7553994e15;
    v33 = (LODWORD(v14) + (*(int *)(v4 - 3) & 0xFF)) | ((v13 | ((v37 | ((LODWORD(v8) + v9) << 8)) << 8)) << 8);
LABEL_9:
    //this = v35;
    v5 = (char *)&v30 + 4;
    goto LABEL_10;
  }
LABEL_12:
  result = v38;
  this->field_10 = v38;
  return result;
}

//----- (00477927) --------------------------------------------------------
int stru6_stru1_indoor_sw_billboard::_477927(float a2)
{
  char *v2; // edi@1
  int v3; // eax@1
  char *v4; // edx@2
  char *v5; // esi@3
  double v6; // st7@6
  signed __int64 v7; // ST84_8@6
  double v8; // ST0C_8@6
  int v9; // esi@6
  double v10; // ST44_8@6
  int v11; // ecx@6
  double v12; // ST34_8@6
  int v13; // ecx@6
  double v14; // ST14_8@6
  double v15; // st7@8
  unsigned int v16; // ecx@8
  signed __int64 v17; // ST64_8@8
  double v18; // ST24_8@8
  int v19; // edi@8
  double v20; // ST3C_8@8
  int v21; // ecx@8
  double v22; // ST2C_8@8
  int v23; // ST9C_4@8
  double v24; // ST1C_8@8
  int *v25; // edi@8
  int v26; // esi@8
  int *v27; // edi@10
  int v28; // esi@10
  int result; // eax@12
  __int64 v30; // [sp+A8h] [bp-30h]@8
  float v31; // [sp+B0h] [bp-28h]@6
  float v32; // [sp+B4h] [bp-24h]@6
  int v33; // [sp+B8h] [bp-20h]@6
  int v34; // [sp+BCh] [bp-1Ch]@2
  stru6_stru1_indoor_sw_billboard *v35; // [sp+C0h] [bp-18h]@1
  float v36; // [sp+C4h] [bp-14h]@6
  int v37; // [sp+C8h] [bp-10h]@6
  int v38; // [sp+CCh] [bp-Ch]@1
  float v39; // [sp+D0h] [bp-8h]@6
  int *v40; // [sp+D4h] [bp-4h]@2

  v2 = (char *)&this->field_14[4 * this->field_10 + 20];
  v38 = 0;
  *(int *)v2 = this->field_14[20];
  v2 += 4;
  *(int *)v2 = this->field_14[21];
  v2 += 4;
  *(int *)v2 = this->field_14[22];
  *((int *)v2 + 1) = this->field_14[23];
  v3 = this->field_10;
  v35 = this;
  if ( v3 > 0 )
  {
    v40 = &this->field_14[40];
    v4 = (char *)&this->field_14[23] + 3;
    v34 = v3;
    while ( 1 )
    {
      v5 = v4 - 15;
      if ( *(float *)(v4 - 15) >= (double)a2 && *(float *)(v4 + 1) >= (double)a2 )
        goto LABEL_11;
      if ( *(float *)v5 >= (double)a2 )
        break;
      if ( *(float *)(v4 + 1) >= (double)a2 )
      {
        v15 = (a2 - *(float *)v5) / (*(float *)(v4 + 1) - *(float *)v5);
        v16 = (unsigned __int8)*v4;
        HIDWORD(v30) = LODWORD(a2);
        v17 = (unsigned __int8)v4[16] - v16;
        v36 = v15;
        v31 = (*(float *)(v4 + 5) - *(float *)(v4 - 11)) * v15 + *(float *)(v4 - 11);
        v32 = (*(float *)(v4 + 9) - *(float *)(v4 - 7)) * v15 + *(float *)(v4 - 7);
        v39 = (double)v17 * v15;
        v18 = v39 + 6.7553994e15;
        v19 = (unsigned __int8)*v4;
        v39 = (double)((unsigned __int8)v4[15] - (unsigned int)(unsigned __int8)*(v4 - 1)) * v36;
        v20 = v39 + 6.7553994e15;
        v21 = (unsigned __int8)*(v4 - 2);
        v37 = LODWORD(v20) + (unsigned __int8)*(v4 - 1);
        v39 = (double)((unsigned int)(unsigned __int8)v4[14] - v21) * v36;
        v22 = v39 + 6.7553994e15;
        v23 = LODWORD(v22) + (unsigned __int8)*(v4 - 2);
        v39 = (double)((*(int *)(v4 + 13) & 0xFF) - (*(int *)(v4 - 3) & 0xFFu)) * v36;
        v24 = v39 + 6.7553994e15;
        v33 = (LODWORD(v24) + (*(int *)(v4 - 3) & 0xFF)) | ((v23 | ((v37 | ((LODWORD(v18) + v19) << 8)) << 8)) << 8);
        v25 = v40;
        *v40 = *(int *)v5;
        v26 = (int)(v5 + 4);
        ++v25;
        *v25 = *(int *)v26;
        v26 += 4;
        ++v25;
        ++v38;
        v40 += 4;
        *v25 = *(int *)v26;
        v25[1] = *(int *)(v26 + 4);
        goto LABEL_9;
      }
LABEL_10:
      v27 = v40;
      ++v38;
      *v40 = *(int *)v5;
      v28 = (int)(v5 + 4);
      ++v27;
      *v27 = *(int *)v28;
      v28 += 4;
      ++v27;
      v40 += 4;
      *v27 = *(int *)v28;
      v27[1] = *(int *)(v28 + 4);
LABEL_11:
      v4 += 16;
      --v34;
      if ( !v34 )
        goto LABEL_12;
    }
    v6 = (a2 - *(float *)v5) / (*(float *)(v4 + 1) - *(float *)v5);
    v7 = (unsigned __int8)v4[16] - (unsigned int)(unsigned __int8)*v4;
    v36 = v6;
    v31 = (*(float *)(v4 + 5) - *(float *)(v4 - 11)) * v6 + *(float *)(v4 - 11);
    v32 = (*(float *)(v4 + 9) - *(float *)(v4 - 7)) * v6 + *(float *)(v4 - 7);
    *(float *)&v37 = (double)v7 * v6;
    v8 = *(float *)&v37 + 6.7553994e15;
    v9 = (unsigned __int8)*v4;
    *(float *)&v37 = (double)((unsigned __int8)v4[15] - (unsigned int)(unsigned __int8)*(v4 - 1)) * v36;
    v10 = *(float *)&v37 + 6.7553994e15;
    v11 = (unsigned __int8)*(v4 - 2);
    v37 = LODWORD(v10) + (unsigned __int8)*(v4 - 1);
    v39 = (double)((unsigned int)(unsigned __int8)v4[14] - v11) * v36;
    v12 = v39 + 6.7553994e15;
    v13 = LODWORD(v12) + (unsigned __int8)*(v4 - 2);
    v39 = (double)((*(int *)(v4 + 13) & 0xFF) - (*(int *)(v4 - 3) & 0xFFu)) * v36;
    v14 = v39 + 6.7553994e15;
    v33 = (LODWORD(v14) + (*(int *)(v4 - 3) & 0xFF)) | ((v13 | ((v37 | ((LODWORD(v8) + v9) << 8)) << 8)) << 8);
LABEL_9:
    //this = v35;
    v5 = (char *)&v30 + 4;
    goto LABEL_10;
  }
LABEL_12:
  result = v38;
  this->field_10 = v38;
  return result;
}

//----- (00477C61) --------------------------------------------------------
int stru6_stru1_indoor_sw_billboard::sub_477C61()
{
  stru6_stru1_indoor_sw_billboard *v1; // ebx@1
  int v2; // ecx@2
  int v3; // eax@3
  double v4; // st7@4
  double v5; // st7@5
  double v6; // st6@5
  double v7; // st5@6
  float v8; // ST30_4@8
  float v9; // ST24_4@8
  double v10; // st7@8
  double v11; // st6@8
  double v12; // st5@8
  float v13; // ST24_4@13
  int v14; // esi@13
  char *v15; // esi@15
  signed int v16; // eax@16
  __int16 v17; // fps@16
  unsigned __int8 v18; // c2@16
  unsigned __int8 v19; // c3@16
  double v20; // st6@16
  float v21; // ST18_4@17
  float v22; // ST2C_4@17
  float v23; // ST34_4@17
  float v24; // ST24_4@17
  double v25; // st7@17
  double v26; // st6@17
  float v27; // ST34_4@18
  float v28; // ST30_4@18
  int v29; // eax@19
  signed int v31; // [sp+8h] [bp-28h]@15
  float v32; // [sp+Ch] [bp-24h]@16
  float v33; // [sp+14h] [bp-1Ch]@16
  float v34; // [sp+18h] [bp-18h]@16
  float v35; // [sp+1Ch] [bp-14h]@17
  float v36; // [sp+20h] [bp-10h]@4
  float v37; // [sp+24h] [bp-Ch]@4
  float v38; // [sp+24h] [bp-Ch]@16
  float v39; // [sp+28h] [bp-8h]@9
  float v40; // [sp+28h] [bp-8h]@16
  float v41; // [sp+2Ch] [bp-4h]@6
  float v42; // [sp+2Ch] [bp-4h]@9

  v1 = this;
  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
  {
    v2 = 0;
    if ( v1->field_10 > 0 )
    {
      v3 = (int)&v1->field_14[1];
      do
      {
        v4 = *(float *)(v3 - 4);
        LODWORD(v37) = *(int *)v3;
        LODWORD(v36) = *(int *)(v3 + 4);
        if ( pBLVRenderParams->sPartyRotX )
        {
          v5 = v4 - (double)pBLVRenderParams->vPartyPos.x;
          v6 = v37 - (double)pBLVRenderParams->vPartyPos.y;
          if ( pRenderer->pRenderD3D )
          {
            v41 = pBLVRenderParams->fSineY * v6 + pBLVRenderParams->fCosineY * v5;
            v7 = pBLVRenderParams->fSineY * v5 - pBLVRenderParams->fCosineY * v6;
          }
          else
          {
            v41 = pBLVRenderParams->fCosineY * v5 - pBLVRenderParams->fSineY * v6;
            v7 = pBLVRenderParams->fSineY * v5 + pBLVRenderParams->fCosineY * v6;
          }
          v8 = v7;
          v9 = v36 - (double)pBLVRenderParams->vPartyPos.z;
          v10 = pBLVRenderParams->fCosineNegX * v41 - pBLVRenderParams->fSineNegX * v9;
          v11 = v8;
          v12 = pBLVRenderParams->fCosineNegX * v9 + pBLVRenderParams->fSineNegX * v41;
        }
        else
        {
          v42 = v4 - (double)pBLVRenderParams->vPartyPos.x;
          v39 = v37 - (double)pBLVRenderParams->vPartyPos.y;
          if ( pRenderer->pRenderD3D )
          {
            v10 = pBLVRenderParams->fSineY * v39 + pBLVRenderParams->fCosineY * v42;
            v11 = pBLVRenderParams->fSineY * v42 - pBLVRenderParams->fCosineY * v39;
          }
          else
          {
            v10 = pBLVRenderParams->fCosineY * v42 - pBLVRenderParams->fSineY * v39;
            v11 = pBLVRenderParams->fSineY * v42 + pBLVRenderParams->fCosineY * v39;
          }
          v12 = v36 - (double)pBLVRenderParams->vPartyPos.z;
        }
        v13 = v12;
        ++v2;
        *(int *)(v3 + 84) = LODWORD(v13);
        v14 = *(int *)(v3 + 8);
        *(float *)(v3 + 76) = v10;
        *(int *)(v3 + 88) = v14;
        *(float *)(v3 + 80) = v11;
        v3 += 16;
      }
      while ( v2 < v1->field_10 );
    }
  }
  else
  {
    v15 = (char *)&this->field_14[1];
    v31 = 3;
    do
    {
      v40 = (double)stru_5C6E00->Cos(pIndoorCamera->sRotationX) * 0.0000152587890625;
      v32 = (double)stru_5C6E00->Sin(pIndoorCamera->sRotationX) * 0.0000152587890625;
      v34 = (double)stru_5C6E00->Cos(pIndoorCamera->sRotationY) * 0.0000152587890625;
      v16 = stru_5C6E00->Sin(pIndoorCamera->sRotationY);
      LODWORD(v38) = *(int *)v15;
      v33 = (double)v16 * 0.0000152587890625;
      //UNDEF(v17);
      v20 = *((float *)v15 - 1) - (double)pIndoorCamera->pos.x;
      if ( v19 | v18 )
      {
        v27 = v20;
        LODWORD(v35) = *((int *)v15 + 1);
        v28 = v38 - (double)pIndoorCamera->pos.y;
        v25 = v33 * v28 + v34 * v27;
        v26 = v34 * v28 - v33 * v27;
      }
      else
      {
        v21 = v20;
        v22 = v38 - (double)pIndoorCamera->pos.y;
        v23 = v33 * v22 + v34 * v21;
        v24 = *((float *)v15 + 1) - (double)pIndoorCamera->pos.z;
        v25 = v32 * v24 + v40 * v23;
        v26 = v34 * v22 - v33 * v21;
        v35 = v40 * v24 - v32 * v23;
      }
      *((int *)v15 + 21) = LODWORD(v35);
      v29 = *((int *)v15 + 2);
      *((float *)v15 + 19) = v25;
      *((int *)v15 + 22) = v29;
      *((float *)v15 + 20) = v26;
      v15 += 16;
      --v31;
    }
    while ( v31 );
  }
  v1->field_10 = 3;
  return 1;
}

//----- (00477F63) --------------------------------------------------------
bool stru6_stru1_indoor_sw_billboard::sub_477F63()
{
  signed int v1; // ebx@1
  stru6_stru1_indoor_sw_billboard *v2; // esi@1
  double v3; // st7@2
  int v4; // edx@4
  char *v5; // ecx@5
  int v6; // edi@5
  float v7; // ST08_4@13
  signed int v9; // [sp+Ch] [bp-8h]@1
  float v10; // [sp+10h] [bp-4h]@2

  auto a1 = this;

  v1 = 0;
  v2 = a1;
  v9 = 0;
  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
  {
    v10 = 16192.0;
    v3 = (double)pBLVRenderParams->field_40 * 0.000015258789;
  }
  else
  {
    v10 = (double)pOutdoorCamera->shading_dist_mist;
    v3 = 8.0;
  }
  v4 = a1->field_10;
  if ( v4 <= 0 )
    goto LABEL_16;
  v5 = (char *)&a1->field_14[20];
  v6 = v4;
  do
  {
    if ( v3 >= *(float *)v5 || *(float *)v5 >= (double)v10 )
    {
      if ( v3 < *(float *)v5 )
        v9 = 1;
      else
        v1 = 1;
    }
    v5 += 16;
    --v6;
  }
  while ( v6 );
  if ( !v1 )
  {
    if ( v9 )
    {
      v2->_477927(v10);
      return v2->field_10 != 0;
    }
LABEL_16:
    memcpy(&v2->field_14[40], &v2->field_14[20], 16 * v4);
    return v2->field_10 != 0;
  }
  v7 = v3;
  _4775ED(v7);
  return v2->field_10 != 0;
}

//----- (0047802A) --------------------------------------------------------
int stru6_stru1_indoor_sw_billboard::sub_47802A()
{
  int v1; // edx@1
  stru6_stru1_indoor_sw_billboard *v2; // edi@1
  int v3; // ebx@2
  char *v4; // esi@3
  float v5; // eax@4
  double v6; // st7@4
  double v7; // ST30_8@5
  double v8; // st6@6
  double v9; // st5@6
  char *v10; // ecx@15
  float v11; // eax@16
  double v12; // st7@16
  double v13; // st6@16
  double v14; // st5@16
  signed int v16; // [sp+38h] [bp-Ch]@1
  int a6; // [sp+3Ch] [bp-8h]@5
  int a5; // [sp+40h] [bp-4h]@5

  auto a1 = this;

  v1 = 0;
  v2 = a1;
  v16 = 0;
  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
  {
    v3 = 0;
    if ( a1->field_10 > 0 )
    {
      v4 = (char *)&a1->field_14[42];
      do
      {
        LODWORD(v5) = *((int *)v4 - 2);
        v6 = (double)pBLVRenderParams->field_40 * 0.000015258789 / *((float *)v4 - 2);
        if ( pRenderer->pRenderD3D )
        {
          v7 = v5 + 6.7553994e15;
          pGame->pIndoorCameraD3D->Project(
            COERCE_UNSIGNED_INT64(v5 + 6.7553994e15),
            COERCE_UNSIGNED_INT64(*((float *)v4 - 1) + 6.7553994e15),
            COERCE_UNSIGNED_INT64(*(float *)v4 + 6.7553994e15),
            &a5,
            &a6);
          *((float *)v4 + 18) = (double)a5;
          *((float *)v4 + 19) = (double)a6;
          *((float *)v4 + 20) = (double)SLODWORD(v7);
        }
        else
        {
          *((float *)v4 + 18) = (double)pBLVRenderParams->uViewportCenterX - v6 * *((float *)v4 - 1);
          v8 = (double)pBLVRenderParams->uViewportCenterY;
          v9 = v6 * *(float *)v4;
          *((int *)v4 + 20) = LODWORD(v5);
          *((float *)v4 + 19) = v8 - v9;
        }
        *((int *)v4 + 21) = *((int *)v4 + 1);
        if ( (double)(signed int)pViewport->uViewportTL_X <= *((float *)v4 + 18)
          && (double)(signed int)pViewport->uViewportBR_X > *((float *)v4 + 18)
          && (double)(signed int)pViewport->uViewportTL_Y <= *((float *)v4 + 19)
          && (double)(signed int)pViewport->uViewportBR_Y > *((float *)v4 + 19) )
          v16 = 1;
        ++v3;
        v4 += 16;
      }
      while ( v3 < v2->field_10 );
    }
  }
  else
  {
    if ( a1->field_10 > 0 )
    {
      v10 = (char *)&a1->field_14[40];
      do
      {
        LODWORD(v11) = *(int *)v10;
        v12 = (double)pOutdoorCamera->int_fov_rad / *(float *)v10;
        *((float *)v10 + 20) = (double)pViewport->uScreenCenterX - v12 * *((float *)v10 + 1);
        v13 = (double)pViewport->uScreenCenterY;
        v14 = v12 * *((float *)v10 + 2);
        *((int *)v10 + 22) = LODWORD(v11);
        *((int *)v10 + 23) = *((int *)v10 + 3);
        *((float *)v10 + 21) = v13 - v14;
        if ( (double)(signed int)pViewport->uViewportTL_X <= *((float *)v10 + 20)
          && (double)(signed int)pViewport->uViewportBR_X > *((float *)v10 + 20)
          && (double)(signed int)pViewport->uViewportTL_Y <= *((float *)v10 + 21)
          && (double)(signed int)pViewport->uViewportBR_Y > *((float *)v10 + 21) )
          v16 = 1;
        ++v1;
        v10 += 16;
      }
      while ( v1 < v2->field_10 );
    }
  }
  return v16;
}

//----- (004783FA) --------------------------------------------------------
void __cdecl sub_4783FA_construct_global_73D150()
{
  char *v0; // eax@1
  signed int v1; // ecx@1

  v0 = (char *)&array_73D150[0].flt_2C;
  v1 = 20;
  do
  {
    *(float *)v0 = 0.0;
    v0 += 48;
    --v1;
  }
  while ( v1 );
}

//----- (0047840D) --------------------------------------------------------
char Render::DrawBuildingsD3D()
{
  IndoorCameraD3D *v0; // eax@3
  char result; // al@3
  BSPModel *v2; // ebx@4
  int v3; // eax@6
  ODMFace *pFace; // esi@6
  Vec3_int_ *v5; // ecx@8
  int v6; // eax@8
  stru148 *v7; // ebx@8
  LightmapBuilder *v8; // eax@8
  int v9; // ecx@8
  char v10; // zf@8
  Texture *pFaceTexture; // eax@10
  signed int v12; // ecx@10
  unsigned int v13; // eax@14
  unsigned int v14; // eax@18
  unsigned int v15; // eax@22
  unsigned int v16; // edi@22
  int v17; // eax@24
  int v18; // edi@34
  RenderVertexSoft *v19; // eax@35
  unsigned short *v20; // ecx@35
  unsigned short *v20b; // ecx@35
  unsigned short *v20c; // ecx@35
  Vec3_int_ *v21; // edx@36
  int v22; // edx@36
  RenderVertexSoft *v23; // edi@37
  int v24; // eax@50
  int v25; // ecx@55
  int v26; // eax@57
  int v27; // eax@57
  int v28; // eax@58
  int v29; // edx@58
  double v30; // st7@59
  LightmapBuilder *v31; // edi@63
  signed int v32; // eax@73
  int v33; // eax@78
  unsigned int v34; // eax@80
  std::string v35; // [sp-18h] [bp-70h]@2
  int v36; // [sp-14h] [bp-6Ch]@69
  RenderVertexSoft *v37; // [sp-10h] [bp-68h]@69
  int v38; // [sp-Ch] [bp-64h]@69
  LightmapBuilder *v39; // [sp-8h] [bp-60h]@2
  int v40; // [sp-4h] [bp-5Ch]@2
  std::string *v41; // [sp+Ch] [bp-4Ch]@2
  int v41b;
  int v42; // [sp+10h] [bp-48h]@6
  LightmapBuilder *pLightmapBuilder; // [sp+14h] [bp-44h]@8
  float v44; // [sp+18h] [bp-40h]@10
  float v45; // [sp+1Ch] [bp-3Ch]@10
  ODMFace *v46; // [sp+20h] [bp-38h]@6
  IndoorCameraD3D *v47; // [sp+24h] [bp-34h]@3
  unsigned int v48; // [sp+28h] [bp-30h]@8
  int v49; // [sp+2Ch] [bp-2Ch]@10
  int v50; // [sp+30h] [bp-28h]@34
  int v51; // [sp+34h] [bp-24h]@35
  int v52; // [sp+38h] [bp-20h]@36
  int v53; // [sp+3Ch] [bp-1Ch]@8
  Vec3_int_ *v54; // [sp+40h] [bp-18h]@6
  int a1; // [sp+44h] [bp-14h]@3
  BSPModel *v56; // [sp+48h] [bp-10h]@4
  int uNumVertices; // [sp+4Ch] [bp-Ch]@34
  int unused; // [sp+50h] [bp-8h]@3
  int a3; // [sp+57h] [bp-1h]@2

  if ( !pRenderer->pRenderD3D )
  {
          MessageBoxW(nullptr, L"D3D version of RenderBuildings called in software!", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Odbuild.cpp:73", 0);
  }
  unused = 0;
  v0 = pGame->pIndoorCameraD3D;
  a1 = 0;
  v47 = v0;
  result = LOBYTE(pOutdoor->pBModels);
  v41b = pOutdoor->uNumBModels;
  if ( (signed int)pOutdoor->uNumBModels > 0 )
  {
    v2 = pOutdoor->pBModels;
    v56 = pOutdoor->pBModels;
    while ( 1 )
    {
      if ( IsBModelVisible(a1, &unused) )
      {
		v2->field_40 |= 1u;
        v3 = v2->uNumFaces;
        pFace = v2->pFaces;
        v54 = 0;
        v46 = pFace;
        v42 = v3;
        if ( v3 > 0 )
          break;
      }
LABEL_86:
      ++a1;
      ++v2;// += 47;
      result = a1;
      v56 = v2;
      if ( a1 >= v41b )
        return result;
    }
    while ( 1 )
    {
      if (pFace->Invisible())
        goto LABEL_85;
      //v5 = (int)*(v2 - 1);
	  v5 = v2->pVertices.pVertices;
      v6 = pFace->pVertexIDs[0];
      v53 = 0;
      v7 = &array_77EC08[pOutdoorCamera->numStru148s];
	  //v8 = *(LightmapBuilder **)(v5 + 12 * v6 + 8);
      v8 = (LightmapBuilder *)v5[v6].z;
      *(int *)&v7->flags = 0;
      pLightmapBuilder = v8;
      v9 = pFace->uTextureID;
      v10 = (BYTE1(pFace->uAttributes) & 0x40) == 0;
      v48 = pFace->uTextureID;
      if ( !v10 )
      {
        v48 = pTextureFrameTable->GetFrameTexture(v9, pEventTimer->uTotalGameTimeElapsed);
        v9 = v48;
      }
      pFaceTexture = (Texture *)(v9 != -1 ? (int)&pBitmaps_LOD->pTextures[v9] : 0);
      v7->pTexture = pFaceTexture;
      v12 = (v9 != -1 ? pBitmaps_LOD->pTextures[v9].uTextureWidth : 24);
      v49 = v12;
      v49 = pFaceTexture->uTextureHeight;
      v10 = (pFace->uAttributes & 0x10) == 0;
      v45 = 1.0 / (double)v12;
      v44 = 1.0 / (double)v49;
      if ( !v10 )
        *(int *)&v7->flags |= 2u;
      if ( BYTE2(pFace->uAttributes) & 0x40 )
        HIBYTE(v7->flags) |= 4u;
      v13 = pFace->uAttributes;
      if ( v13 & 4 )
      {
        HIBYTE(v7->flags) |= 4u;
      }
      else
      {
        if ( v13 & 0x20 )
          HIBYTE(v7->flags) |= 8u;
      }
      v14 = pFace->uAttributes;
      if ( BYTE1(v14) & 8 )
      {
        *(int *)&v7->flags |= 0x2000u;
      }
      else
      {
        if ( v14 & 0x40 )
          HIBYTE(v7->flags) |= 0x10u;
      }
      v15 = GetTickCount();
      v7->sTextureDeltaU = pFace->sTextureDeltaU;
      v7->sTextureDeltaV = pFace->sTextureDeltaV;
      v16 = v15 >> 4;
      if ( pFace->pFacePlane.vNormal.z && (v40 = pFace->pFacePlane.vNormal.z, abs(v40) >= 59082) )
      {
        v17 = *(int *)&v7->flags;
        if ( BYTE1(v17) & 4 )
          goto LABEL_29;
        if ( BYTE1(v17) & 8 )
        {
LABEL_26:
          v7->sTextureDeltaV -= v16 & v7->pTexture->uHeightMinus1;
          goto LABEL_30;
        }
      }
      else
      {
        v17 = *(int *)&v7->flags;
        if ( BYTE1(v17) & 4 )
          goto LABEL_26;
        if ( BYTE1(v17) & 8 )
        {
LABEL_29:
          v7->sTextureDeltaV += v16 & v7->pTexture->uHeightMinus1;
          goto LABEL_30;
        }
      }
LABEL_30:
      if ( BYTE1(v17) & 0x10 )
      {
        v7->sTextureDeltaU -= v16 & v7->pTexture->uWidthMinus1;
      }
      else
      {
        if ( BYTE1(v17) & 0x20 )
          v7->sTextureDeltaU += v16 & v7->pTexture->uWidthMinus1;
      }
      v18 = pFace->uNumVertices;
      v50 = 0;
      v49 = 0;
      uNumVertices = v18;
      if ( v18 > 0 )
      {
        //v19 = (char *)&array_73D150[0].vWorldPosition.z;
        //v20 = (char *)pFace->pTextureUIDs;
		v19 = array_73D150;
        v20 = pFace->pTextureUIDs;
		v20b = pFace->pVertexIDs;
		v20c = pFace->pTextureVIDs;
        v51 = v18;
        do
        {
/*          v21 = &(*(v56 - 1))[*((short *)v20 - 20)];
          *((float *)v19 - 2) = (double)v21->x;
          *((float *)v19 - 1) = (double)v21->y;
          *(float *)v19 = (double)v21->z;
          v19 += 48;
          v52 = v7->sTextureDeltaU + *(short *)v20;
          *((float *)v19 - 5) = (double)v52 * v45;
          v22 = v7->sTextureDeltaV + *((short *)v20 + 20);
          v20 += 2;
          v10 = v51-- == 1;
          v52 = v22;
          *((float *)v19 - 4) = (double)v22 * v44;*/
          
		  //v21 = (BSPVertexBuffer *)(*((_DWORD *)v56 - 1) + 12 * *(v20 - 20));
		  v21 = &v56->pVertices.pVertices[*v20b];
          //*((float *)v19 - 2) = (double)v21->x;
          //*((float *)v19 - 1) = (double)v21->y;
		  v19->vWorldPosition.x = (double)v21->x;
		  v19->vWorldPosition.y = (double)v21->y;
          v19->vWorldPosition.z = (double)v21->z;
          ++v19;
          v52 = v7->sTextureDeltaU + (signed __int16)*v20;
          //*((float *)v19 - 5) = (double)v52 * v45;
		  (v19-1)->u = (double)v52 * v45;
          v22 = v7->sTextureDeltaV + (signed __int16)*v20c;
          ++v20;
		  ++v20b;
		  ++v20c;
          v10 = v51-- == 1;
          v52 = v22;
          //*((float *)v19 - 4) = (double)v22 * v44;
		  (v19-1)->v = (double)v22 * v44;
        }
        while ( !v10 );
        //v23 = (char *)&array_73D150[0].vWorldViewPosition;
		v23 = array_73D150;
        v51 = uNumVertices;
        *(float *)&pLightmapBuilder = (double)(signed int)pLightmapBuilder;
        do
        {
          //if ( *(float *)&pLightmapBuilder == *((float *)v23 - 1) )
		  if ( *(float *)&pLightmapBuilder == v23->vWorldPosition.z )
            ++v53;
          //v47->ViewTransform((RenderVertexSoft *)(v23 - 12), 1u);
		  v47->ViewTransform(v23, 1u);
		  if ( v23->vWorldViewPosition.x < 8.0 || (double)pOutdoorCamera->shading_dist_mist < v23->vWorldViewPosition.x )
          {
            if ( v23->vWorldViewPosition.x >= 8.0 )
              v49 = 1;
            else
              v50 = 1;
          }
          else
          {
            v47->Project(v23, 1u, 0);
          }
          ++v23;// += 48;
          --v51;
        }
        while ( v51 );
        v18 = uNumVertices;
      }
      if ( v53 == v18 )
        LOBYTE(v7->field_32) |= 1u;
      v24 = pOutdoor->vSunlight.x;
      v7->pODMFace = pFace;
      v7->uNumVertices = v18;
      v7->field_59 = 5;
      pLightmapBuilder = (LightmapBuilder *)-v24;
      v51 = pFace->pFacePlane.vNormal.x;
      v51 = (unsigned __int64)(-v24 * (signed __int64)v51) >> 16;
      v53 = pFace->pFacePlane.vNormal.y;
      pLightmapBuilder = (LightmapBuilder *)-pOutdoor->vSunlight.y;
      v53 = (unsigned __int64)(-pOutdoor->vSunlight.y * (signed __int64)v53) >> 16;
      v52 = pFace->pFacePlane.vNormal.z;
      v52 = (unsigned __int64)(-pOutdoor->vSunlight.z * (signed __int64)v52) >> 16;
      pLightmapBuilder = (LightmapBuilder *)(v51 + v53 + v52);
      v51 = 20 * (int)pLightmapBuilder;
      result = 20 - (20 * (signed int)pLightmapBuilder >> 16);
      v7->dimming_level = result;
      if ( result < 0 )
        v7->dimming_level = 0;
      if ( v7->dimming_level > 31 )
        v7->dimming_level = 31;
      if ( pOutdoorCamera->numStru148s >= 1999 + 5000)
        return result;
      ++pOutdoorCamera->numStru148s;
      ++pOutdoorCamera->field_44;
      if ( ODMFace::IsBackfaceCulled(pFace, array_73D150, v7) )
      {
        LOBYTE(v25) = (char)v54;
        v26 = a1;
        pFace->bVisible = 1;
        v7->uBModelFaceID = v25;
        LOWORD(v25) = (unsigned __int8)v25;
        v7->uBModelID = v26;
        v27 = 8 * (v25 | (v26 << 6));
        LOBYTE(v27) = v27 | 6;
        v7->field_50 = v27;
        if ( v18 > 0 )
        {
          v28 = 0;
          v29 = v18;
          do
          {
            v30 = 1.0 / (array_73D150[v28].vWorldViewPosition.x + 0.0000001);
            memcpy(&array_50AC10[v28], &array_73D150[v28], sizeof(array_50AC10[v28]));
            ++v28;
            --v29;
            array_50A2B0[v28 + 49]._rhw = v30;
          }
          while ( v29 );
          pFace = v46;
        }

        static stru154 static_RenderBuildingsD3D_stru_73C834;
        /*static bool __init_flag = false;
        if (!__init_flag)
        {
          __init_flag = true;

          static_RenderBuildingsD3D_byte_73C84C_init_flag |= 1u;
          stru154::stru154(&static_RenderBuildingsD3D_stru_73C834);
          atexit(loc_4789D4);
        }*/

        v40 = (int)pFace;
        pLightmapBuilder = pGame->pLightmapBuilder;
        v31 = pLightmapBuilder;
        pLightmapBuilder->ApplyLights_OutdoorFace(pFace);
        pDecalBuilder->ApplyDecals_OutdoorFace(pFace);
        v31->std__vector_000004_size = 0;
        LOBYTE(v31) = 0;
        if ( stru_F8AD28.uNumLightsApplied > 0 || pDecalBuilder->uNumDecals > 0 )
        {
          v31 = (LightmapBuilder *)(v50 ? 3 : v49 != 0 ? 5 : 0);
		  static_RenderBuildingsD3D_stru_73C834.GetFacePlaneAndClassify(pFace, &v56->pVertices);
          if ( pDecalBuilder->uNumDecals > 0 )
          {
            v40 = -1;
            v39 = v31;
            v38 = 0;
            v37 = array_50AC10;
            v36 = uNumVertices;
            pDecalBuilder->ApplyDecals(31 - v7->dimming_level,
              2,
              &static_RenderBuildingsD3D_stru_73C834,
              uNumVertices,
              array_50AC10,
              0,
              (char)v31,
              -1);
          }
        }
        if ( stru_F8AD28.uNumLightsApplied > 0 )
          pLightmapBuilder->ApplyLights(
            &stru_F8AD28,
            &static_RenderBuildingsD3D_stru_73C834,
            uNumVertices,
            array_50AC10,
            0,
            (char)v31);
        if ( v50 )
        {
          v32 = sr_424CD7(uNumVertices);
          goto LABEL_76;
        }
        if ( v49 )
        {
          v32 = sr_424EE0_MakeFanFromTriangle(uNumVertices);
LABEL_76:
          v7->uNumVertices = v32;
          uNumVertices = v32;
          OutdoorCamera::Project(v32);
        }
        if ( uNumVertices )
        {
          v33 = *(int *)&v7->flags;
          if ( v33 & 2 )
          {
            if ( BYTE1(v33) & 0x3C )
              v34 = pRenderer->pHDWaterBitmapIDs[0];
            else
              v34 = pRenderer->pHDWaterBitmapIDs[pRenderer->hd_water_current_frame];
            v40 = (int)pBitmaps_LOD->pHardwareTextures[v34];
          }
          else
          {
            v40 = (int)pBitmaps_LOD->pHardwareTextures[v48];
          }
          pRenderer->DrawPolygon(uNumVertices, v7, pFace, (IDirect3DTexture2 *)v40);
        }
        goto LABEL_85;
      }
      --pOutdoorCamera->numStru148s;
      --pOutdoorCamera->field_44;
LABEL_85:
      v54 = (Vec3_int_ *)((char *)v54 + 1);
      v2 = v56;
      ++pFace;
      v46 = pFace;
      if ( (signed int)v54 >= (signed int)v42 )
        goto LABEL_86;
    }
  }
  return result;
}
// 73C84C: using guessed type char static_RenderBuildingsD3D_byte_73C84C_init_flag;

//----- (004789DE) --------------------------------------------------------
BSPModel *Render::DrawBuildingsSW()
{
  BSPModel *result; // eax@1
  BSPModel *v1; // ebx@2
  int v2; // eax@4
  ODMFace *v3; // edi@4
  int v4; // ecx@6
  int v5; // eax@6
  int v6; // ecx@6
  int v7; // ecx@6
  double v8; // st7@7
  char *v9; // ebx@7
  int v10; // eax@9
  double v11; // st7@9
  stru148 *v12; // ebx@19
  double v13; // st7@21
  double v14; // ST4C_8@23
  int v15; // eax@23
  int v16; // eax@27
  int v17; // ecx@29
  unsigned __int8 v18; // sf@29
  unsigned __int8 v19; // of@29
  int v20; // ecx@30
  int v21; // eax@31
  int v22; // eax@31
  int v23; // eax@35
  int v24; // eax@39
  Texture *v25; // eax@43
  int v26; // esi@43
  signed int v27; // ecx@43
  double v28; // st6@43
  double v29; // st5@43
  unsigned short *v30; // edx@44
  int v31; // eax@44
  double v32; // st4@45
  int v33; // ecx@45
  char v34; // zf@45
  BSPVertexBuffer *v35; // eax@50
  unsigned int v36; // eax@53
  signed int v37; // esi@53
  int v38; // eax@54
  signed int v39; // edx@55
  char *v40; // ecx@56
  double v41; // ST1C_8@57
  double v42; // ST24_8@57
  signed int v43; // eax@60
  signed int v44; // esi@60
  int v45; // eax@61
  signed int v46; // edx@62
  char *v47; // ecx@63
  double v48; // ST34_8@64
  double v49; // ST44_8@64
  int v50; // eax@66
  signed int v51; // ecx@67
  char *v52; // edx@68
  double v53; // ST3C_8@69
  double v54; // ST2C_8@69
  float v55; // [sp+44h] [bp-7Ch]@50
  float v56; // [sp+48h] [bp-78h]@50
  float v57; // [sp+4Ch] [bp-74h]@50
  float v58; // [sp+50h] [bp-70h]@64
  int v59; // [sp+54h] [bp-6Ch]@64
  int v60; // [sp+58h] [bp-68h]@69
  float v61; // [sp+5Ch] [bp-64h]@64
  float v62; // [sp+60h] [bp-60h]@69
  float v63; // [sp+64h] [bp-5Ch]@57
  float v64; // [sp+68h] [bp-58h]@57
  int v65; // [sp+6Ch] [bp-54h]@64
  int v66; // [sp+70h] [bp-50h]@1
  int v67; // [sp+74h] [bp-4Ch]@6
  int v68; // [sp+78h] [bp-48h]@4
  int v69; // [sp+7Ch] [bp-44h]@57
  int v70; // [sp+80h] [bp-40h]@69
  int v71; // [sp+84h] [bp-3Ch]@23
  float v72; // [sp+88h] [bp-38h]@69
  int v73; // [sp+8Ch] [bp-34h]@57
  int v74; // [sp+90h] [bp-30h]@6
  int v75; // [sp+94h] [bp-2Ch]@6
  ODMFace *v76; // [sp+98h] [bp-28h]@4
  int v77; // [sp+9Ch] [bp-24h]@6
  BSPModel *v78; // [sp+A0h] [bp-20h]@2
  int v79; // [sp+A4h] [bp-1Ch]@4
  int a1; // [sp+A8h] [bp-18h]@1
  unsigned short *v81; // [sp+ACh] [bp-14h]@7
  int v82; // [sp+B0h] [bp-10h]@6
  int v83; // [sp+B4h] [bp-Ch]@6
  signed int v84; // [sp+B8h] [bp-8h]@7
  int a2; // [sp+BCh] [bp-4h]@1

  a2 = 0;
  a1 = 0;
  result = (BSPModel *)pOutdoor->pBModels;
  v66 = pOutdoor->uNumBModels;
  if ( (signed int)pOutdoor->uNumBModels > 0 )
  {
    v1 = pOutdoor->pBModels;
    v78 = pOutdoor->pBModels;
    while ( 1 )
    {
      if ( IsBModelVisible(a1, &a2) )
      {
		v1->field_40 |= 1u;
        v2 = v1->uNumFaces;
        v3 = (ODMFace *)v1->pFaces;
        v74 = 0;
        v76 = v3;
        v68 = v2;
        if ( v2 > 0 )
          break;
      }
LABEL_73:
      ++a1;
      ++v1;
      result = (BSPModel *)a1;
      v78 = v1;
      if ( a1 >= v66 )
        return result;
    }
    while ( 1 )
    {
	  if ( !v3->Invisible() )
      {
        v4 = 3 * v3->pVertexIDs[0];
        v5 = (int)((char *)v1 - 8);
        v67 = (int)((char *)v1 - 8);
        v6 = *(_DWORD *)(*(&v1->uNumConvexFaces - 2) + 4 * v4 + 8) + 4;
        v82 = 0;
        v83 = v6;
        v74 = 0;
        v7 = v3->uNumVertices;
        v75 = 0;
        v77 = v7;
        if ( v7 > 0 )
        {
          v8 = (double)v83;
          v9 = (char *)&array_73D150[0].vWorldViewPosition;
		  v81 = v3->pVertexIDs;
          v83 = v7;
          *(float *)&v84 = v8;
          while ( 1 )
          {
            v10 = *(int *)(v5 + 4) + 12 * *(short *)v81;
            *((float *)v9 - 3) = (double)*(signed int *)v10 + 4.0;
            *((float *)v9 - 2) = (double)*(signed int *)(v10 + 4) + 4.0;
            v11 = (double)*(signed int *)(v10 + 8) + 4.0;
            *((float *)v9 - 1) = v11;
            if ( *(float *)&v84 == v11 )
              ++v82;
            pGame->pIndoorCameraD3D->ViewTransform((RenderVertexSoft *)(v9 - 12), 1u);
            if ( *(float *)v9 < 8.0 || (double)pOutdoorCamera->shading_dist_mist < *(float *)v9 )
            {
              if ( *(float *)v9 >= 8.0 )
                v75 = 1;
              else
                v74 = 1;
            }
            else
            {
              pGame->pIndoorCameraD3D->Project((RenderVertexSoft *)(v9 - 12), 1u, 0);
            }
            v81 += 2;
            v9 += 48;
            --v83;
            if ( !v83 )
              break;
            v5 = v67;
          }
          v7 = v77;
        }
        v12 = &array_77EC08[pOutdoorCamera->numStru148s];
        *(int *)&v12->flags = 0;
        if ( v82 == v7 )
          *(int *)&v12->flags = 65536;
        v12->pODMFace = (ODMFace *)v3;
        v12->uNumVertices = v7;
        v12->field_59 = 5;
        v84 = *(int *)v3;
        v83 = (unsigned __int64)(v84 * (signed __int64)-pOutdoor->vSunlight.x) >> 16;
        v82 = -pOutdoor->vSunlight.y;
        v84 = *(int *)(v3 + 4);
        v82 = (unsigned __int64)(v84 * (signed __int64)-pOutdoor->vSunlight.y) >> 16;
        v81 = (unsigned __int16 *)-pOutdoor->vSunlight.z;
        v84 = *(int *)(v3 + 8);
        v81 = (unsigned __int16 *)((unsigned __int64)(v84 * (signed __int64)-pOutdoor->vSunlight.z) >> 16);
        v84 = v83 + v82 + ((unsigned __int64)(v84 * (signed __int64)-pOutdoor->vSunlight.z) >> 16);
        v13 = (double)v84 * 0.000015258789;
        if ( v13 < 0.0 )
          v13 = 0.0;
        *(float *)&v84 = v13 * 31.0;
        v14 = *(float *)&v84 + 6.7553994e15;
        v71 = LODWORD(v14);
        v15 = (int)&v12->dimming_level;
        v12->dimming_level = 31 - LOBYTE(v14);
        if ( (char)(31 - LOBYTE(v14)) < 0 )
          *(char *)v15 = 0;
        if ( *(char *)v15 > 31 )
          *(char *)v15 = 31;
        v16 = *(short *)(v3 + 272);
        if ( *(char *)(v3 + 29) & 0x40 )
          v16 = pTextureFrameTable->GetFrameTexture(v16, pEventTimer->uTotalGameTimeElapsed);
        v17 = v16;
        result = (BSPModel *)&pBitmaps_LOD->pTextures[v16];
        v19 = __OFSUB__(pOutdoorCamera->numStru148s, 1999);
        v18 = pOutdoorCamera->numStru148s - 1999 < 0;
        v12->pTexture = (Texture *)(v17 != -1 ? (int)result : 0);
        if ( !(v18 ^ v19) )
          return result;
        ++pOutdoorCamera->numStru148s;
        ++pOutdoorCamera->field_44;
        if ( !ODMFace::IsBackfaceCulled((ODMFace *)v3, array_73D150, v12) )
        {
LABEL_71:
          --pOutdoorCamera->numStru148s;
          --pOutdoorCamera->field_44;
          goto LABEL_72;
        }
        LOBYTE(v20) = v79;
        v21 = a1;
        *(char *)(v3 + 305) = 1;
        v12->uBModelFaceID = v20;
        LOWORD(v20) = (unsigned __int8)v20;
        v12->uBModelID = v21;
        v22 = 8 * (v20 | (v21 << 6));
        LOBYTE(v22) = v22 | 6;
        v12->field_50 = v22;
        if ( *(char *)(v3 + 28) & 0x10 )
          *(int *)&v12->flags |= 2u;
        if ( *(char *)(v3 + 30) & 0x40 )
          HIBYTE(v12->flags) |= 4u;
        v23 = *(int *)(v3 + 28);
        if ( v23 & 4 )
        {
          HIBYTE(v12->flags) |= 4u;
        }
        else
        {
          if ( v23 & 0x20 )
            HIBYTE(v12->flags) |= 8u;
        }
        v24 = *(int *)(v3 + 28);
        if ( BYTE1(v24) & 8 )
        {
          HIBYTE(v12->flags) |= 0x20u;
        }
        else
        {
          if ( v24 & 0x40 )
            HIBYTE(v12->flags) |= 0x10u;
        }
        v25 = v12->pTexture;
        v26 = v77;
        v27 = v25->uTextureWidth;
        v84 = v25->uTextureHeight;
        v28 = 1.0 / (double)v27;
        v29 = 1.0 / (double)v84;
        if ( v77 > 0 )
        {
		  v30 = v3->pTextureVIDs;
          v31 = 0;
          v83 = v77;
          do
          {
            v32 = 1.0 / (*(float *)(v31 * 48 + 7590236) + 0.0000001);
            memcpy(&array_50AC10[v31], &array_73D150[v31], sizeof(array_50AC10[v31]));
            ++v31;
            array_50A2B0[v31 + 49]._rhw = v32;
            v84 = v12->sTextureDeltaU + *(short *)(v30 - 40);
            array_50A2B0[v31 + 49].u = (double)v84 * v28;
            v33 = v12->sTextureDeltaV + *(short *)v30;
            v30 += 2;
            v34 = v83-- == 1;
            v84 = v33;
            array_50A2B0[v31 + 49].v = (double)v33 * v29;
          }
          while ( !v34 );
          v3 = v76;
          v26 = v77;
        }
        
        static stru154 static_sub_004789DE_stru_73C818; // idb
        /*static bool __init_flag = false;
        if (!__init_flag)
        {
          __init_flag = true;

          static_sub_004789DE_byte_73C830__init_flag |= 1u;
          stru154::stru154(&static_sub_004789DE_stru_73C818);
        }*/

        pGame->pLightmapBuilder->ApplyLights_OutdoorFace((ODMFace *)v3);
        if ( stru_F8AD28.uNumLightsApplied <= 0 )
        {
          v12->field_108 = 0;
        }
        else
        {
          v35 = (BSPVertexBuffer *)(v78 - 2);
          v12->field_108 = 1;

          static_sub_004789DE_stru_73C818.GetFacePlaneAndClassify((ODMFace *)v3, v35);
          v55 = static_sub_004789DE_stru_73C818.face_plane.vNormal.x;
          v56 = static_sub_004789DE_stru_73C818.face_plane.vNormal.y;
          v57 = static_sub_004789DE_stru_73C818.face_plane.vNormal.z;
          pGame->pLightmapBuilder->_45CA88(&stru_F8AD28, array_50AC10, v26, (Vec3_float_ *)&v55);
        }
        if ( v74 )
        {
          v36 = sr_4250FE(v26);
          v37 = v36;
          if ( !v36 || (OutdoorCamera::Project(v36), v38 = sr_4254D2(v37), (v12->uNumVertices = v38) == 0) )
            goto LABEL_71;
          v12->_48276F_sr();
          v39 = 0;
          if ( (signed int)v12->uNumVertices > 0 )
          {
            v40 = (char *)&array_508690[0].vWorldViewProjY;
            do
            {
              LODWORD(v64) = *((int *)v40 - 1);
              v41 = v64 + 6.7553994e15;
              v69 = LODWORD(v41);
              dword_50B638[v39] = LODWORD(v41);
              LODWORD(v63) = *(int *)v40;
              v42 = v63 + 6.7553994e15;
              v73 = LODWORD(v42);
              v40 += 48;
              dword_50B570[v39++] = LODWORD(v42);
            }
            while ( v39 < (signed int)v12->uNumVertices );
          }
        }
        else
        {
          if ( v75 )
          {
            v43 = sr_4252E8(v26);
            v44 = v43;
            if ( !v43 || (OutdoorCamera::Project(v43), v45 = sr_4254D2(v44), (v12->uNumVertices = v45) == 0) )
              goto LABEL_71;
            v12->_48276F_sr();
            v46 = 0;
            if ( (signed int)v12->uNumVertices > 0 )
            {
              v47 = (char *)&array_508690[0].vWorldViewProjY;
              do
              {
                LODWORD(v61) = *((int *)v47 - 1);
                v48 = v61 + 6.7553994e15;
                v65 = LODWORD(v48);
                dword_50B638[v46] = LODWORD(v48);
                LODWORD(v58) = *(int *)v47;
                v49 = v58 + 6.7553994e15;
                v59 = LODWORD(v49);
                v47 += 48;
                dword_50B570[v46++] = LODWORD(v49);
              }
              while ( v46 < (signed int)v12->uNumVertices );
            }
          }
          else
          {
            v50 = sr_4254D2(v26);
            v12->uNumVertices = v50;
            if ( !v50 )
              goto LABEL_71;
            sr_sub_4829B9(
              &array_73D150[*(char *)(v3 + 298)],
              &array_73D150[*(char *)(v3 + 299)],
              &array_73D150[*(char *)(v3 + 300)],
              v12,
              0);
            v51 = 0;
            if ( (signed int)v12->uNumVertices > 0 )
            {
              v52 = (char *)&array_508690[0].vWorldViewProjY;
              do
              {
                LODWORD(v62) = *((int *)v52 - 1);
                v53 = v62 + 6.7553994e15;
                v60 = LODWORD(v53);
                dword_50B638[v51] = LODWORD(v53);
                LODWORD(v72) = *(int *)v52;
                v54 = v72 + 6.7553994e15;
                v70 = LODWORD(v54);
                v52 += 48;
                dword_50B570[v51++] = LODWORD(v54);
              }
              while ( v51 < (signed int)v12->uNumVertices );
            }
          }
        }
        sr_sub_486B4E_push_outdoor_edges(array_508690, dword_50B638, dword_50B570, v12);
      }
LABEL_72:
      ++v79;
      v1 = v78;
      v3 += 308;
      v76 = v3;
      if ( v79 >= v68 )
        goto LABEL_73;
    }
  }
  return result;
}
// 50B570: using guessed type int dword_50B570[];
// 50B638: using guessed type int dword_50B638[];
// 73C830: using guessed type char static_sub_004789DE_byte_73C830__init_flag;

//----- (00479089) --------------------------------------------------------
bool __fastcall IsBModelVisible(unsigned int uModelID, int *reachable)
{
  BSPModel *v2; // eax@1
  int v3; // edi@1
  int v4; // ebx@1
  int v5; // ST28_4@1
  int v6; // ecx@1
  int v7; // ebx@3
  int v8; // eax@3
  int v9; // eax@3
  //int v10; // ebx@3
  signed int v11; // esi@6
  int v12; // esi@8
  bool result; // eax@9
  //unsigned int v14; // [sp+Ch] [bp-20h]@1
  int v15; // [sp+Ch] [bp-20h]@5
  //int *v16; // [sp+10h] [bp-1Ch]@1
  int v17; // [sp+1Ch] [bp-10h]@1
  int v18; // [sp+20h] [bp-Ch]@1
  int v19; // [sp+20h] [bp-Ch]@3
  int angle; // [sp+24h] [bp-8h]@1
  int v21; // [sp+28h] [bp-4h]@1
  //int v22; // [sp+28h] [bp-4h]@3

  //v16 = unused;
  angle = (signed int)(pOutdoorCamera->uCameraFovInDegrees << 11) / 360 >> 1;
  //v14 = uModelID;
  v2 = &pOutdoor->pBModels[uModelID];
  v3 = v2->vBoundingCenter.x - pIndoorCamera->pos.x;
  v4 = v2->vBoundingCenter.y - pIndoorCamera->pos.y;
  v5 = stru_5C6E00->Cos(pIndoorCamera->sRotationY);
  v21 = stru_5C6E00->Sin(pIndoorCamera->sRotationY);
  v18 = stru_5C6E00->Cos(pIndoorCamera->sRotationX);
  stru_5C6E00->Sin(pIndoorCamera->sRotationX);
  v6 = v5;
  v17 = v3 * v5 + v4 * v21;
  if ( pIndoorCamera->sRotationX )
    v17 = (unsigned __int64)(v17 * (signed __int64)v18) >> 16;
  v19 = v4 * v6 - v3 * v21;
  v7 = abs(v4);
  v8 = abs(v3);
  v9 = int_get_vector_length(v8, v7, 0);
  //v10 = v14 * 188;
  //v22 = v9;
  *reachable = false;
  if ( v9 < pOutdoor->pBModels[uModelID].sBoundingRadius + 256 )
    *reachable = true;
  v15 = stru_5C6E00->Sin(angle);
  if ( v19 >= 0 )
    v11 = ((unsigned __int64)(v15 * (signed __int64)v17) >> 16) - ((unsigned __int64)(stru_5C6E00->Cos(angle) * (signed __int64)v19) >> 16);
  else
    v11 = ((unsigned __int64)(stru_5C6E00->Cos(angle) * (signed __int64)v19) >> 16) + ((unsigned __int64)(v15 * (signed __int64)v17) >> 16);
  v12 = v11 >> 16;
  if ( v9 <= pOutdoorCamera->shading_dist_mist + 2048 )
  {
    //if ( abs(v12) > *(int *)((char *)&pOutdoor->pBModels->sBoundingRadius + v10) + 512 )
	if ( abs(v12) > pOutdoor->pBModels[uModelID].sBoundingRadius + 512 )
    {
      result = v12 < 0;
      LOBYTE(result) = v12 >= 0;
      return result;
    }
    else
      return true;
  }
  return false;
}

//----- (00479295) --------------------------------------------------------
int stru148::_479295()
{
  stru148 *v1; // edi@1
  ODMFace *v2; // esi@1
  int v3; // ecx@4
  int v4; // eax@4
  int v5; // edx@4
  int v6; // ST14_4@5
  int v7; // ST04_4@5
  stru149 *v8; // ecx@5
  Vec3_int_ thisa; // [sp+Ch] [bp-10h]@8
  int v11; // [sp+18h] [bp-4h]@4

  v1 = this;
  v2 = this->pODMFace;
  if ( !v2->pFacePlane.vNormal.z )
  {
    v3 = v2->pFacePlane.vNormal.x;
    v4 = -v2->pFacePlane.vNormal.y;
LABEL_9:
    v5 = 0;
    v11 = 65536;
    goto LABEL_5;
  }
  if ( (v2->pFacePlane.vNormal.x || v2->pFacePlane.vNormal.y) && abs(v2->pFacePlane.vNormal.z) < 59082 )
  {
    thisa.x = -v2->pFacePlane.vNormal.y;
    thisa.y = v2->pFacePlane.vNormal.x;
    thisa.z = 0;
    thisa.Normalize_float();
    v4 = thisa.x;
    v3 = thisa.y;
    goto LABEL_9;
  }
  v3 = 0;
  v4 = 65536;
  v11 = 0;
  v5 = -65536;
LABEL_5:
  v6 = v11;
  v1->sTextureDeltaU = v2->sTextureDeltaU;
  v7 = v3;
  v8 = v1->ptr_38;
  v1->sTextureDeltaV = v2->sTextureDeltaV;
  v8->_48616B(v4, v7, 0, 0, v5, v6);
  return 1;
}

//----- (00479332) --------------------------------------------------------
int Render::OnOutdoorRedrawSW()
{
  signed int result; // eax@1
  unsigned int v1; // edi@1
  char *v2; // esi@2
  char v3; // cl@3
  double v4; // st7@4
  float v5; // ST34_4@6
  double v6; // ST24_8@6
  int v7; // eax@6
  unsigned int v8; // eax@11
  signed int v9; // eax@13
  Vec3_float_ *v10; // eax@14
  double v11; // st7@17
  float v12; // ST34_4@19
  double v13; // ST1C_8@19
  float v14; // [sp+4h] [bp-34h]@1
  float v15; // [sp+8h] [bp-30h]@1
  float v16; // [sp+Ch] [bp-2Ch]@1

  v14 = (double)pOutdoor->vSunlight.x / 65536.0;
  result = 0;
  v1 = (unsigned int)&array_77EC08[pOutdoorCamera->numStru148s];
  v15 = (double)pOutdoor->vSunlight.y / 65536.0;
  v16 = (double)pOutdoor->vSunlight.z / 65536.0;
  if ( v1 > (unsigned int)array_77EC08 )
  {
    v2 = (char *)&array_77EC08[0].pODMFace;
    while ( 1 )
    {
      v3 = v2[5];
      if ( v3 == 5 )
        break;
      if ( v3 == 1 )
      {
        v9 = pTerrainNormalIndices[((*((int *)v2 - 9) >> 15) & 1)
                                 + 2 * ((unsigned __int8)v2[9] + ((unsigned __int8)v2[8] << 7))];
        if ( v9 > (signed int)(uNumTerrainNormals - 1) )
          v10 = 0;
        else
          v10 = &pTerrainNormals[v9];
        if ( v10 )
        {
          v11 = -(v16 * v10->z + v15 * v10->y + v14 * v10->x);
          if ( v11 < 0.0 )
            v11 = 0.0;
          v12 = v11 * 31.0;
          v13 = v12 + 6.7553994e15;
          v2[4] = 31 - LOBYTE(v13);
        }
        else
        {
          v2[4] = 0;
        }
        if ( v2[4] < 0 )
          v2[4] = 0;
        goto LABEL_23;
      }
LABEL_24:
      v2 += 268;
      if ( (unsigned int)(v2 - 84) >= v1 )
        return result;
    }
    v4 = (double)(signed int)(((unsigned __int64)(**(int **)v2 * (signed __int64)-pOutdoor->vSunlight.x) >> 16)
                            + ((unsigned __int64)(*(int *)(*(int *)v2 + 4) * (signed __int64)-pOutdoor->vSunlight.y) >> 16)
                            + ((unsigned __int64)(*(int *)(*(int *)v2 + 8) * (signed __int64)-pOutdoor->vSunlight.z) >> 16))
       * 0.000015258789;
    if ( v4 < 0.0 )
      v4 = 0.0;
    v5 = v4 * 31.0;
    v6 = v5 + 6.7553994e15;
    v7 = (int)(v2 + 4);
    v2[4] = 31 - LOBYTE(v6);
    if ( (char)(31 - LOBYTE(v6)) < 0 )
      *(char *)v7 = 0;
    if ( *(char *)v7 > 31 )
      *(char *)v7 = 31;
    if ( *(char *)(*(int *)v2 + 29) & 0x40 )
    {
      v8 = pTextureFrameTable->GetFrameTexture(
             *((short *)v2 - 4),
             pEventTimer->uTotalGameTimeElapsed);
      *((int *)v2 - 6) = v8 != -1 ? (int)&pBitmaps_LOD->pTextures[v8] : 0;
    }
LABEL_23:
    result = 1;
    goto LABEL_24;
  }
  return result;
}

unsigned short *LoadTgaTexture(const wchar_t *filename, int *out_width = nullptr, int *out_height = nullptr)
{
  #pragma pack(push, 1)
    struct TGAHeader
    {
      unsigned char  tgaSkip;
      unsigned char  colourmaptype;      // type of colour map 0=none, 1=has palette
      unsigned char  tgaType;            // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed

      short colourmapstart;     // first colour map entry in palette
      short colourmaplength;    // number of colours in palette
      char  colourmapbits;      // number of bits per palette entry 15,16,24,32

      //unsigned char  tgaDontCare2[9];
      short xstart;             // image x origin
      short ystart;             // image y origin

      unsigned short tgaWidth;
      unsigned short tgaHeight;
      unsigned char  tgaBPP;

      char  descriptor;         // image descriptor bits:   00vhaaaa
        //      h horizontal flip
        //      v vertical flip
        //      a alpha bits
    };
  #pragma pack(pop)

  if (out_width)
    *out_width = 0;
  if (out_height)
    *out_height = 0;

  DWORD w;
  auto  file = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
  if (file == INVALID_HANDLE_VALUE)
    return nullptr;

  TGAHeader header;
  ReadFile(file, &header, sizeof(header), &w, nullptr);
  SetFilePointer(file, header.tgaSkip, nullptr, FILE_CURRENT);

  if (header.tgaBPP != 24 || header.tgaType != 2)
  {
    CloseHandle(file);
    return nullptr;
  }

  int imgSize = header.tgaWidth * header.tgaHeight * 3;
  auto pixels = new unsigned char[imgSize];
  ReadFile(file, pixels, imgSize, &w, nullptr);
  CloseHandle(file);

  if (w != imgSize)
  {
    delete [] pixels;
    return nullptr;
  }

  if (out_width)
    *out_width = header.tgaWidth;
  if (out_height)
    *out_height = header.tgaHeight;

  auto pixels_16bit = new unsigned short[imgSize / 3];
  for (int i = 0; i < imgSize / 3; ++i)
  {
    pixels_16bit[i] = (pixels[i * 3] / 8 & 0x1F) |
                      ((pixels[i * 3 + 1] / 4 & 0x3F) << 5) |
                      ((pixels[i * 3 + 2] / 8 & 0x1F) << 11);
  }
  delete [] pixels;
  return pixels_16bit;
}

unsigned short *skybox_xn, *skybox_xp,
              *skybox_yn, *skybox_yp,
              *skybox_zn, *skybox_zp;
int            skybox_width, skybox_height;

IDirect3DTexture2   *skybox_texture;
IDirectDrawSurface4 *skybox_surface;

bool Skybox_Initialize(const wchar_t *skybox_name)
{
  wchar_t xn_filename[1024], xp_filename[1024],
          yn_filename[1024], yp_filename[1024],
          zn_filename[1024], zp_filename[1024];
  swprintf(xn_filename, L"%s_xn.tga", skybox_name); swprintf(xp_filename, L"%s_xp.tga", skybox_name);
  swprintf(yn_filename, L"%s_yn.tga", skybox_name); swprintf(yp_filename, L"%s_yp.tga", skybox_name);
  swprintf(zn_filename, L"%s_zn.tga", skybox_name); swprintf(zp_filename, L"%s_zp.tga", skybox_name);

  int xn_width, xn_height;
  skybox_xn = LoadTgaTexture(xn_filename, &xn_width, &xn_height);
  if (!skybox_xn)
    return false;

  int xp_width, xp_height;
  skybox_xp = LoadTgaTexture(xp_filename, &xp_width, &xp_height);
  if (!skybox_xp || xp_width != xn_width || xp_height != xn_height)
  {
    delete [] skybox_xn;
    if (skybox_xp) delete [] skybox_xp;
    return false;
  }

  int yn_width, yn_height;
  skybox_yn = LoadTgaTexture(yn_filename, &yn_width, &yn_height);
  if (!skybox_yn || yn_width != xn_width || yn_height != xn_height)
  {
    delete [] skybox_xn;
    if (skybox_xp) delete [] skybox_xp;
    if (skybox_yn) delete [] skybox_yn;
    return false;
  }

  int yp_width, yp_height;
  skybox_yp = LoadTgaTexture(yp_filename, &yp_width, &yp_height);
  if (!skybox_yp || yp_width != xn_width || yp_height != xn_height)
  {
    delete [] skybox_xn;
    if (skybox_xp) delete [] skybox_xp;
    if (skybox_yn) delete [] skybox_yn;
    if (skybox_yp) delete [] skybox_yp;
    return false;
  }

  int zn_width, zn_height;
  skybox_zn = LoadTgaTexture(zn_filename, &zn_width, &zn_height);
  if (!skybox_zn || zn_width != xn_width || zn_height != xn_height)
  {
    delete [] skybox_xn;
    if (skybox_xp) delete [] skybox_xp;
    if (skybox_yn) delete [] skybox_yn;
    if (skybox_yp) delete [] skybox_yp;
    if (skybox_zn) delete [] skybox_zn;
    return false;
  }

  int zp_width, zp_height;
  skybox_zp = LoadTgaTexture(zp_filename, &zp_width, &zp_height);
  if (!skybox_zp || zp_width != xn_width || zp_height != xn_height)
  {
    delete [] skybox_xn;
    if (skybox_xp) delete [] skybox_xp;
    if (skybox_yn) delete [] skybox_yn;
    if (skybox_yp) delete [] skybox_yp;
    if (skybox_zn) delete [] skybox_zn;
    if (skybox_zp) delete [] skybox_zp;
    return false;
  }

  skybox_width = xn_width;
  skybox_height = xn_height;

  
  if (!pRenderer->pRenderD3D->CreateTexture(skybox_width, skybox_height, &skybox_surface, &skybox_texture,
                                            false, false, pRenderer->uMinDeviceTextureDim))
    return false;

  return true;
}

struct vector
{
  float x, y, z;
};

struct matrix
{
  float m[4][4];
};

void VectorNormalize(vector *v)
{
  float invmag = 1.0f / sqrtf(v->x * v->x + v->y * v->y + v->z * v->z);
  v->x *= invmag;
  v->y *= invmag;
  v->z *= invmag;
}

void MatrixRotationAxis(matrix *pout, CONST vector *pv, float angle)
{
  memset(pout, 0, sizeof(matrix));
  pout->m[3][0] = 0;
  pout->m[3][1] = 0;
  pout->m[3][2] = 0;
  pout->m[3][3] = 1;

  vector v;
  v.x = pv->x; v.y = pv->y; v.z = pv->z;
  VectorNormalize(&v);

    pout->m[0][0] = (1.0f - cos(angle)) * v.x * v.x + cos(angle);
    pout->m[1][0] = (1.0f - cos(angle)) * v.x * v.y - sin(angle) * v.z;
    pout->m[2][0] = (1.0f - cos(angle)) * v.x * v.z + sin(angle) * v.y;
    pout->m[0][1] = (1.0f - cos(angle)) * v.y * v.x + sin(angle) * v.z;
    pout->m[1][1] = (1.0f - cos(angle)) * v.y * v.y + cos(angle);
    pout->m[2][1] = (1.0f - cos(angle)) * v.y * v.z - sin(angle) * v.x;
    pout->m[0][2] = (1.0f - cos(angle)) * v.z * v.x - sin(angle) * v.y;
   pout->m[1][2] = (1.0f - cos(angle)) * v.z * v.y + sin(angle) * v.x;
    pout->m[2][2] = (1.0f - cos(angle)) * v.z * v.z + cos(angle);
}

void VectorTransform(const matrix *m, const vector *v, vector *out)
{
  out->x = m->m[0][0] * v->x + m->m[1][0] * v->y + m->m[2][0] * v->z + m->m[3][0];
  out->y = m->m[0][1] * v->x + m->m[1][1] * v->y + m->m[2][1] * v->z + m->m[3][1];
  out->z = m->m[0][2] * v->x + m->m[1][2] * v->y + m->m[2][2] * v->z + m->m[3][2];
}

bool DrawSkyD3D_Skybox()
{
  static bool initialized = false,
              initialization_failed = false;
  if (initialization_failed)
    return false;
  
  static int last_camera_rot_y,
             last_camera_rot_x;
  if (!initialized)
  {
    if (!Skybox_Initialize(L"data/skybox/stars"))
    {
      initialization_failed = true;
      return false;
    }
    initialized = true;

    last_camera_rot_y = pParty->sRotationY + 1; // force update for the first run 
    last_camera_rot_x = pParty->sRotationX + 1;
  }

  /*
  r(y) = 
cos y	0	sin y	0
0	1	0	0
-sin y	0	cos y	0
0	0	0	1

x cos y - z sin y
y
x sin y + z cos y
1



r(x) =     // should be r(right) actually
1	0      	0	0
0	cos x	-sin x	0
0	sin x	cos x	0
0	0	    0	1


x
y cos x + z sin x
-y sin x + z cos x
1

  */

  if (last_camera_rot_y == pParty->sRotationY &&
      last_camera_rot_x == pParty->sRotationX)
  {
draw:
    struct RenderVertexD3D3  v[6];

    v[0].pos.x = pViewport->uScreen_TL_X;
    v[0].pos.y = pViewport->uScreen_TL_Y;
    v[0].pos.z = 0.99989998;
    v[0].rhw = 1;
    v[0].diffuse = 0xFFFFFFFF;
    v[0].specular = 0;
    v[0].texcoord.x = 0;
    v[0].texcoord.y = 0;
    
    v[1].pos.x = pViewport->uScreen_TL_X + pViewport->uScreenWidth;
    v[1].pos.y = pViewport->uScreen_TL_Y + pViewport->uScreenHeight;
    v[1].pos.z = 0.99989998;
    v[1].rhw = 1;
    v[1].diffuse = 0xFFFFFFFF;
    v[1].specular = 0;
    v[1].texcoord.x = (float)pViewport->uScreenWidth / skybox_width;
    v[1].texcoord.y = (float)pViewport->uScreenHeight / skybox_height;

    v[2].pos.x = pViewport->uScreen_TL_X + pViewport->uScreenWidth;
    v[2].pos.y = pViewport->uScreen_TL_Y;
    v[2].pos.z = 0.99989998;
    v[2].rhw = 1;
    v[2].diffuse = 0xFFFFFFFF;
    v[2].specular = 0;
    v[2].texcoord.x = (float)pViewport->uScreenWidth / skybox_width;
    v[2].texcoord.y = 0;

    memcpy(&v[3], &v[0], sizeof(*v));

    v[4].pos.x = pViewport->uScreen_TL_X;
    v[4].pos.y = pViewport->uScreen_TL_Y + pViewport->uScreenHeight;
    v[4].pos.z = 0.99989998;
    v[4].rhw = 1;
    v[4].diffuse = 0xFFFFFFFF;
    v[4].specular = 0;
    v[4].texcoord.x = 0;
    v[4].texcoord.y = (float)pViewport->uScreenHeight / skybox_height;

    memcpy(&v[5], &v[1], sizeof(*v));

    pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
    pRenderer->pRenderD3D->pDevice->SetTexture(0, skybox_texture);
    pRenderer->pRenderD3D->pDevice->DrawPrimitive(D3DPT_TRIANGLELIST, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1, v, 6, D3DDP_DONOTUPDATEEXTENTS | D3DDP_DONOTLIGHT);
    //pRenderer->pRenderD3D->pDevice->DrawPrimitive(D3DPT_TRIANGLELIST, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1, v + 1, 3, D3DDP_DONOTUPDATEEXTENTS | D3DDP_DONOTLIGHT);

    return true;
  }


  DDSURFACEDESC2 desc;
  desc.dwSize = sizeof(desc);
  if (!pRenderer->LockSurface_DDraw4(skybox_surface, &desc, DDLOCK_WAIT | DDLOCK_WRITEONLY))
    return false;
  
  last_camera_rot_y = pParty->sRotationY;
  last_camera_rot_x = pParty->sRotationX;

  float aspect = (float)pViewport->uScreenWidth / (float)pViewport->uScreenHeight;
  float fov_x = 3.141592f * (pOutdoorCamera->uCameraFovInDegrees + 0) / 360.0f;
  float fov_y = fov_x / aspect;

  float ray_dx = fov_x / (float)pViewport->uScreenWidth,
        ray_dy = fov_y / (float)pViewport->uScreenHeight;
  float party_angle_x = 2 * 3.141592653589 * pParty->sRotationX / 2048.0,
        party_angle_y = 2 * 3.141592653589 * pParty->sRotationY / 2048.0;
  for (int y = 0; y < pViewport->uScreenHeight; ++y)
    for (int x = 0; x < pViewport->uScreenWidth; ++x)
    {
      float angle_x = party_angle_x - (y - pViewport->uScreenHeight / 2) * ray_dy;
      float angle_y = party_angle_y - (x - pViewport->uScreenWidth / 2) * ray_dx;

      float _dir_x_ = 1,
            _dir_y_ = 0,
            _dir_z_ = 0;

      float dir_x_ = _dir_x_ * cosf(angle_y);// - _dir_z_ * sinf(angle_y);  // rotation around y
      //float dir_y_ = _dir_y_;
      float dir_z_ = _dir_x_ * sinf(angle_y);// + _dir_z_ * cosf(angle_y);

      //float dir_x =  dir_x_;                                               // rotation around x
      //float dir_y =  /*dir_y_ * cosf(angle_x)*/ + dir_z_ * sinf(angle_x);
      //float dir_z = /*-dir_y_ * sinf(angle_x)*/ + dir_z_ * cosf(angle_x);

      vector right;                                            // rotate around right actually to avoid space distortion
      right.x = /*dir_y * 0*/ - dir_z_ * 1;
      right.y = /*dir_z_ * 0 - dir_x_ * */0;
      right.z = dir_x_ * 1/* - dir_y_ * 0*/;
      //VectorNormalize(&right);

      matrix rightMatrix;
      MatrixRotationAxis(&rightMatrix, &right, angle_x);

      vector v1, v2;
      v1.x = dir_x_; v1.y = 0; v1.z = dir_z_;
      VectorTransform(&rightMatrix, &v1, &v2);

      float dir_x = v2.x,
            dir_y = v2.y,
            dir_z = v2.z;

      float abs_dir_x = fabsf(dir_x),
            abs_dir_y = fabsf(dir_y),
            abs_dir_z = fabsf(dir_z);

      unsigned short color = (0x1F << 11) | (0x1F << 5) | (5);  //default to orange
      if (abs_dir_x >= abs_dir_y)
      {
        if (abs_dir_x >= abs_dir_z)
        {
          if (dir_x >= 0)
          {
            float instersect_y = dir_y / (2.0f * dir_x); // plane equation for this side is x + 0.5 = 0
            float instersect_z = dir_z / (2.0f * dir_x);

            float u = 1.0f - (instersect_z + 0.5f),
                  v = 1.0f - (instersect_y + 0.5f);
            
            int tx = u * (skybox_width - 1),
                ty = v * (skybox_height - 1);

            color = skybox_xp[ty * skybox_width + tx];
            //color = ty * 0x1F / skybox_height;
          }
          else
          {
            float instersect_y = dir_y / (2.0f * dir_x);
            float instersect_z = dir_z / (2.0f * dir_x);

            float u = 1.0f - (instersect_z + 0.5f),
                  v = instersect_y + 0.5f;
            
            int tx = u * (skybox_width - 1),
                ty = v * (skybox_height - 1);

            color = skybox_xn[ty * skybox_width + tx];
            //color = tx * 0x1F / skybox_height;
          }
        }
        else if (dir_z >= 0)
          goto DIR_ZP;
        else
          goto DIR_ZN;
      }
      else if (abs_dir_y >= abs_dir_z)
      {
        if (dir_y >= 0)
        {
            float instersect_x = dir_x / (2.0f * dir_y);
            float instersect_z = dir_z / (2.0f * dir_y);

            float u = instersect_x + 0.5f,
                  v = instersect_z + 0.5f;
            
            int tx = u * (skybox_width - 1),
                ty = v * (skybox_height - 1);

            color = skybox_yp[ty * skybox_width + tx];
            //color = tx * 0x1F / skybox_height;
        }
        /*else   should never be seen i guess
        {
            __debugbreak();
          // -y
            //Log::Warning(L"(%03u, %03u): -y", x, y);
        }*/
      }
      else if (dir_z >= 0)
      {
DIR_ZP:
        // +z
        float instersect_x = dir_x / (2.0f * dir_z);
        float instersect_y = dir_y / (2.0f * dir_z);
        //float intersect_z = 0.5f;

        float u = instersect_x + 0.5f,
              v = -instersect_y + 0.5f;

        int tx = u * (skybox_width - 1),
            ty = v * (skybox_height - 1);

        color = skybox_zp[ty * skybox_width + tx];
      }
      else
      {
DIR_ZN:
        // -z
        float instersect_x = -dir_x / (2.0f * dir_z);
        float instersect_y = -dir_y / (2.0f * dir_z);
        //float intersect_z = -0.5f;

        float u = 1.0f - instersect_x - 0.5f,
              v = -instersect_y + 0.5f;

        int tx = u * (skybox_width - 1),
            ty = v * (skybox_height - 1);

        color = skybox_zn[ty * skybox_width + tx];
      }

      //pRenderer->pTargetSurface[(pViewport->uScreenY + y) * pRenderer->uTargetSurfacePitch + pViewport->uScreenX + x] = color;
      ((unsigned __int16 *)((char *)desc.lpSurface + y * desc.lPitch))[x] = color;
    }
    
  ErrD3D((skybox_surface)->Unlock(0));
  goto draw;
}

//----- (00479543) --------------------------------------------------------
void Render::DrawSkyD3D()
{
  int v0; // esi@2
  int v1; // eax@2
  //double v2; // st7@2
  //double v3; // st6@2
  //double v4; // st5@2
  //double v5; // st4@2
  //double v6; // st7@2
  //char *v7; // esi@3
  int v8; // eax@4
  int v9; // eax@4
  int v10; // ebx@4
  signed __int64 v11; // qax@6
  double v12; // st7@6
  int v13; // edi@6
  int v14; // ecx@6
  int v15; // eax@8
  int v16; // eax@12
  signed __int64 v17; // qtt@13
  signed int v18; // ecx@13
  //Texture *v19; // eax@15
  //double v20; // st6@15
  //double v21; // st7@15
  //double v22; // st6@15
  //unsigned __int8 v23; // sf@15
  //unsigned __int8 v24; // of@15
  stru148 _this; // [sp+14h] [bp-150h]@1
  //double v26; // [sp+120h] [bp-44h]@4
  //float v27; // [sp+128h] [bp-3Ch]@4
  float v28; // [sp+12Ch] [bp-38h]@2
  int v29; // [sp+130h] [bp-34h]@4
  int v30; // [sp+134h] [bp-30h]@1
  //int v31; // [sp+138h] [bp-2Ch]@2
  int v32; // [sp+13Ch] [bp-28h]@6
  int v33; // [sp+140h] [bp-24h]@2
  int v34; // [sp+144h] [bp-20h]@1
  int v35; // [sp+148h] [bp-1Ch]@4
  int v36; // [sp+14Ch] [bp-18h]@2
  int v37; // [sp+154h] [bp-10h]@8
  int v38; // [sp+158h] [bp-Ch]@1
  int v39; // [sp+15Ch] [bp-8h]@4
  int v40; // [sp+160h] [bp-4h]@7
  
  extern bool new_sky;
  if (new_sky)
  {
    if (DrawSkyD3D_Skybox())
    return;
  }

  v30 = ((double)(pOutdoorCamera->int_fov_rad * pIndoorCamera->pos.z)
        / ((double)pOutdoorCamera->int_fov_rad + 8192.0) + pViewport->uScreenCenterY);
  v38 = pViewport->uScreenCenterY - 
        pOutdoorCamera->int_fov_rad / (pOutdoorCamera->shading_dist_mist * cos(pIndoorCamera->sRotationX * 0.003066406352445483) + 0.0000001000000011686097) *
        (pOutdoorCamera->shading_dist_mist * -sin(pIndoorCamera->sRotationX * 0.003066406352445483) - pIndoorCamera->pos.z);
  _this._48607B(&stru_8019C8);
  _this.ptr_38->_48694B();
  _this.uTileBitmapID = pOutdoor->uSky_TextureID;
  _this.pTexture = (Texture *)(SLOWORD(pOutdoor->uSky_TextureID) != -1 ? &pBitmaps_LOD->pTextures[SLOWORD(pOutdoor->uSky_TextureID)] : 0);
  if (pOutdoor->uSky_TextureID == -1)
    return;

  _this.dimming_level = 0;
  _this.uNumVertices = 4;
  _this.v_18.x = -stru_5C6E00->Sin(pIndoorCamera->sRotationX + 16);
  _this.v_18.y = 0;
  _this.v_18.z = -stru_5C6E00->Cos(pIndoorCamera->sRotationX + 16);
  _this.field_24 = 0x2000000;

  _this.sTextureDeltaU = 224 * pMiscTimer->uTotalGameTimeElapsed;
  _this.sTextureDeltaV = 224 * pMiscTimer->uTotalGameTimeElapsed;

  array_50AC10[0].vWorldViewProjX = pViewport->uViewportTL_X;
  array_50AC10[0].vWorldViewProjY = pViewport->uViewportTL_Y;

  array_50AC10[1].vWorldViewProjX = pViewport->uViewportTL_X;
  array_50AC10[1].vWorldViewProjY = v38;

  array_50AC10[2].vWorldViewProjX = pViewport->uViewportBR_X;
  array_50AC10[2].vWorldViewProjY = v38;

  array_50AC10[3].vWorldViewProjX = pViewport->uViewportBR_X;
  array_50AC10[3].vWorldViewProjY = pViewport->uViewportTL_Y;

  //pParty->sRotationY / 2048.0f
    
    float t = (GetTickCount() % 96000) / 96000.0f;
    array_50AC10[0].u = t - pParty->sRotationY / 1024.0f;
    array_50AC10[0].v = t - pParty->sRotationX / 512.0f;
    
    array_50AC10[1].u = t - pParty->sRotationY / 1024.0f;
    array_50AC10[1].v = 1 + t - pParty->sRotationX / 512.0f;

    array_50AC10[2].u = 1 + t - pParty->sRotationY / 1024.0f;
    array_50AC10[2].v = 1 + t - pParty->sRotationX / 512.0f;

    array_50AC10[3].u = 1 + t - pParty->sRotationY / 1024.0f;
    array_50AC10[3].v = t - pParty->sRotationX / 512.0f;

  v36 = (double)(pViewport->uViewportBR_X - pViewport->uViewportTL_X) * 0.5;
  v33 = 65536 / (signed int)(v36 / tan(0.6457717418670654) + 0.5);

  for (uint i = 0; i < _this.uNumVertices; ++i)
  {
    v29 = floorf(array_50AC10[i].vWorldViewProjY + 0.5f);
    v39 = (unsigned __int64)(_this.ptr_38->field_14 * v33 * (v30 - v29)) / 65536;
    v8 = v39 + _this.ptr_38->field_C;

    v39 = (unsigned __int64)(_this.ptr_38->field_20 * v33 * (v30 - v29)) / 65536;
    v36 = v39 + _this.ptr_38->field_18;

    v9 = (unsigned __int64)(_this.v_18.z * v33 * (v30 - v29)) / 65536;
    v10 = _this.v_18.x + v9;
    v39 = _this.v_18.x + v9;
    if ( _this.v_18.x + v9 > 0 )
    {
      v10 = 0;
      v39 = 0;
    }
    //v11 = (signed __int64)array_50AC10[i].vWorldViewProjX;
    v38 = v10;
    v12 = array_50AC10[i].vWorldViewProjY - 1.0;
    v13 = v33 * (pViewport->uScreenCenterX - (signed __int64)array_50AC10[i].vWorldViewProjX);
    v34 = -_this.field_24;
    v32 = (signed __int64)v12;
    v14 = v33 * (v30 - v32);
    while ( 1 )
    {
      //v40 = v14;
      if ( !v10 )
      {
        v37 = _this.v_18.z;
        v16 = (unsigned __int64)(_this.v_18.z * (signed __int64)v14) >> 16;
        --v32;
        v14 += v33;
        v10 = _this.v_18.x + v16;
        v39 = _this.v_18.x + v16;
        v38 = _this.v_18.x + v16;
        break;
      }
      v37 = abs(v34 >> 14);
      v15 = abs(v10);
      if ( v37 <= v15 || v32 <= pViewport->uViewportTL_Y )
      {
        if ( v39 <= 0 )
          break;
      }
      //v14 = v40;
      v37 = _this.v_18.z;
      v16 = (unsigned __int64)(_this.v_18.z * v14) >> 16;
      --v32;
      v14 += v33;
      v10 = _this.v_18.x + v16;
      v39 = _this.v_18.x + v16;
      v38 = _this.v_18.x + v16;
      break;
    }
    LODWORD(v17) = v34 << 16;
    HIDWORD(v17) = v34 >> 16;
    v18 = v17 / v38;
    if ( v18 < 0 )
      v18 = pOutdoorCamera->shading_dist_mist;

    v37 += ((unsigned __int64)(_this.ptr_38->field_10 * v13) >> 16);
    v36 += ((unsigned __int64)(_this.ptr_38->field_1C * v13) >> 16);
    v35 = 224 * pMiscTimer->uTotalGameTimeElapsed + fixpoint_sub0(v37, v18) / 8;
    v36 = 224 * pMiscTimer->uTotalGameTimeElapsed + fixpoint_sub0(v36, v18) / 8;

    //array_50AC10[i].vWorldViewPosition.x = pOutdoorCamera->shading_dist_mist;
    //array_50AC10[i].vWorldPosition.x = v36 / (_this.pTexture->uTextureHeight * 65536.0);
    //array_50AC10[i].vWorldPosition.y = 1.0 / (pOutdoorCamera->shading_dist_mist >> 16);
    //array_50AC10[i].vWorldPosition.z = v35 / (_this.pTexture->uTextureWidth * 65536.0);
    //array_50AC10[i]._rhw = 1.0f / (v18 >> 16);
    //array_50AC10[i].u = (double)v35 / (65536.0 * _this.pTexture->uTextureWidth);
    //array_50AC10[i].v = (double)v36 / (65536.0 * _this.pTexture->uTextureHeight);
    //float t = (GetTickCount() % 96000) / 96000.0f;
    array_50AC10[i]._rhw = 1.0f;
    //array_50AC10[i].u = t;
    //array_50AC10[i].v = t;
  }
    //if ( i  == _this.uNumVertices - 1 )
    //{
      pRenderer->DrawSkyPolygon(_this.uNumVertices, &_this, pBitmaps_LOD->pHardwareTextures[_this.uTileBitmapID]);

      array_50AC10[0].vWorldViewProjY = v38;
      array_50AC10[1].vWorldViewProjY = array_50AC10[1].vWorldViewProjY + 30.0;
      array_50AC10[2].vWorldViewProjY = array_50AC10[2].vWorldViewProjY + 30.0;
      array_50AC10[3].vWorldViewProjY = v38;

      pRenderer->DrawSkyPolygon(_this.uNumVertices, &_this, pBitmaps_LOD->pHardwareTextures[_this.uTileBitmapID]);
      //return;
    //}
}

//----- (00479A53) --------------------------------------------------------
void __fastcall _479A53_draw_some_blv_poly(unsigned int uNumVertices, unsigned int uFaceID)
{
  BLVFace *pFace; // esi@1
  unsigned int v3; // edi@1
  PolygonType v4; // al@1
  double v5; // st7@3
  signed __int64 v6; // qax@3
  PolygonType v7; // cl@3
  int v8; // esi@7
  int v9; // eax@7
  unsigned int v10; // eax@7
  double v11; // st6@7
  int v12; // edx@7
  int v13; // eax@7
  char *v14; // esi@8
  void *v15; // ecx@9
  int v16; // eax@9
  int v17; // edi@9
  double v18; // st7@9
  signed int v19; // ebx@9
  void *v20; // ecx@9
  int v21; // ebx@11
  int v22; // eax@14
  signed __int64 v23; // qtt@16
  double v24; // st7@16
  unsigned __int8 v25; // sf@16
  unsigned __int8 v26; // of@16
  Render *v27; // ecx@17
  double v28; // st7@20
  char *v29; // ebx@20
  char *v30; // edx@20
  unsigned __int8 v31; // c0@21
  unsigned __int8 v32; // c3@21
  double v33; // st6@23
  char *v34; // esi@30
  const void *v35; // ecx@31
  int v36; // eax@31
  const void *v37; // edi@31
  signed __int64 v38; // qax@31
  int v39; // ecx@31
  int v40; // ebx@33
  int v41; // eax@36
  signed __int64 v42; // qtt@39
  int v43; // eax@39
  char v44; // zf@39
  double v45; // st7@39
  double v46; // st7@39
  unsigned int v47; // edx@40
  double v48; // st7@41
  RenderVertexSoft *v49; // ebx@41
  void *v50; // edi@43
  double v51; // st7@46
  RenderVertexSoft *v52; // edx@46
  void *v53; // edi@48
  char *v54; // ebx@52
  unsigned int v55; // eax@53
  unsigned int v56; // eax@55
  int v57; // ST10_4@55
  Texture *v58; // eax@55
  signed int v59; // [sp-4h] [bp-178h]@17
  stru148 *v60; // [sp+0h] [bp-174h]@17
  IDirect3DTexture2 *v61; // [sp+4h] [bp-170h]@17
  stru148 v62; // [sp+14h] [bp-160h]@6
  unsigned int v63; // [sp+120h] [bp-54h]@7
  double v64; // [sp+124h] [bp-50h]@7
  unsigned int v65; // [sp+128h] [bp-4Ch]@1
  unsigned int v66; // [sp+12Ch] [bp-48h]@7
  float v67; // [sp+130h] [bp-44h]@7
  __int64 v68; // [sp+134h] [bp-40h]@3
  __int64 v69; // [sp+13Ch] [bp-38h]@3
  int v70; // [sp+144h] [bp-30h]@3
  int X; // [sp+148h] [bp-2Ch]@9
  int v72; // [sp+14Ch] [bp-28h]@7
  float v73; // [sp+150h] [bp-24h]@16
  unsigned int v74; // [sp+154h] [bp-20h]@3
  RenderVertexSoft *v75; // [sp+158h] [bp-1Ch]@3
  float v76; // [sp+15Ch] [bp-18h]@9
  int v77; // [sp+160h] [bp-14h]@9
  int v78; // [sp+164h] [bp-10h]@7
  void *v79; // [sp+168h] [bp-Ch]@9
  float v80; // [sp+16Ch] [bp-8h]@3
  const void *v81; // [sp+170h] [bp-4h]@7

  __debugbreak();

  pFace = &pIndoor->pFaces[uFaceID];
  v65 = uFaceID;
  v3 = uNumVertices;
  v4 = pFace->uPolygonType;
  if ( v4 == POLYGON_InBetweenFloorAndWall || v4 == POLYGON_Floor )
  {
    if ( (signed int)uNumVertices > 0 )
    {
      v54 = (char *)&array_507D30[0].u;
      LODWORD(v80) = uNumVertices;
      do
      {
        v69 = (GetTickCount() >> 5) - pBLVRenderParams->vPartyPos.x;
        *(float *)v54 = (double)v69 + *(float *)v54;
        *(float *)v54 = *(float *)v54 * 0.25;
        v55 = GetTickCount();
        v54 += 48;
        v44 = LODWORD(v80)-- == 1;
        v68 = pBLVRenderParams->vPartyPos.y + (v55 >> 5);
        *((float *)v54 - 11) = ((double)v68 + *((float *)v54 - 11)) * 0.25;
      }
      while ( !v44 );
      uFaceID = v65;
    }
    v56 = 8 * uFaceID;
    LOBYTE(v56) = PID(OBJECT_BModel,uFaceID);
    v57 = v56;
    v58 = pFace->GetTexture();
    pRenderer->DrawIndoorPolygon(v3, pFace, pBitmaps_LOD->pHardwareTextures[pFace->uBitmapID], v58, v57, -1, 0);
    return;
  }
  HIDWORD(v69) = pIndoorCamera->sRotationX;
  HIDWORD(v68) = pIndoorCamera->pos.z;
  *(float *)&v74 = (double)pBLVRenderParams->uViewportCenterY;
  v70 = (signed __int64)((double)(pBLVRenderParams->field_40 * pBLVRenderParams->vPartyPos.z)
                       / (((double)pBLVRenderParams->field_40 + 16192.0)
                        * 65536.0)
                       + *(float *)&v74);
  v5 = (double)pIndoorCamera->sRotationX * 0.0030664064;
  *(float *)&v75 = v5;
  v80 = cos(v5) * 16192.0;
  v6 = (signed __int64)(*(float *)&v74
                      - (double)pBLVRenderParams->field_40
                      / ((v80 + 0.0000001)
                       * 65535.0)
                      * (sin(*(float *)&v75) * -16192.0 - (double)SHIDWORD(v68)));
  v7 = pFace->uPolygonType;
  if ( v7 == 4 || v7 == 3 )
    v70 = v6;
  stru_8019C8._48653D(65536, 0, 0, 0, 65536, 0);
  v62._48607B(&stru_8019C8);
  v62.uTileBitmapID = pFace->uBitmapID;
  v62.pTexture = (Texture *)((signed __int16)v62.uTileBitmapID != -1 ? &pBitmaps_LOD->pTextures[(signed __int16)v62.uTileBitmapID] : 0);
  if ( !v62.pTexture )
    return;
  v8 = pBLVRenderParams->sPartyRotX;
  v62.dimming_level = 0;
  v62.uNumVertices = v3;
  v9 = stru_5C6E00->Sin(pBLVRenderParams->sPartyRotX + 16);
  v62.v_18.y = 0;
  v62.v_18.x = -v9;
  v62.v_18.z = -stru_5C6E00->Cos(v8 + 16);
  v10 = pBLVRenderParams->uViewportZ - pBLVRenderParams->uViewportX;
  memcpy(&array_507D30[v3], array_507D30, sizeof(array_507D30[v3]));
  LODWORD(v80) = v10;
  v62.field_24 = 33554432;
  v64 = (double)(signed int)v10 * 0.5;
  v72 = 65536 / (signed int)(signed __int64)(v64 / tan(0.6457717418670654) + 0.5);
  LODWORD(v80) = v62.pTexture->uTextureWidth;
  v11 = 1.0 / (double)SLODWORD(v80);
  LODWORD(v80) = v62.pTexture->uTextureHeight;
  v12 = v62.pTexture->uWidthMinus1;
  v13 = v62.pTexture->uHeightMinus1;
  v67 = v11;
  v63 = 224 * pMiscTimer->uTotalGameTimeElapsed & v13;
  v66 = 224 * pMiscTimer->uTotalGameTimeElapsed & v12;
  v78 = 0;
  v81 = 0;
  *((float *)&v68 + 1) = 1.0 / (double)SLODWORD(v80);
  if ( (signed int)v62.uNumVertices <= 0 )
  {
LABEL_17:
    v61 = pBitmaps_LOD->pHardwareTextures[(signed __int16)v62.uTileBitmapID];
    v27 = pRenderer;
    v60 = &v62;
    v59 = v62.uNumVertices;
    goto LABEL_18;
  }
  v14 = (char *)&array_507D30[0].vWorldViewProjY;
  while ( 2 )
  {
    v15 = (void *)(v72 * (v70 - (unsigned __int64)(signed __int64)*(float *)v14));
    LODWORD(v80) = v62.ptr_38->field_14;
    v77 = (unsigned __int64)(SLODWORD(v80) * (signed __int64)(signed int)v15) >> 16;
    v16 = v77 + v62.ptr_38->field_C;
    v77 = (int)v15;
    v74 = v16;
    LODWORD(v80) = v62.ptr_38->field_20;
    v77 = (unsigned __int64)(SLODWORD(v80) * (signed __int64)(signed int)v15) >> 16;
    v79 = v15;
    v75 = (RenderVertexSoft *)(v77 + v62.ptr_38->field_18);
    LODWORD(v80) = v62.v_18.z;
    v79 = (void *)((unsigned __int64)(v62.v_18.z * (signed __int64)(signed int)v15) >> 16);
    v17 = v72 * (pBLVRenderParams->uViewportCenterX - (unsigned __int64)(signed __int64)*((float *)v14 - 1));
    v18 = *(float *)v14 - 1.0;
    v19 = -v62.field_24;
    v77 = -v62.field_24;
    X = (int)((char *)v79 + v62.v_18.x);
    LODWORD(v76) = (signed __int64)v18;
    v20 = (void *)(v72 * (v70 - LODWORD(v76)));
    while ( 1 )
    {
      v79 = v20;
      if ( !X )
        goto LABEL_14;
      v21 = abs(v19 >> 14);
      if ( v21 <= abs(X) )
        break;
      if ( SLODWORD(v76) <= (signed int)pViewport->uViewportTL_Y )
        break;
      v19 = v77;
      v20 = v79;
LABEL_14:
      LODWORD(v80) = v62.v_18.z;
      v79 = (void *)((unsigned __int64)(v62.v_18.z * (signed __int64)(signed int)v20) >> 16);
      v22 = (unsigned __int64)(v62.v_18.z * (signed __int64)(signed int)v20) >> 16;
      --LODWORD(v76);
      v20 = (char *)v20 + v72;
      X = v22 + v62.v_18.x;
      v78 = 1;
    }
    if ( !v78 )
    {
      LODWORD(v23) = v77 << 16;
      HIDWORD(v23) = v77 >> 16;
      v79 = (void *)(v23 / X);
      v77 = v17;
      LODWORD(v80) = v62.ptr_38->field_10;
      v77 = v17;
      LODWORD(v76) = v74 + ((unsigned __int64)(SLODWORD(v80) * (signed __int64)v17) >> 16);
      LODWORD(v80) = v62.ptr_38->field_1C;
      v75 = (RenderVertexSoft *)((char *)v75 + ((unsigned __int64)(SLODWORD(v80) * (signed __int64)v17) >> 16));
      v77 = (unsigned __int64)(SLODWORD(v76) * v23 / X) >> 16;
      LODWORD(v73) = (unsigned __int64)((signed int)v75 * v23 / X) >> 16;
      v14 += 48;
      LODWORD(v80) = v66 + ((signed int)((unsigned __int64)(SLODWORD(v76) * v23 / X) >> 16) >> 4);
      v81 = (char *)v81 + 1;
      v24 = (double)SLODWORD(v80) * 0.000015259022;
      LODWORD(v80) = v63 + ((signed int)((unsigned __int64)((signed int)v75 * v23 / X) >> 16) >> 4);
      v26 = __OFSUB__((int)v81, v62.uNumVertices);
      v25 = (signed int)((char *)v81 - v62.uNumVertices) < 0;
      *((float *)v14 - 10) = v24 * v67;
      *((float *)v14 - 9) = (double)SLODWORD(v80) * 0.000015259022 * *((float *)&v68 + 1);
      *((float *)v14 - 11) = 65536.0 / (double)(signed int)v79;
      if ( !(v25 ^ v26) )
        goto LABEL_17;
      continue;
    }
    break;
  }
  LODWORD(v73) = 0;
  v80 = v76;
  if ( (signed int)v62.uNumVertices > 0 )
  {
    v28 = (double)SLODWORD(v76);
    LODWORD(v76) = (int)(char *)array_50AC10 + 28;
    v29 = (char *)&array_50AC10[0].vWorldViewProjX;
    v30 = (char *)&array_507D30[1].vWorldViewProjY;
    v79 = array_50AC10;
    v81 = array_507D30;
    v78 = v62.uNumVertices;
    do
    {
      v31 = v28 < *((float *)v30 - 12);
      v32 = v28 == *((float *)v30 - 12);
      ++LODWORD(v73);
      memcpy(v79, v81, 0x30u);
      v79 = (char *)v79 + 48;
      LODWORD(v76) += 48;
      v29 += 48;
      if ( v31 | v32 || v28 >= *(float *)v30 )
      {
        if ( v28 >= *((float *)v30 - 12) || v28 <= *(float *)v30 )
          goto LABEL_28;
        v33 = (*((float *)v30 - 1) - *((float *)v30 - 13)) * v28 / (*(float *)v30 - *((float *)v30 - 12))
            + *((float *)v30 - 1);
      }
      else
      {
        v33 = (*((float *)v30 - 13) - *((float *)v30 - 1)) * v28 / (*((float *)v30 - 12) - *(float *)v30)
            + *((float *)v30 - 13);
      }
      *(float *)v29 = v33;
      v79 = (char *)v79 + 48;
      v29 += 48;
      ++LODWORD(v73);
      *(unsigned int *)LODWORD(v76) = v28;
      LODWORD(v76) += 48;
LABEL_28:
      v81 = (char *)v81 + 48;
      v30 += 48;
      --v78;
    }
    while ( v78 );
  }
  if ( SLODWORD(v73) <= 0 )
    goto LABEL_40;
  v34 = (char *)&array_50AC10[0].vWorldViewProjY;
  v65 = v77 >> 14;
  HIDWORD(v69) = LODWORD(v73);
  do
  {
    v35 = (const void *)(v72 * (v70 - (unsigned __int64)(signed __int64)*(float *)v34));
    v78 = v62.ptr_38->field_14;
    v81 = (const void *)((unsigned __int64)(v78 * (signed __int64)(signed int)v35) >> 16);
    v36 = (int)((char *)v81 + v62.ptr_38->field_C);
    v81 = v35;
    v74 = v36;
    v78 = v62.ptr_38->field_20;
    v81 = (const void *)((unsigned __int64)(v78 * (signed __int64)(signed int)v35) >> 16);
    v78 = (int)v35;
    v75 = (RenderVertexSoft *)((char *)v81 + v62.ptr_38->field_18);
    v81 = (const void *)v62.v_18.z;
    v78 = (unsigned __int64)(v62.v_18.z * (signed __int64)(signed int)v35) >> 16;
    v37 = (const void *)(v72
                       * (pBLVRenderParams->uViewportCenterX - (unsigned __int64)(signed __int64)*((float *)v34 - 1)));
    v38 = (signed __int64)(*(float *)v34 - 1.0);
    v81 = 0;
    LODWORD(v76) = v38;
    v39 = v72 * (v70 - v38);
    while ( 1 )
    {
      v78 = v39;
      if ( !X )
        goto LABEL_36;
      v40 = abs(X);
      if ( abs((signed __int64)v65) <= v40 )
        break;
      if ( SLODWORD(v76) <= (signed int)pViewport->uViewportTL_Y )
        break;
      v39 = v78;
LABEL_36:
      v78 = v62.v_18.z;
      v41 = (unsigned __int64)(v62.v_18.z * (signed __int64)v39) >> 16;
      --LODWORD(v76);
      v39 += v72;
      X = v41 + v62.v_18.x;
      v81 = (const void *)1;
    }
    if ( v81 )
    {
      v79 = (void *)v62.v_18.z;
      v78 = 2 * LODWORD(v76);
      v81 = (const void *)((unsigned __int64)(v62.v_18.z
                                            * (signed __int64)(signed int)(signed __int64)(((double)v70
                                                                                          - ((double)(2 * LODWORD(v76))
                                                                                           - *(float *)v34))
                                                                                         * (double)v72)) >> 16);
      X = (int)((char *)v81 + v62.v_18.x);
    }
    LODWORD(v42) = v77 << 16;
    HIDWORD(v42) = v77 >> 16;
    v79 = (void *)(v42 / X);
    v81 = v37;
    v78 = v62.ptr_38->field_10;
    v81 = (const void *)((unsigned __int64)(v78 * (signed __int64)(signed int)v37) >> 16);
    v43 = v74 + ((unsigned __int64)(v78 * (signed __int64)(signed int)v37) >> 16);
    v74 = (unsigned int)v37;
    LODWORD(v76) = v43;
    v78 = v62.ptr_38->field_1C;
    v75 = (RenderVertexSoft *)((char *)v75 + ((unsigned __int64)(v78 * (signed __int64)(signed int)v37) >> 16));
    v74 = (unsigned __int64)(v43 * v42 / X) >> 16;
    v81 = (const void *)((unsigned __int64)((signed int)v75 * v42 / X) >> 16);
    v34 += 48;
    v78 = v66 + ((signed int)v74 >> 4);
    v44 = HIDWORD(v69)-- == 1;
    v45 = (double)v78 * 0.000015259022;
    v78 = v63 + ((signed int)((unsigned __int64)((signed int)v75 * v42 / X) >> 16) >> 4);
    *((float *)v34 - 10) = v45 * v67;
    *((float *)v34 - 9) = (double)v78 * 0.000015259022 * *((float *)&v68 + 1);
    v46 = (double)(signed int)v79;
    *((float *)v34 - 16) = 0.000015258789 * v46;
    *((float *)v34 - 11) = 65536.0 / v46;
  }
  while ( !v44 );
LABEL_40:
  v47 = 0;
  if ( SLODWORD(v73) > 0 )
  {
    v48 = (double)SLODWORD(v80);
    v75 = array_507D30;
    v49 = array_50AC10;
    HIDWORD(v69) = LODWORD(v73);
    do
    {
      if ( v48 >= v49->vWorldViewProjY )
      {
        v50 = v75;
        ++v47;
        ++v75;
        memcpy(v50, v49, 0x30u);
      }
      ++v49;
      --HIDWORD(v69);
    }
    while ( HIDWORD(v69) );
  }
  v62.uNumVertices = v47;
  pRenderer->_4A2ED5(v47, &v62, pBitmaps_LOD->pHardwareTextures[(signed __int16)v62.uTileBitmapID]);
  *(float *)&v74 = 0.0;
  if ( SLODWORD(v73) > 0 )
  {
    v51 = (double)SLODWORD(v80);
    v75 = array_507D30;
    v52 = array_50AC10;
    v80 = v73;
    do
    {
      if ( v51 <= v52->vWorldViewProjY )
      {
        v53 = v75;
        ++v74;
        ++v75;
        memcpy(v53, v52, 0x30u);
      }
      ++v52;
      --LODWORD(v80);
    }
    while ( v80 != 0.0 );
  }
  v62.uNumVertices = v74;
  v61 = pBitmaps_LOD->pHardwareTextures[(signed __int16)v62.uTileBitmapID];
  v60 = &v62;
  v59 = v74;
  v27 = pRenderer;
LABEL_18:
  v27->_4A2ED5(v59, v60, v61);
}

//----- (0047A384) --------------------------------------------------------
void ODM_LoadAndInitialize(const char *pLevelFilename, OutdoorCamera *thisa)
{
  int v2; // ebx@3
  unsigned int v3; // eax@3
  MapInfo *v4; // edi@4
  //int v5; // eax@8
  //SpawnPointMM7 *v6; // edx@14
  size_t v7; // eax@19
  char *v8; // eax@19
  char *v9; // eax@21
  char Source[120]; // [sp+Ch] [bp-84h]@19
  const char *pFilename; // [sp+84h] [bp-Ch]@1
  //unsigned int v12; // [sp+88h] [bp-8h]@12
  //int v13; // [sp+8Ch] [bp-4h]@11

  pFilename = pLevelFilename;
  thisa->AllocSoftwareDrawBuffers();
  pOutdoorCamera->_485F64();
  pWeather->bRenderSnow = 0;
  pRenderer->ClearZBuffer(0, 479);
  thisa = (OutdoorCamera *)1;
  GetAlertStatus();
  if ( qword_A750D8 )
    qword_A750D8 = 0i64;
  v2 = pMapStats->GetMapInfo(pCurrentMapName);
  v3 = 0;
  if ( v2 )
  {
    v4 = &pMapStats->pInfos[v2];
    v3 = v4->uRespawnIntervalDays;
  }
  else
  {
    v4 = (MapInfo *)thisa;
  }
  day_attrib &= ~DAY_ATTRIB_FOG;
  dword_6BE13C_uCurrentlyLoadedLocationID = v2;
  pOutdoor->Initialize(
    pFilename,
    (unsigned int)(signed __int64)((double)(signed __int64)pParty->uTimePlayed * 0.234375) / 0x3C / 0x3C / 0x18 + 1,
    v3,
    (int)&thisa);
  if ( !(BYTE1(dword_6BE364_game_settings_1) & 0x20) )
  {
    InitializeActors();
    InitializeSpriteObjects();
  }
  BYTE1(dword_6BE364_game_settings_1) &= 0xDFu;
  //v5 = 0;
  if ( !v2 )
    thisa = 0;
  if ( thisa == (OutdoorCamera *)1 )
  {
    //v13 = 0;
    for (uint i = 0; i < pOutdoor->uNumSpawnPoints; ++i)
    {
      //v12 = 0;
      //while ( 1 )
      //{
      auto spawn = pOutdoor->pSpawnPoints + i;
        //v6 = &pOutdoor->pSpawnPoints[v12 / 0x18];
      if (spawn->uKind == 3 )
        SpawnEncounter(v4, spawn, 0, 0, 0);
      else
        v4->SpawnRandomTreasure(spawn);
        //++v13;
        //v12 += 24;
        //if ( v13 >= (signed int)pOutdoor->uNumSpawnPoints )
        //  break;
        //v5 = 0;
      //}
    }
    RespawnGlobalDecorations();
  }
  pOutdoor->PrepareDecorations();
  pOutdoor->_47F223_LooksLikeGenerateMonsterLoot();
  pOutdoor->InitalizeActors(v2);
  pOutdoor->MessWithLUN();
  v7 = strlen("levels\\");
  strcpy(Source, &pFilename[v7]);
  strcpy(pOutdoor->pLevelFilename, Source);
  pWeather->Initialize();
  pIndoorCamera->sRotationY = pParty->sRotationY;
  pIndoorCamera->sRotationX = pParty->sRotationX;
  pOutdoorCamera->RotationToInts();
  pOutdoor->UpdateSunlightVectors();
  pOutdoorCamera->int_fov_rad = (signed __int64)pIndoorCamera->flt_1C_fov;
  pOutdoorCamera->int_fov_rad_inv = (signed __int64)pIndoorCamera->flt_20_inv_1C;
  v8 = (char *)&array_77EC08[0].ptr_38;
  do
  {
    *(int *)v8 = (int)&stru_8019C8;
    v8 += 268;
  }
  while ( (signed int)v8 < (signed int)&unk_801A00 );
  v9 = (char *)&array_77EC08[0].prolly_tail;
  do
  {
    *((int *)v9 - 1) = 0;
    *(int *)v9 = 0;
    *((int *)v9 - 5) = 0;
    v9 += 268;
  }
  while ( (signed int)v9 < (signed int)&unk_801A0C );
  MM7Initialization();
}

//----- (0047A825) --------------------------------------------------------
bool LevelDecoration::_47A825()
{
  bool v1; // ebx@1
  LevelDecoration *v2; // edi@1

  v1 = 0;
  v2 = this;
  if ( pParty->uCurrentHour >= 1 || (unsigned __int16)_449B57_test_bit(pParty->_quest_bits, 178) )
  {
    v1 = 0;
  }
  else
  {
    if ( (unsigned __int16)_449B57_test_bit(pParty->_quest_bits, 164)
      && (unsigned __int16)_449B57_test_bit(pParty->_quest_bits, 165)
      && (unsigned __int16)_449B57_test_bit(pParty->_quest_bits, 166)
      && (unsigned __int16)_449B57_test_bit(pParty->_quest_bits, 167)
      && (unsigned __int16)_449B57_test_bit(pParty->_quest_bits, 168)
      && (unsigned __int16)_449B57_test_bit(pParty->_quest_bits, 169)
      && (unsigned __int16)_449B57_test_bit(pParty->_quest_bits, 170)
      && (unsigned __int16)_449B57_test_bit(pParty->_quest_bits, 171)
      && (unsigned __int16)_449B57_test_bit(pParty->_quest_bits, 172)
      && (unsigned __int16)_449B57_test_bit(pParty->_quest_bits, 173)
      && (unsigned __int16)_449B57_test_bit(pParty->_quest_bits, 174)
      && (unsigned __int16)_449B57_test_bit(pParty->_quest_bits, 175)
      && (unsigned __int16)_449B57_test_bit(pParty->_quest_bits, 176)
      && (unsigned __int16)_449B57_test_bit(pParty->_quest_bits, 177) )
    {
      v1 = 1;
      LOBYTE(v2->field_2) &= 0xDFu;
      return v1;
    }
  }
  LOBYTE(v2->field_2) |= 0x20u;
  return v1;
}

//----- (0047BC6F) --------------------------------------------------------
unsigned __int16 *__fastcall GetBillboardPalette(RenderBillboard *a1, int a2, signed int a3, int a4)
{
  int v4; // ebx@1
  int v6; // edx@4
  int v7; // ecx@5
  signed int v8; // eax@6
  signed __int64 v9; // qtt@11
  signed int v10; // eax@12
  int v11; // esi@17
  signed __int64 v12; // qtt@19
  double v13; // ST10_8@19
  int v14; // edi@25
  signed int v15; // edx@26
  signed __int64 v16; // qtt@29
  signed int v17; // eax@30
  int v18; // [sp+10h] [bp-8h]@1
  float a3a; // [sp+20h] [bp+8h]@19

  v4 = a2;
  v18 = a2;
  if ( pParty->armageddon_timer )
    return PaletteManager::Get(a2);
  if ( !pWeather->bNight )
  {
    if (day_attrib & DAY_ATTRIB_FOG)
    {
      v14 = day_fogrange_1 << 16;
      if ( a3 >= day_fogrange_1 << 16 )
      {
        if ( a3 <= day_fogrange_2 << 16 )
        {
          LODWORD(v16) = (a3 - v14) << 16;
          HIDWORD(v16) = (a3 - v14) >> 16;
          v15 = (unsigned __int64)(27 * v16 / ((day_fogrange_2 - day_fogrange_1) << 16)) >> 16;
        }
        else
        {
          v15 = 27;
        }
      }
      else
      {
        v15 = 0;
      }
      v17 = _43F55F_get_billboard_light_level(a1, v15);
      if ( v17 > 27 )
        v17 = 27;
      if ( !a3 )
        v17 = 27;
      v7 = v18;
      v6 = v17;
      return (unsigned __int16 *)PaletteManager::Get_Mist_or_Red_LUT(v7, v6, 1);
    }
    v11 = a4;
    if ( a4 < 0 )
      v11 = 0;
    LODWORD(v12) = a3 << 16;
    HIDWORD(v12) = a3 >> 16;
    a3a = (double)(signed int)(((unsigned __int64)(11 * v12 / (pOutdoorCamera->shading_dist_shade << 16)) >> 16) + 20)
        * pOutdoor->fFogDensity;
    v13 = a3a + 6.7553994e15;
    v10 = _43F55F_get_billboard_light_level(a1, LODWORD(v13) + v11);
    if ( v10 > 27 )
      v10 = 27;
    if ( v10 < a4 )
      v10 = a4;
    if ( v10 > pOutdoor->max_terrain_dimming_level )
      v10 = pOutdoor->max_terrain_dimming_level;
    return PaletteManager::Get_Dark_or_Red_LUT(v4, v10, 1);
  }
  v6 = 0;
  if (pWeather->bNight)
  {
    v8 = 67108864;
    if ( (signed __int64)pParty->pPartyBuffs[16].uExpireTime > 0 )
      v8 = pParty->pPartyBuffs[16].uPower << 26;
    if ( a3 <= v8 )
    {
      if ( a3 > 0 )
      {
        LODWORD(v9) = a3 << 16;
        HIDWORD(v9) = a3 >> 16;
        v6 = (unsigned __int64)(27 * v9 / v8) >> 16;
      }
    }
    else
    {
      v6 = 27;
    }
    v10 = _43F55F_get_billboard_light_level(a1, v6);
    if ( v10 > 27 || !a3 )
      v10 = 27;
    return PaletteManager::Get_Dark_or_Red_LUT(v4, v10, 1);
  }
  v7 = 0;
  return (unsigned __int16 *)PaletteManager::Get_Mist_or_Red_LUT(v7, v6, 1);
}
// 6BE030: using guessed type int day_attrib;
// 6BE040: using guessed type int day_fogrange_1;
// 6BE044: using guessed type int day_fogrange_2;

//----- (0047BEB1) --------------------------------------------------------
int __fastcall sr_sub_47BEB1(signed int a1, stru148 *a2, int terrain_gamma, int a4, int *a5, int *a6, int a7, int a8)
{
  stru148 *v8; // ebx@1
  signed int v9; // edx@1
  int v10; // eax@5
  signed int v11; // eax@9
  signed int v12; // eax@15
  signed __int64 v13; // qtt@21
  int *v14; // ecx@30
  int *v15; // edi@30
  int v16; // ebx@32
  signed __int64 v17; // qtt@37
  double v18; // ST10_8@37
  double v19; // ST10_8@38
  int v20; // edi@39
  int result; // eax@46
  int *v22; // eax@48
  signed int v23; // edx@51
  signed __int64 v24; // qtt@51
  int v25; // ecx@51
  signed int v26; // [sp+14h] [bp-4h]@1
  float v27; // [sp+28h] [bp+10h]@37
  float v28; // [sp+28h] [bp+10h]@38
  int v29; // [sp+2Ch] [bp+14h]@37

  v8 = a2;
  v9 = a1;
  v26 = a1;
  if ( pParty->armageddon_timer )
  {
    *a5 = -1;
    *a6 = -1;
    *(char *)a7 = 1;
LABEL_46:
    result = a8;
    *(char *)a8 = 0;
    return result;
  }
  if ( a1 < 0 )
  {
    v26 = v8->field_34 << 16;
    v9 = v8->field_34 << 16;
  }
  v10 = pWeather->bNight;
  if ( bUnderwater == 1 )
    v10 = 0;
  if ( !v10 )
  {
    if ( !(day_attrib & DAY_ATTRIB_FOG) && !bUnderwater )
    {
      v14 = a5;
      v15 = a6;
      if ( !v9 )
      {
        *a5 = 31;
        *a6 = -1;
      }
      v16 = v8->dimming_level - terrain_gamma;
      if ( v16 >= 0 )
      {
        if ( v16 > 27 )
          v16 = 27;
      }
      else
      {
        v16 = 0;
      }
      *a6 = 27;
      if ( a4 )
      {
        v28 = pOutdoor->fFogDensity * 27.0;
        v19 = v28 + 6.7553994e15;
        v29 = LODWORD(v19);
      }
      else
      {
        LODWORD(v17) = v9 << 16;
        HIDWORD(v17) = v9 >> 16;
        v27 = (double)(signed int)(((unsigned __int64)(v17 / (pOutdoorCamera->shading_dist_shade << 16) * (31 - *a6)) >> 16)
                                 + *a6)
            * pOutdoor->fFogDensity;
        v18 = v27 + 6.7553994e15;
        v29 = LODWORD(v18);
      }
      *v14 = v16 + v29;
      v20 = *v15;
      if ( v16 + v29 > v20 )
        *v14 = v20;
      if ( *v14 < v16 )
        *v14 = v16;
      if ( *v14 > pOutdoor->max_terrain_dimming_level )
        *v14 = pOutdoor->max_terrain_dimming_level;
      goto LABEL_45;
    }
    if ( v9 >= day_fogrange_1 << 16 )
    {
      if ( v9 <= day_fogrange_2 << 16 )
      {
        v23 = v9 - (day_fogrange_1 << 16);
        LODWORD(v24) = v23 << 16;
        HIDWORD(v24) = v23 >> 16;
        v25 = (unsigned __int64)(27 * v24 / ((day_fogrange_2 - day_fogrange_1) << 16)) >> 16;
        v22 = a5;
        *a5 = v25;
        if ( v25 > 27 )
          goto LABEL_54;
        v9 = v26;
      }
      else
      {
        v22 = a5;
        *a5 = 27;
      }
    }
    else
    {
      v22 = a5;
      *a5 = 0;
    }
    if ( v9 )
    {
LABEL_55:
      if ( a4 )
        *v22 = 31;
      *a6 = 31;
      *(char *)a7 = 0;
      goto LABEL_59;
    }
LABEL_54:
    *v22 = 27;
    goto LABEL_55;
  }
  if ( v10 == 1 )
  {
    v11 = 1;
    if ( byte_4D864C && BYTE1(pGame->uFlags) & 0x10 )
    {
      v12 = 0;
    }
    else
    {
      if ( (signed __int64)pParty->pPartyBuffs[16].uExpireTime > 0 )
      {
        if ( (signed __int64)pParty->pPartyBuffs[16].uExpireTime <= 0 )
          v11 = 0;
        else
          v11 = pParty->pPartyBuffs[16].uPower;
      }
      v12 = v11 << 26;
    }
    if ( a4 )
      goto LABEL_24;
    if ( v9 <= v12 )
    {
      if ( v9 > 0 )
      {
        LODWORD(v13) = v9 << 16;
        HIDWORD(v13) = v9 >> 16;
        v9 = v26;
        *a5 = (unsigned __int64)(27 * v13 / v12) >> 16;
      }
      if ( *a5 > 27 )
        goto LABEL_24;
    }
    else
    {
      *a5 = 27;
    }
    if ( v9 )
    {
LABEL_25:
      if ( v8->field_32 & 4 )
        *a5 = 27;
      *a6 = 27;
LABEL_45:
      *(char *)a7 = 0;
      goto LABEL_46;
    }
LABEL_24:
    *a5 = 27;
    goto LABEL_25;
  }
  *a5 = -1;
  *a6 = -1;
  *(char *)a7 = 1;
LABEL_59:
  result = a8;
  *(char *)a8 = 1;
  return result;
}

//----- (0047C178) --------------------------------------------------------
void *__fastcall sr_sub_47C178(signed int a1, stru148 *a2, int terrain_gamma, int a4)
{
  stru148 *v4; // esi@1
  void *result; // eax@2
  int v6; // [sp+4h] [bp-8h]@3
  int v7; // [sp+8h] [bp-4h]@3

  v4 = a2;
  if ( pParty->armageddon_timer )
  {
    result = PaletteManager::Get(a2->pTexture->palette_id2);
  }
  else
  {
    sr_sub_47BEB1(a1, a2, terrain_gamma, a4, &v6, &v7, (int)((char *)&terrain_gamma + 3), (int)((char *)&a4 + 3));
    result = sr_sub_47C1CA(v4, SBYTE3(a4), v6, v7);
  }
  return result;
}

//----- (0047C1CA) --------------------------------------------------------
void *__fastcall sr_sub_47C1CA(stru148 *a1, char a2, int a3, signed int a4)
{
  stru148 *v4; // esi@1
  void *result; // eax@2
  int v6; // edx@3
  int v7; // ecx@8
  int a3a; // [sp+4h] [bp-8h]@1
  char v9; // [sp+8h] [bp-4h]@1

  v9 = a2;
  v4 = a1;
  a3a = 1;
  if ( pParty->armageddon_timer )
  {
    result = PaletteManager::Get(a1->pTexture->palette_id2);
  }
  else
  {
    v6 = pGame->_44EC23(a1, &a3a, a4);
    if ( v6 == -1 )
      v6 = a3;
    if ( v9 == 1 )
    {
      if ( v6 != -1 || a4 != -1 )
      {
        v7 = v4->pTexture->palette_id2;
      }
      else
      {
        v6 = 0;
        v7 = 0;
      }
      result = PaletteManager::Get_Mist_or_Red_LUT(v7, v6, a3a);
    }
    else
    {
      result = PaletteManager::Get_Dark_or_Red_LUT(v4->pTexture->palette_id2, v6, a3a);
    }
  }
  return result;
}

//----- (0047C24C) --------------------------------------------------------
unsigned __int16 *__fastcall sr_sub_47C24C_get_palette(BLVFace *a1, int a2, int a3, char a4)
{
  int v4; // esi@1
  int v5; // eax@2
  int a3a; // [sp+4h] [bp-4h]@1

  v4 = a2;
  a3a = 1;
  if ( a4 )
  {
    v5 = pGame->_44ED0A(a1, &a3a, 31);
    if ( v5 != -1 )
      a3 = v5;
  }
  return PaletteManager::Get_Dark_or_Red_LUT(v4, a3, a3a);
}

//----- (0047C28C) --------------------------------------------------------
char *__fastcall sr_sub_47C28C_get_palette(stru148 *a1, char a2, signed int a3, signed int a4)
{
  stru148 *v4; // esi@1
  char *result; // eax@2
  signed int v6; // eax@3
  int v7; // ecx@8
  int a2a; // [sp+4h] [bp-8h]@1
  char v9; // [sp+8h] [bp-4h]@1

  v9 = a2;
  v4 = a1;
  a2a = 1;
  if ( pParty->armageddon_timer )
  {
    result = (char *)pPaletteManager->field_199600_palettes[a1->pTexture->palette_id2];
  }
  else
  {
    v6 = pGame->_44EC23(a1, &a2a, a4);
    if ( v6 != -1 )
      a3 = v6;
    if ( v9 == 1 )
    {
      if ( a3 != -1 || a4 != -1 )
        v7 = v4->pTexture->palette_id2;
      else
        v7 = 0;
      result = (char *)PaletteManager::_47C30E_get_palette(v7, a2a);
    }
    else
    {
      result = (char *)PaletteManager::_47C33F_get_palette(v4->pTexture->palette_id2, a2a);
    }
  }
  return result;
}
// 4D864C: using guessed type char byte_4D864C;

//----- (0047C370) --------------------------------------------------------
unsigned int __cdecl GetLevelFogColor()
{
  unsigned int result; // eax@2
  signed __int64 v1; // qax@5
  int v2; // eax@6

  if ( bUnderwater )
  {
    result = 0xFF258F5C;
  }
  else
  {
    if (day_attrib & DAY_ATTRIB_FOG)
    {
      if ( pWeather->bNight ) // night-time fog
      {
        __debugbreak(); // decompilation can be inaccurate, please  send savegame to Nomad
        v2 = -(pWeather->bNight != 1);
        result = (v2 & 0xE0E0E1) - 0xE0E0E1;
      }
      else
      {
        v1 = (signed __int64)((1.0 - pOutdoor->fFogDensity) * 200.0 + pOutdoor->fFogDensity * 31.0);
        result = v1 | (((unsigned int)v1 | (((unsigned int)v1 | 0xFFFFFF00) << 8)) << 8);
      }
    }
    else
      return 0;
  }
  return result;
}
// 6BE030: using guessed type int day_attrib;
// 6BE3C4: using guessed type char bUnderwater;

//----- (0047C3D7) --------------------------------------------------------
int __fastcall sub_47C3D7_get_fog_related_stuff(int a1, int a2, float a3)
{
  int v3; // ecx@1
  double v5; // st7@10
  signed int v6; // esi@10
  signed int v7; // ecx@11
  double v8; // st6@12
  double v9; // st7@15
  double v10; // st6@16
  float v11; // ST14_4@17
  double v12; // ST08_8@17

  v3 = pWeather->bNight;
  if ( bUnderwater == 1 )
    v3 = 0;
  if ( pParty->armageddon_timer || !(day_attrib & DAY_ATTRIB_FOG) && !bUnderwater )
    return 0xFF000000;
  if ( v3 )
  {
    v5 = (double)day_fogrange_1;
    v6 = 216;
    if ( a3 < v5 )
      goto LABEL_11;
    v8 = (double)day_fogrange_2;
    if ( a3 > v8 )
    {
LABEL_13:
      v7 = v6;
      goto LABEL_19;
    }
    v7 = (signed __int64)((a3 - v5) / (v8 - v5) * 216.0);
  }
  else
  {
    v9 = (double)day_fogrange_1;
    v6 = 216;
    if ( a3 < v9 )
    {
LABEL_11:
      v7 = 0;
      goto LABEL_19;
    }
    v10 = (double)day_fogrange_2;
    if ( a3 > v10 )
      goto LABEL_13;
    v11 = (a3 - v9) * 216.0 / (v10 - v9);
    v12 = v11 + 6.7553994e15;
    v7 = LODWORD(v12);
  }
  if ( v7 > v6 )
  {
LABEL_20:
    v7 = v6;
    goto LABEL_21;
  }
LABEL_19:
  if ( a3 == 0.0 )
    goto LABEL_20;
LABEL_21:
  if ( a2 )
    v7 = 248;
  return (-1 - v7) << 24;
}

//----- (0047C4FC) --------------------------------------------------------
signed int __fastcall GetActorTintColor(int max_dimm, int min_dimm, float distance, int a4, RenderBillboard *a5)
{
  //int v5; // esi@1
  signed int v6; // edx@1
  //signed int result; // eax@2
  int v8; // eax@3
  double v9; // st7@12
  //double v10; // ST0C_8@18
  int v11; // ecx@28
  //signed int v12; // edi@28
  //double v13; // ST0C_8@33
  //double v14; // ST0C_8@34
  double v15; // st7@44
  //double v16; // ST0C_8@44
  //double v17; // ST0C_8@44
  int v18; // ST14_4@44
  //double v19; // ST0C_8@44
  signed int v20; // [sp+10h] [bp-4h]@10
  float a3a; // [sp+1Ch] [bp+8h]@33
  //float a3b; // [sp+1Ch] [bp+8h]@34
  float a3c; // [sp+1Ch] [bp+8h]@44
  //float a3d; // [sp+1Ch] [bp+8h]@44
  //float a4b; // [sp+20h] [bp+Ch]@18
  //int a4a; // [sp+20h] [bp+Ch]@33
  //float a4c; // [sp+20h] [bp+Ch]@44
  //float a4d; // [sp+20h] [bp+Ch]@44
  int a5a; // [sp+24h] [bp+10h]@44

  //v5 = a2;
  v6 = 0;

  if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
    return 8 * (31 - max_dimm) | ((8 * (31 - max_dimm) | ((31 - max_dimm) << 11)) << 8);

  if (pParty->armageddon_timer)
    return 0xFFFF0000;

  v8 = pWeather->bNight;
  if (bUnderwater)
    v8 = 0;
  if ( v8 )
  {
    v20 = 1;
    if ( (signed __int64)pParty->pPartyBuffs[PARTY_BUFF_TORCHLIGHT].uExpireTime > 0 )
      v20 = pParty->pPartyBuffs[PARTY_BUFF_TORCHLIGHT].uPower;
    v9 = (double)v20 * 1024.0;
    if ( a4 )
      goto LABEL_19;
    if ( distance <= v9 )
    {
      if ( distance > 0.0 )
      {
        //a4b = distance * 216.0 / v9;
        //v10 = a4b + 6.7553994e15;
        //v6 = LODWORD(v10);
        v6 = floorf(0.5f + distance * 216.0 / v9);
        if (v6 > 216 )
          goto LABEL_19;
      }
    }
    else
    {
      v6 = 216;
    }
    if ( distance != 0.0 )
    {
LABEL_20:
      if ( a5 )
        v6 = 8 * _43F55F_get_billboard_light_level(a5, v6 >> 3);
      if ( v6 > 216 )
        v6 = 216;
      return (255 - v6) | ((255 - v6) << 16) | ((255 - v6) << 8);
    }
LABEL_19:
    v6 = 216;
    goto LABEL_20;
  }



  if (fabsf(distance) < 1.0e-6f)
    return 0xFFF8F8F8;

  // dim in measured in 8-steps
  v11 = 8 * (max_dimm - min_dimm);
    //v12 = v11;
    if ( v11 >= 0 )
    {
      if ( v11 > 216 )
        v11 = 216;
    }
    else
      v11 = 0;

    float fog_density_mult = 216.0f;
    if (a4)
      fog_density_mult += distance / (double)pOutdoorCamera->shading_dist_shade * 32.0;

    v6 = v11 + floorf(pOutdoor->fFogDensity * fog_density_mult + 0.5f);
    /*if ( a4 )
    {
      //a3b = pOutdoor->fFogDensity * 216.0;
      //v14 = a3b + 6.7553994e15;
      //a4a = floorf(a3b + 0.5f);//LODWORD(v14);
    }
    else
    {
      //a3a = (distance / (double)pOutdoorCamera->shading_dist_shade * 32.0 + 216.0) * pOutdoor->fFogDensity;
      //v13 = a3a + 6.7553994e15;
      //a4a = floorf(a3a + 0.5f);//LODWORD(v13);
    }
    v6 = a4a + v11;*/
    if ( a5 )
      v6 = 8 * _43F55F_get_billboard_light_level(a5, v6 >> 3);
    if ( v6 > 216 )
      v6 = 216;
    if ( v6 < v11 )
      v6 = v11;
    if ( v6 > 8 * pOutdoor->max_terrain_dimming_level )
      v6 = 8 * pOutdoor->max_terrain_dimming_level;
    if ( !bUnderwater )
      return (255 - v6) | ((255 - v6) << 16) | ((255 - v6) << 8);
    else
    {
    v15 = (double)(255 - v6) * 0.0039215689;
    a3c = v15;
    //a4c = v15 * 16.0;
    //v16 = a4c + 6.7553994e15;
    a5a = floorf(v15 * 16.0 + 0.5f);//LODWORD(v16);
    //a4d = a3c * 194.0;
    //v17 = a4d + 6.7553994e15;
    v18 = floorf(a3c * 194.0 + 0.5f);//LODWORD(v17);
    //a3d = a3c * 153.0;
    //v19 = a3d + 6.7553994e15;
     return (int)floorf(a3c * 153.0 + 0.5f)/*LODWORD(v19)*/ | ((v18 | (a5a << 8)) << 8);
    }
}
// 6BE3C4: using guessed type char bUnderwater;

//----- (0047F44B) --------------------------------------------------------
unsigned int __stdcall WorldPosToGridCellX(signed int sWorldPosX)
{
  return (sWorldPosX / 512) + 64;
}
// 47F44B: using guessed type int __stdcall WorldPosToGridCellX(int);

//----- (0047F458) --------------------------------------------------------
unsigned int __stdcall WorldPosToGridCellZ(signed int sWorldPosZ)
{
  return 64 - (sWorldPosZ / 512);
}

//----- (0047F469) --------------------------------------------------------
int __stdcall GridCellToWorldPosX(int a1)
{
  return (a1 - 64) << 9;
}

//----- (0047F476) --------------------------------------------------------
int __stdcall GridCellToWorldPosZ(int a1)
{
  return (64 - a1) << 9;
}

//----- (0047F4D3) --------------------------------------------------------
void __fastcall sub_47F4D3(int band1, int band2, int band3)
{
  int v3; // edi@1
  //stru220 *v4; // esi@1
  double v5; // ST2C_8@3
  double v6; // st7@3
  //double v7; // [sp+18h] [bp-28h]@3
  //double v8; // [sp+20h] [bp-20h]@2
  int v9; // [sp+34h] [bp-Ch]@1
  int v10; // [sp+38h] [bp-8h]@1
  //signed int band3a; // [sp+48h] [bp+8h]@2

  v9 = band2 * 512;
  pOutdoorCamera->outdoor_grid_band_3 = band3;
  v10 = band1 * 512;
  v3 = band3 * 512;
  pOutdoorCamera->uPickDepth = band3 * 512;
  //v4 = stru_76E5C8;                             // v4:  0 -> 65536
  for (uint i = 0; i < 16384; ++i)
  //do
  {
    auto v4 = stru_76E5C8[i];
    //band3a = 256;
    //v8 = (double)(signed int)((char *)v4 + 256 - (int)stru_76E5C8);
    for (uint j = 0; j < 128; ++j)                  // band3a: 0 -> 128
    {
      v5 = pow(j * 512 + 256, 2.0);
      v6 = pow(i * 4 + 256, 2.0);
      //*((float *)&v5 + 1) = sqrt(v6 + v5);
      int v7 = floorf(sqrtf(v5 + v6) + 0.5f);//*((float *)&v5 + 1) + 6.7553994e15;
      if (v7 >= v10)
      {
        if (v7 >= v9)
          v4.field_0 = ((v7 >= v3) - 1) & 2;
        else
          v4.field_0 = 2;
      }
      else
      {
        v4.field_0 = 1;
      }
      //band3a += 512;
      v4.distance = v7;
      //++v4;
    }
    //while ( band3a < 65792 );
  }
  //while ( (signed int)v4 < (signed int)arary_77E5C8 );
}

//----- (004811A3) --------------------------------------------------------
void stru148::_4811A3()
{
  __debugbreak();

  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 0));
  pRenderer->DrawTerrainPolygon(uNumVertices, this,
    pBitmaps_LOD->pHardwareTextures[pRenderer->pHDWaterBitmapIDs[pRenderer->hd_water_tile_id]],
    0, 0);

  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, 1));
  pRenderer->DrawTerrainPolygon(uNumVertices, this, pBitmaps_LOD->pHardwareTextures[uTileBitmapID], 1, 1);
}

//----- (00481DB2) --------------------------------------------------------
char __fastcall sr_sub_481DB2(RenderVertexSoft *a1, signed int a2, stru148 *a3)
{
  int v3; // eax@2
  int v4; // esi@2
  signed int v5; // esi@2
  char *v6; // edi@3
  double v7; // ST14_8@4
  double v8; // ST0C_8@4
  char result; // al@5

  if ( a2 >= 3 )
  {
    v3 = a3->uTileBitmapID;
    v4 = a3->uTileBitmapID;
    a3->ptr_38 = &stru_8019C8;
    a3->pTexture = (Texture *)(v4 != -1 ? (int)&pBitmaps_LOD->pTextures[v3] : 0);
    v5 = 0;
    if ( (signed int)a3->uNumVertices > 0 )
    {
      v6 = (char *)&array_508690[0].vWorldViewProjY;
      do
      {
        v7 = *((float *)v6 - 1) + 6.7553994e15;
        dword_50B638[v5] = LODWORD(v7);
        v8 = *(float *)v6 + 6.7553994e15;
        v6 += 48;
        dword_50B570[v5++] = LODWORD(v8);
      }
      while ( v5 < (signed int)a3->uNumVertices );
    }
    result = sr_sub_486B4E_push_outdoor_edges(a1, dword_50B638, dword_50B570, a3);
  }
  return result;
}
// 50B570: using guessed type int dword_50B570[];
// 50B638: using guessed type int dword_50B638[];

//----- (00481E55) --------------------------------------------------------
void OutdoorCamera::Project(unsigned int uNumVertices)
{
  double v1; // st7@2
  double v2; // st6@2
  double v3; // st5@2
  int v4; // eax@2
  unsigned int v5; // edx@2
  double v6; // st4@3
  double v7; // st3@3

  if ( (signed int)uNumVertices > 0 )
  {
    v1 = (double)pOutdoorCamera->int_fov_rad;
    v2 = (double)pViewport->uScreenCenterX;
    v3 = (double)pViewport->uScreenCenterY;
    v4 = 0;
    v5 = uNumVertices;
    do
    {
      v6 = v1 * array_507D30[v4]._rhw;
      v7 = v6 * array_507D30[v4].vWorldViewPosition.y;
      memcpy(&array_50AC10[v4], &array_507D30[v4], sizeof(array_50AC10[v4]));
      array_50AC10[v4].vWorldViewProjX = v2 - v7;
      array_50AC10[v4].vWorldViewProjY = v3 - v6 * array_507D30[v4].vWorldViewPosition.z;
      ++v4;
      --v5;
    }
    while ( v5 );
  }
}

//----- (00481EB7) --------------------------------------------------------
void __cdecl ResetStru148s()
{
  int v0; // ecx@1
  char *v1; // eax@2

  v0 = pOutdoorCamera->numStru148s;
  if ( pOutdoorCamera->numStru148s > 0 )
  {
    v1 = (char *)&array_77EC08[0].prolly_tail;
    do
    {
      *((int *)v1 - 1) = 0;
      *(int *)v1 = 0;
      *((int *)v1 - 5) = 0;
      v1 += 268;
      --v0;
    }
    while ( v0 );
  }
}

//----- (00481ED9) --------------------------------------------------------
void __cdecl sub_481ED9_MessWithOutdoorCamera()
{
  stru_8019C8._48616B(65536, 0, 0, 0, 65536, 0);
  pOutdoorCamera->numStru148s = 0;
  pOutdoorCamera->uNumEdges = 0;
  pOutdoorCamera->uNumSpans = 0;
  pOutdoorCamera->uNumSurfs = 0;
  pOutdoorCamera->uNumBillboards = 0;
  pOutdoorCamera->field_44 = 0;
}

//----- (00481EFA) --------------------------------------------------------
bool __fastcall sub_481EFA(RenderVertexSoft *a1, RenderVertexSoft *a2, RenderVertexSoft *a3, RenderVertexSoft *a4, int a5)
{
  RenderVertexSoft *v5; // esi@1
  RenderVertexSoft *v6; // edx@1
  bool v7; // edi@2
  bool v8; // ecx@5
  bool v9; // esi@8
  bool v10; // eax@11
  double v11; // st7@14
  signed int v12; // esi@15
  signed int v13; // edx@18
  signed int v14; // ecx@21
  signed int v15; // eax@24
  RenderVertexSoft *v17; // [sp+Ch] [bp-8h]@1

  v5 = a2;
  v6 = a1;
  v17 = v5;
  v7 = a1->vWorldViewPosition.x < 8.0;
  v8 = v5->vWorldViewPosition.x < 8.0;
  v9 = a3->vWorldViewPosition.x < 8.0;
  v10 = a4->vWorldViewPosition.x < 8.0;
  return !(v8 & v9 & v10 & v7)
      && ((v11 = (double)pOutdoorCamera->shading_dist_mist, v11 > v6->vWorldViewPosition.x) ? (v12 = 0) : (v12 = 1),
          v11 > v17->vWorldViewPosition.x ? (v13 = 0) : (v13 = 1),
          v11 > a3->vWorldViewPosition.x ? (v14 = 0) : (v14 = 1),
          v11 > a4->vWorldViewPosition.x ? (v15 = 0) : (v15 = 1),
          !(v13 & v14 & v15 & v12));
}

//----- (00481FC9) --------------------------------------------------------
int __fastcall sub_481FC9(RenderVertexSoft *a1, RenderVertexSoft *a2, RenderVertexSoft *a3, stru148 *a4)//Rotate camera
{
  float arg_0, arg_4, var_4, var_8, var_c, var_10, var_14;

  if (a1->vWorldPosition.y == a2->vWorldPosition.y && a2->vWorldPosition.y == a3->vWorldPosition.y)
    a4->flags |= 0x10;
  var_c = a1->vWorldViewPosition.x - a2->vWorldViewPosition.x;
  var_14 = a1->vWorldViewPosition.y - a2->vWorldViewPosition.y;
  arg_0 = a1->vWorldViewPosition.z - a2->vWorldViewPosition.z;
  var_10 = a3->vWorldViewPosition.x - a2->vWorldViewPosition.x;
  var_8 = a3->vWorldViewPosition.y - a2->vWorldViewPosition.y;
  var_4 = a3->vWorldViewPosition.z - a2->vWorldViewPosition.z;
  arg_4 = a3->vWorldPosition.y - a2->vWorldPosition.y;
  if (((a3->vWorldPosition.y - a2->vWorldPosition.y) * (a1->vWorldPosition.x - a2->vWorldPosition.x) - (a3->vWorldPosition.x - a2->vWorldPosition.x) * (a1->vWorldPosition.y - a2->vWorldPosition.y)) * (pIndoorCamera->pos.y - a2->vWorldPosition.z) +
      ((a3->vWorldPosition.z - a2->vWorldPosition.z) * (a1->vWorldPosition.y - a2->vWorldPosition.y) - (a3->vWorldPosition.y - a2->vWorldPosition.y) * (a1->vWorldPosition.z - a2->vWorldPosition.z)) * (pIndoorCamera->pos.x - a2->vWorldPosition.x) +
      ((a3->vWorldPosition.x - a2->vWorldPosition.x) * (a1->vWorldPosition.z - a2->vWorldPosition.z) - (a3->vWorldPosition.z - a2->vWorldPosition.z) * (a1->vWorldPosition.x - a2->vWorldPosition.x)) * (pIndoorCamera->pos.z - a2->vWorldPosition.y) < 0)
  {
   arg_4 = var_4 * var_14 - var_8 * arg_0;
   a4->v_18.x = floorf(arg_4 + 0.5f);
   arg_4 = var_10 * arg_0 - var_4 * var_c;
   a4->v_18.y = floorf(arg_4 + 0.5f);
   arg_4 = var_8 * var_c - var_10 * var_14;
   a4->v_18.z = floorf(arg_4 + 0.5f);
   a4->_486089_normalize_v_18();
   arg_4 = -(a4->v_18.x * a2->vWorldViewPosition.x) - a4->v_18.y * a2->vWorldViewPosition.y - a4->v_18.z * a2->vWorldViewPosition.z;
   a4->field_24 = floorf(arg_4 + 0.5f);
   return true;
  }
  else
    return false;
}

//----- (004823F4) --------------------------------------------------------
bool IsTerrainSlopeTooHigh(int pos_x, int pos_z)
{
  //unsigned int v2; // ebx@1
  //unsigned int v3; // edi@1
  //int v4; // eax@1
  //int v6; // esi@5
  //int v7; // ecx@6
  //int v8; // edx@6
  //int v9; // eax@6
  //int v10; // esi@10
  //int v11; // [sp+14h] [bp-8h]@1
  //int v12; // [sp+18h] [bp-4h]@1

  //v12 = a1;
  //v11 = a2;
  auto grid_x = WorldPosToGridCellX(pos_x);
  auto grid_z = WorldPosToGridCellZ(pos_z) - 1;

  auto party_grid_x1 = GridCellToWorldPosX(grid_x);
  //dword_76D56C_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(grid_x + 1);
  //dword_76D570_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(grid_x + 1);
  //dword_76D574_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(grid_x);
  auto party_grid_z1 = GridCellToWorldPosZ(grid_z);
  //dword_76D55C_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(grid_z);
  //dword_76D560_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(grid_z + 1);
  //dword_76D564_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(grid_z + 1);
  auto party_x1z1_y = pOutdoor->DoGetHeightOnTerrain(grid_x, grid_z);
  auto party_x2z1_y = pOutdoor->DoGetHeightOnTerrain(grid_x + 1, grid_z);
  auto party_x2z2_y = pOutdoor->DoGetHeightOnTerrain(grid_x + 1, grid_z + 1);
  auto party_x1z2_y = pOutdoor->DoGetHeightOnTerrain(grid_x, grid_z + 1);
  //dword_76D554_terrain_cell_world_pos_around_party_y = v4;
  if (party_x1z1_y == party_x2z1_y &&
      party_x2z1_y == party_x2z2_y &&
      party_x2z2_y == party_x1z2_y )
    return false;

  auto dx = abs(pos_x - party_grid_x1),
       dz = abs(party_grid_z1 - pos_z);

  int y1, y2, y3;
  if (dz >= dx)
  {
    y1 = party_x1z2_y;  //  lower-left triangle
    y2 = party_x2z2_y;  //  y3 | \ 
    y3 = party_x1z1_y;  //     |   \ 
                        /*     |     \ 
                               |______ \
                            y1           y2   */
  }
  else
  {
    y1 = party_x2z1_y;  // upper-right
    y2 = party_x1z1_y;  //  y2_______ y1
    y3 = party_x2z2_y;  //    \     |
                        /*      \   |
                                  \ |
                                    y3     */
  }

  int y_min = min(y1, min(y2, y3)),
      y_max = max(y1, max(y2, y3));
  return y_max - y_min > 512;

  /*if ( y1 >= y2 )
  {
    y_min = y2;
    if ( y2 < y3 )
      goto LABEL_13;
LABEL_12:
    y_min = y3;
    goto LABEL_13;
  }
  else if ( y1 >= y3 )
    goto LABEL_12;
  else
  y_min = y1;

LABEL_13:
  if ( y1 <= y2 )
  {
    if ( y2 > y3 )
      y3 = y2;
  }
  else
  {
    if ( y1 > y3 )
      y3 = y1;
  }
  return y3 - v10 > 512;*/
}

//----- (0048257A) --------------------------------------------------------
int __fastcall GetTerrainHeightsAroundParty2(int a1, int a2, int *pIsOnWater, int bFloatAboveWater)
{
  //unsigned int v4; // ebx@1
  //unsigned int v5; // edi@1
  int result; // eax@9
  //int v7; // ebx@10
  int v8; // ebx@11
  int v9; // eax@11
  int v10; // ecx@11
  //int v11; // [sp+Ch] [bp-Ch]@1
  //int v12; // [sp+10h] [bp-8h]@1
  int v13; // [sp+10h] [bp-8h]@11
  signed int v14; // [sp+14h] [bp-4h]@3
  int v15; // [sp+24h] [bp+Ch]@11

  //v11 = a1;
  //v12 = a2;
  auto grid_x = WorldPosToGridCellX(a1);
  auto grid_z = WorldPosToGridCellZ(a2) - 1;

  auto grid_x1 = GridCellToWorldPosX(grid_x),
       grid_x2 = GridCellToWorldPosX(grid_x + 1);
  auto grid_z1 = GridCellToWorldPosZ(grid_z),
       grid_z2 = GridCellToWorldPosZ(grid_z + 1);

  auto y_x1z1 = pOutdoor->DoGetHeightOnTerrain(grid_x,     grid_z),
       y_x2z1 = pOutdoor->DoGetHeightOnTerrain(grid_x + 1, grid_z),
       y_x2z2 = pOutdoor->DoGetHeightOnTerrain(grid_x + 1, grid_z + 1),
       y_x1z2 = pOutdoor->DoGetHeightOnTerrain(grid_x,     grid_z + 1);
  //v4 = WorldPosToGridCellX(a1);
  //v5 = WorldPosToGridCellZ(v12) - 1;
  //dword_76D538_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(v4);
  //dword_76D53C_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(v4 + 1);
  //dword_76D540_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(v4 + 1);
  //dword_76D544_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(v4);
  //dword_76D528_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(v5);
  //dword_76D52C_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(v5);
  //dword_76D530_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(v5 + 1);
  //dword_76D534_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(v5 + 1);
  //dword_76D518_terrain_cell_world_pos_around_party_y = pOutdoor->DoGetHeightOnTerrain(v4, v5);
  //dword_76D51C_terrain_cell_world_pos_around_party_y = pOutdoor->DoGetHeightOnTerrain(v4 + 1, v5);
  //dword_76D520_terrain_cell_world_pos_around_party_y = pOutdoor->DoGetHeightOnTerrain(v4 + 1, v5 + 1);
  //dword_76D524_terrain_cell_world_pos_around_party_y = pOutdoor->DoGetHeightOnTerrain(v4, v5 + 1);
  *pIsOnWater = false;
  if ( pOutdoor->ActuallyGetSomeOtherTileInfo(grid_x, grid_z) & 2 )
    *pIsOnWater = true;
  v14 = 0;
  if ( !bFloatAboveWater && *pIsOnWater )
    v14 = -60;
  if ( y_x1z1 != y_x2z1 ||
       y_x2z1 != y_x2z2 ||
       y_x2z2 != y_x1z2 )
  {
    if ( abs(grid_z1 - a2) >= abs(a1 - grid_x1) )
    {
      v8 = y_x1z2;
      v9 = y_x2z2;
      v10 = y_x1z1;
      v15 = a1 - grid_x1;
      v13 = a2 - grid_z2;
    }
    else
    {
      v8 = y_x2z1;
      v9 = y_x1z1;
      v10 = y_x2z2;
      v15 = grid_x2 - a1;
      v13 = grid_z1 - a2;
    }
    return v14 + v8 + fixpoint_sub0(v13, (v10 - v8) * 128) + fixpoint_sub0(v15, (v9 - v8) * 128);
  }
  else
    return y_x1z1;
}

//----- (0048276F) --------------------------------------------------------
void stru148::_48276F_sr()
{
  unsigned int v1; // ebx@1
  float v2; // edx@2
  double v3; // st7@2
  char *v4; // ecx@3
  float v5; // eax@5
  float v6; // eax@7
  float v7; // eax@9
  float v8; // ecx@13
  int i; // eax@16
  int v10; // edx@20
  RenderVertexSoft *v11; // ecx@22
  RenderVertexSoft *v12; // edx@22
  RenderVertexSoft *v13; // esi@22
  int v14; // ebx@26
  RenderVertexSoft *v15; // ebx@27
  double v16; // st6@28
  double v17; // st5@28
  double v18; // st4@28
  int v19; // [sp+4h] [bp-2Ch]@20
  int v20; // [sp+8h] [bp-28h]@22
  int v21; // [sp+Ch] [bp-24h]@22
  stru148 *v22; // [sp+10h] [bp-20h]@1
  float v23; // [sp+14h] [bp-1Ch]@11
  float v24; // [sp+18h] [bp-18h]@7
  float v25; // [sp+1Ch] [bp-14h]@5
  float v26; // [sp+20h] [bp-10h]@2
  float v27; // [sp+24h] [bp-Ch]@2
  float v28; // [sp+28h] [bp-8h]@2
  float v29; // [sp+2Ch] [bp-4h]@9

  v1 = this->uNumVertices;
  v22 = this;
  if ( (signed int)v1 >= 3 )
  {
    LODWORD(v2) = 0;
    v26 = 10000.0;
    v28 = 10000.0;
    v3 = -10000.0;
    v27 = -10000.0;
    if ( (signed int)v1 > 0 )
    {
      v4 = (char *)&array_508690[0].vWorldViewProjY;
      do
      {
        if ( *((float *)v4 - 1) < (double)v26 )
        {
          LODWORD(v5) = *((int *)v4 - 1);
          v25 = v2;
          v26 = v5;
        }
        if ( *((float *)v4 - 1) > (double)v27 )
        {
          LODWORD(v6) = *((int *)v4 - 1);
          v24 = v2;
          v27 = v6;
        }
        if ( *(float *)v4 < (double)v28 )
        {
          LODWORD(v7) = *(int *)v4;
          v29 = v2;
          v28 = v7;
        }
        if ( v3 < *(float *)v4 )
        {
          v3 = *(float *)v4;
          v23 = v2;
        }
        ++LODWORD(v2);
        v4 += 48;
      }
      while ( SLODWORD(v2) < (signed int)v1 );
    }
    v8 = v29;
    if ( LODWORD(v29) == LODWORD(v25) || LODWORD(v29) == LODWORD(v24) )
      v8 = v23;
    v29 = 0.0;
    for ( i = 0; i < (signed int)v1; ++i )
    {
      if ( i == LODWORD(v25) || i == LODWORD(v24) || i == LODWORD(v8) )
      {
        v10 = LODWORD(v29)++;
        *(&v19 + v10) = i;
      }
    }
    v11 = &array_508690[v19];
    v12 = &array_508690[v20];
    v13 = &array_508690[v21];
    if ( LODWORD(v29) != 3 )
    {
      v11 = array_508690;
      v13 = (RenderVertexSoft *)((char *)array_508690 + 16 * (3 * v1 - 3));
      v12 = &array_508690[1];
      v28 = array_508690[1].vWorldPosition.x - array_508690[0].vWorldPosition.x;
      v27 = array_508690[1].vWorldPosition.y - array_508690[0].vWorldPosition.y;
      v29 = array_508690[1].vWorldPosition.z - array_508690[0].vWorldPosition.z;
      v26 = v13->vWorldPosition.x - array_508690[0].vWorldPosition.x;
      v25 = v13->vWorldPosition.y - array_508690[0].vWorldPosition.y;
      v24 = v13->vWorldPosition.z - array_508690[0].vWorldPosition.z;
      if ( v24 * v27 - v25 * v29 == 0.0 )
      {
        if ( v26 * v29 - v24 * v28 == 0.0 )
        {
          if ( v25 * v28 - v26 * v27 == 0.0 )
          {
            v14 = v1 - 2;
            LODWORD(v26) = v14;
            if ( v14 >= 2 )
            {
              v15 = &array_508690[v14];
              do
              {
                v16 = v15->vWorldPosition.x - array_508690[0].vWorldPosition.x;
                v17 = v15->vWorldPosition.y - array_508690[0].vWorldPosition.y;
                v18 = v15->vWorldPosition.z - array_508690[0].vWorldPosition.z;
                v13 = v15;
                if ( v27 * v18 - v17 * v29 != 0.0 )
                  break;
                if ( v16 * v29 - v18 * v28 != 0.0 )
                  break;
                if ( v28 * v17 - v16 * v27 != 0.0 )
                  break;
                --LODWORD(v26);
                --v15;
              }
              while ( SLODWORD(v26) >= 2 );
            }
          }
        }
      }
    }
    sr_sub_4829B9(v11, v12, v13, v22, 1);
  }
}

//----- (004829B9) --------------------------------------------------------
stru148 *__fastcall sr_sub_4829B9(RenderVertexSoft *a1, RenderVertexSoft *a2, RenderVertexSoft *a3, stru148 *a4, int a5)
{
  double v5; // st7@1
  RenderVertexSoft *v6; // esi@1
  double v7; // st6@1
  stru148 *result; // eax@3
  double v9; // st6@3
  double v10; // st5@3
  float v11; // ST0C_4@3
  float v12; // ST04_4@3
  double v13; // st4@3
  float v14; // [sp+8h] [bp-Ch]@1
  float v15; // [sp+10h] [bp-4h]@1
  float v16; // [sp+1Ch] [bp+8h]@1
  float v17; // [sp+1Ch] [bp+8h]@3

  v5 = a2->vWorldViewProjX - a1->vWorldViewProjX;
  v6 = a3;
  v16 = a3->vWorldViewProjY - a1->vWorldViewProjY;
  v15 = a2->vWorldViewProjY - a1->vWorldViewProjY;
  v14 = v6->vWorldViewProjX - a1->vWorldViewProjX;
  v7 = v16 * v5 - v14 * v15;
  if ( v7 == 0.0 )
    v7 = 0.0000001;
  result = a4;
  v9 = 1.0 / v7;
  v10 = 1.0 / a1->vWorldViewPosition.x;
  v11 = 1.0 / a2->vWorldViewPosition.x - v10;
  v12 = 1.0 / v6->vWorldViewPosition.x - v10;
  v13 = (v11 * v16 - v12 * v15) * v9;
  v17 = (v11 * v14 - v12 * v5) * -v9;
  a4->field_C = a1->vWorldViewProjX;
  a4->field_10 = a1->vWorldViewProjY;
  a4->field_0 = v10;
  a4->field_8 = v17;
  a4->field_4 = v13;
  return result;
}

//----- (00482A90) --------------------------------------------------------
signed int __cdecl const_1_0()
{
  return 1;
}

//----- (00482A94) --------------------------------------------------------
int sr_sub_482A94(Span *_this)
{
  stru315 *v1; // ebp@0
  Span *v2; // edi@1
  stru148 *v3; // esi@1
  int v4; // ecx@1
  stru149 *v5; // eax@1
  stru149 *v6; // eax@1
  int v7; // edx@1
  int v8; // eax@1
  int v9; // ecx@1
  int v10; // edx@1
  int v11; // ebx@1
  int v12; // eax@1
  signed int v13; // ebx@1
  int v14; // ebx@2
  signed __int64 v15; // qtt@3
  stru149 *v16; // eax@3
  signed int v17; // ebx@3
  Texture *v18; // eax@14
  unsigned __int16 *v19; // eax@15
  stru149 *v20; // eax@21
  signed int v21; // eax@21
  int v22; // eax@21
  int v23; // ecx@21
  Texture *v24; // edx@21
  signed int v25; // eax@21
  signed int v27; // [sp-4h] [bp-A4h]@8
  int v28; // [sp+Ch] [bp-94h]@1
  int v29; // [sp+10h] [bp-90h]@1
  stru316 a2; // [sp+14h] [bp-8Ch]@21
  stru315 a1; // [sp+3Ch] [bp-64h]@1
  int v32; // [sp+80h] [bp-20h]@1
  int v33; // [sp+84h] [bp-1Ch]@1
  int v34; // [sp+88h] [bp-18h]@1
  int v35; // [sp+8Ch] [bp-14h]@1
  int v36; // [sp+90h] [bp-10h]@1
  int v37; // [sp+94h] [bp-Ch]@1
  int v38; // [sp+98h] [bp-8h]@1
  int X; // [sp+9Ch] [bp-4h]@1

  v2 = _this;
  v3 = _this->pParent;
  v4 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - _this->field_A);
  v5 = v3->ptr_38;
  v38 = v4;
  v37 = v5->field_14;
  v38 = (unsigned __int64)(v37 * (signed __int64)v4) >> 16;
  v6 = v3->ptr_38;
  v7 = v38 + v6->field_C;
  v37 = v6->field_20;
  v33 = v7;
  v8 = ((unsigned __int64)(v37 * (signed __int64)v4) >> 16) + v3->ptr_38->field_18;
  v38 = v4;
  v34 = v8;
  v37 = v3->v_18.z;
  v38 = (unsigned __int64)(v37 * (signed __int64)v4) >> 16;
  v9 = v3->v_18.x;
  v28 = v3->sTextureDeltaU << 16;
  v35 = v3->sTextureDeltaV << 16;
  v10 = v2->field_8;
  v29 = pOutdoorCamera->camera_rotation_y_int_sine;
  v32 = pOutdoorCamera->camera_rotation_y_int_cosine;
  a1.field_28 = v2->field_C;
  v11 = v3->field_24;
  v37 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterX - v10);
  v12 = v3->v_18.y;
  v13 = -v11;
  v36 = v13;
  X = ((unsigned __int64)(v37 * (signed __int64)v12) >> 16) + v38 + v9;
  if ( !X || (v14 = abs(v13 >> 14), v14 > abs(X)) )
    return 0;
  LODWORD(v15) = v36 << 16;
  HIDWORD(v15) = v36 >> 16;
  v38 = v15 / X;
  v16 = v3->ptr_38;
  X = v37;
  v36 = v16->field_10;
  X = v37;
  v36 = v33 + ((unsigned __int64)(v36 * (signed __int64)v37) >> 16);
  v33 = v3->ptr_38->field_1C;
  X = (unsigned __int64)(v33 * (signed __int64)v37) >> 16;
  v34 += (unsigned __int64)(v33 * (signed __int64)v37) >> 16;
  v17 = 2;
  a1.pTextureLOD = (unsigned __int16 *)v3->pTexture->pLevelOfDetail2;
  if ( v38 >= mipmapping_building_mm1 << 16 )
  {
    if ( v38 >= mipmapping_building_mm2 << 16 )
    {
      if ( v38 >= mipmapping_building_mm3 << 16 )
      {
        if ( bUseLoResSprites )
          goto LABEL_12;
        v27 = 3;
      }
      else
      {
        v27 = 2;
      }
      v17 = v27;
      goto LABEL_12;
    }
    v17 = 1;
  }
  else
  {
    v17 = 0;
  }
LABEL_12:
  if ( v17 < (signed int)v3->ptr_48 )
    v17 = (signed int)v3->ptr_48;
  v18 = v3->pTexture;
  if ( v17 )
  {
    if ( v17 == 1 )
    {
      v19 = (unsigned __int16 *)v18->pLevelOfDetail1;
    }
    else
    {
      if ( v17 == 2 )
        v19 = (unsigned __int16 *)v18->pLevelOfDetail2;
      else
        v19 = (unsigned __int16 *)v18->pLevelOfDetail3;
    }
  }
  else
  {
    v19 = (unsigned __int16 *)v18->pLevelOfDetail0_prolly_alpha_mask;
  }
  a1.pTextureLOD = v19;
  X = (unsigned __int64)(v36 * (signed __int64)v38) >> 16;
  v20 = v3->ptr_38;
  X = v38;
  a1.field_30 = v28 + ((unsigned __int64)(v36 * (signed __int64)v38) >> 16) - v20->field_24;
  X = (unsigned __int64)(v34 * (signed __int64)v38) >> 16;
  v21 = X - v3->ptr_38->field_28 - v35;
  a1.field_30 >>= v17 + bUseLoResSprites;
  a1.field_2C = v21 >> (v17 + bUseLoResSprites);
  v35 = pOutdoorCamera->int_fov_rad_inv;
  v37 = (signed int)((unsigned __int64)(pOutdoorCamera->int_fov_rad_inv * (signed __int64)v38) >> 16) >> (v17 + bUseLoResSprites);
  a1.field_4 = (unsigned __int64)(v37 * (signed __int64)v29) >> 16;
  X = (unsigned __int64)(v37 * (signed __int64)v32) >> 16;
  a1.field_0 = -(signed int)((unsigned __int64)(v37 * (signed __int64)v32) >> 16);
  v22 = v2->field_A;
  a1.pColorBuffer = &pRenderer->pTargetSurface[v2->field_8 + pRenderer->uTargetSurfacePitch * v2->field_A];
  HIWORD(v23) = HIWORD(v38);
  a1.pDepthBuffer = (unsigned int *)&pRenderer->pActiveZBuffer[v2->field_8 + 640 * v22];
  LOWORD(v23) = 0;
  a1.field_24 = v23 | v3->field_50;
  v24 = v3->pTexture;
  v32 = (signed int)v24->uTextureWidth >> v17;
  v25 = (signed int)v24->uTextureHeight >> v17;
  a1.field_10 = v17 - v24->uWidthLn2 + 16;
  a1.field_C = v32 - 1;
  a1.field_8 = (v25 << 16) - 65536;
  a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v2, v38, v3, pOutdoorCamera->building_gamme, 1u, 1);
  if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
    sr_sub_485975(&a1, (stru315 *)&a2);
  else
    sr_sub_4D6FB0(v1);
  return 1;
}

//----- (00482E07) --------------------------------------------------------
signed int __fastcall sr_sub_482E07(Span *ecx0, unsigned __int16 *pRenderTarget)
{
  stru315 *v2; // ebp@0
  stru148 *v3; // esi@1
  int v4; // edi@1
  int v5; // edi@1
  stru149 *v6; // eax@1
  stru149 *v7; // eax@1
  int v8; // edx@1
  int v9; // eax@1
  int v10; // edi@1
  int v11; // eax@1
  unsigned __int64 v12; // qax@1
  int v13; // eax@1
  signed __int64 v14; // qtt@3
  int v15; // ebx@4
  signed __int64 v16; // qtt@5
  int v17; // eax@5
  unsigned __int16 *v18; // eax@7
  Texture *v19; // eax@8
  Texture *v20; // eax@10
  Texture *v21; // eax@12
  Texture *v22; // eax@14
  int v23; // ecx@17
  Texture *v24; // ebx@17
  signed int v25; // edx@17
  signed int v26; // eax@17
  char v27; // bl@17
  stru149 *v28; // eax@18
  stru149 *v29; // eax@18
  int v30; // eax@18
  int v31; // eax@18
  unsigned int v32; // edx@18
  int v33; // edi@21
  signed __int64 v34; // qtt@22
  signed int v35; // ecx@22
  int v36; // eax@24
  stru149 *v37; // eax@24
  int v38; // edi@24
  int v39; // eax@24
  int v40; // edi@35
  signed __int64 v41; // qtt@36
  int v42; // edx@36
  stru149 *v43; // eax@36
  int v44; // edi@36
  int v45; // eax@36
  Span *v46; // edi@44
  stru149 *v47; // eax@44
  stru149 *v48; // eax@44
  int v49; // eax@44
  int v50; // ecx@44
  unsigned int v51; // edx@44
  int v52; // edi@46
  signed __int64 v53; // qtt@47
  unsigned int v54; // ecx@47
  int v55; // eax@49
  stru149 *v56; // eax@49
  int v57; // edi@49
  int v58; // eax@49
  int v59; // edi@60
  signed __int64 v60; // qtt@61
  int v61; // edx@61
  stru149 *v62; // eax@61
  int v63; // edi@61
  int v64; // eax@61
  int v66; // [sp+Ch] [bp-B8h]@1
  int v67; // [sp+10h] [bp-B4h]@1
  int v68; // [sp+14h] [bp-B0h]@1
  int v69; // [sp+18h] [bp-ACh]@1
  int v70; // [sp+1Ch] [bp-A8h]@5
  int v71; // [sp+20h] [bp-A4h]@1
  signed int v72; // [sp+24h] [bp-A0h]@1
  stru316 a2; // [sp+28h] [bp-9Ch]@18
  int v74; // [sp+50h] [bp-74h]@17
  stru315 a1; // [sp+54h] [bp-70h]@5
  Span *v76; // [sp+98h] [bp-2Ch]@1
  unsigned __int16 *v77; // [sp+9Ch] [bp-28h]@1
  int v78; // [sp+A0h] [bp-24h]@17
  int v79; // [sp+A4h] [bp-20h]@3
  int v80; // [sp+A8h] [bp-1Ch]@3
  int v81; // [sp+ACh] [bp-18h]@1
  int X; // [sp+B0h] [bp-14h]@2
  int v83; // [sp+B4h] [bp-10h]@1
  int v84; // [sp+B8h] [bp-Ch]@1
  int v85; // [sp+BCh] [bp-8h]@1
  int v86; // [sp+C0h] [bp-4h]@18

  v85 = ecx0->field_C;
  v3 = ecx0->pParent;
  v4 = pViewport->uScreenCenterY - ecx0->field_A;
  v77 = pRenderTarget;
  v5 = pOutdoorCamera->int_fov_rad_inv * v4;
  v6 = v3->ptr_38;
  v76 = ecx0;
  v81 = v5;
  v83 = v6->field_14;
  v81 = (unsigned __int64)(v83 * (signed __int64)v5) >> 16;
  v7 = v3->ptr_38;
  v8 = v81 + v7->field_C;
  v83 = v7->field_20;
  v67 = v8;
  v9 = ((unsigned __int64)(v83 * (signed __int64)v5) >> 16) + v3->ptr_38->field_18;
  v81 = v5;
  v71 = v9;
  v83 = v3->v_18.z;
  v81 = (unsigned __int64)(v83 * (signed __int64)v5) >> 16;
  v68 = v3->sTextureDeltaU << 16;
  v69 = v3->sTextureDeltaV << 16;
  v72 = -v3->field_24;
  v10 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterX - ecx0->field_8);
  v11 = v3->v_18.y;
  v66 = v81 + v3->v_18.x;
  v83 = v10;
  v12 = v10 * (signed __int64)v11;
  v81 = v12 >> 16;
  v13 = v66 + (v12 >> 16);
  v84 = v13;
  if ( !v13
    || (X = v72 >> 15, v83 = abs(v13), abs(v72 >> 15) >= v83)
    || (LODWORD(v14) = v72 << 16,
        HIDWORD(v14) = v72 >> 16,
        v79 = v14 / v84,
        v80 = v10 - v85 * pOutdoorCamera->int_fov_rad_inv,
        v81 = (unsigned __int64)(v80 * (signed __int64)v3->v_18.y) >> 16,
        (v84 = v66 + v81) == 0)
    || (v15 = abs(v66 + v81), abs(X) >= v15) )
    return 0;
  LODWORD(v16) = v72 << 16;
  HIDWORD(v16) = v72 >> 16;
  v70 = v16 / v84;
  v17 = v16 / v84;
  a1.field_24 = v79;
  if ( v79 >= v17 )
    a1.field_24 = v17;
  v18 = (unsigned __int16 *)v3->pTexture->pLevelOfDetail2;
  a1.pTextureLOD = (unsigned __int16 *)v3->pTexture->pLevelOfDetail2;
  v84 = 2;
  if ( a1.field_24 >= mipmapping_building_mm1 << 16 )
  {
    if ( a1.field_24 >= mipmapping_building_mm2 << 16 )
    {
      if ( a1.field_24 >= mipmapping_building_mm3 << 16 )
      {
        if ( bUseLoResSprites )
          goto LABEL_16;
        v22 = v3->pTexture;
        v84 = 3;
        v18 = (unsigned __int16 *)v22->pLevelOfDetail3;
      }
      else
      {
        v21 = v3->pTexture;
        v84 = 2;
        v18 = (unsigned __int16 *)v21->pLevelOfDetail2;
      }
    }
    else
    {
      v20 = v3->pTexture;
      v84 = 1;
      v18 = (unsigned __int16 *)v20->pLevelOfDetail1;
    }
  }
  else
  {
    v19 = v3->pTexture;
    v84 = 0;
    v18 = (unsigned __int16 *)v19->pLevelOfDetail0_prolly_alpha_mask;
  }
  a1.pTextureLOD = v18;
LABEL_16:
  if ( v18 )
  {
    v23 = v3->field_5A;
    v83 = v3->field_52;
    v24 = v3->pTexture;
    v74 = v23;
    v78 = v85 >> v23;
    v25 = v24->uTextureWidth;
    v81 = v85 - (v85 >> v23 << v23);
    v26 = (signed int)v24->uTextureHeight >> v84;
    a1.field_10 = v84 - v24->uWidthLn2 + 16;
    v27 = v84 + bUseLoResSprites;
    a1.field_8 = (v26 << 16) - 65536;
    a1.field_C = (v25 >> v84) - 1;
    if ( v79 >= v70 )
    {
      v46 = v76;
      a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v76, v70, v3, pOutdoorCamera->building_gamme, 0, 1);
      v47 = v3->ptr_38;
      v79 = v80;
      v86 = v47->field_10;
      v79 = v80;
      v84 = v67 + ((unsigned __int64)(v86 * (signed __int64)v80) >> 16);
      v86 = v3->ptr_38->field_1C;
      v86 = v71 + ((unsigned __int64)(v86 * (signed __int64)v80) >> 16);
      v79 = (unsigned __int64)(v84 * (signed __int64)v70) >> 16;
      v48 = v3->ptr_38;
      v79 = v70;
      a1.field_30 = v68 + ((unsigned __int64)(v84 * (signed __int64)v70) >> 16) - v48->field_24;
      v79 = (unsigned __int64)(v86 * (signed __int64)v70) >> 16;
      v49 = ((unsigned __int64)(v86 * (signed __int64)v70) >> 16) - v3->ptr_38->field_28;
      a1.field_30 >>= v27;
      a1.field_2C = (v69 + v49) >> v27;
      a1.field_14 = dword_80AA20 >> v27;
      a1.field_18 = dword_80AA1C >> v27;
      a1.field_1C = dword_80AA18 >> v27;
      v50 = v46->field_8;
      a1.field_20 = dword_80AA14 >> v27;
      v51 = v50 + pRenderer->uTargetSurfacePitch * v46->field_A;
      a1.pDepthBuffer = (unsigned int *)(&pRenderer->pActiveZBuffer[640 * v46->field_A - 1] + v85 + v50);
      a1.pColorBuffer = &v77[v85 - 1] + v51;
      v80 += pOutdoorCamera->int_fov_rad_inv << v74;
      if ( v78 > 0 )
      {
        do
        {
          v77 = (unsigned __int16 *)v3->v_18.y;
          v86 = (unsigned __int64)((signed int)v77 * (signed __int64)v80) >> 16;
          v84 = v66 + ((unsigned __int64)((signed int)v77 * (signed __int64)v80) >> 16);
          if ( v66 + (unsigned int)((unsigned __int64)((signed int)v77 * (signed __int64)v80) >> 16)
            && (v52 = abs((signed __int64)v66 + ((__int64)((signed int)v77 * (signed __int64)v80) >> 16)), abs((signed __int64)X) < v52) )
          {
            LODWORD(v53) = v72 << 16;
            HIDWORD(v53) = v72 >> 16;
            v86 = v53 / v84;
            v54 = v53 / v84;
            v84 = v53 / v84;
          }
          else
          {
            v84 = 0x40000000u;
            v54 = 0x40000000u;
          }
          HIWORD(v55) = HIWORD(v54);
          LOWORD(v55) = 0;
          a1.field_24 = v3->field_50 | v55;
          v77 = (unsigned __int16 *)v3->ptr_38->field_10;
          v77 = (unsigned __int16 *)(v67 + ((unsigned __int64)((signed int)v77 * (signed __int64)v80) >> 16));
          v86 = (unsigned __int64)((signed int)v77 * (signed __int64)(signed int)v54) >> 16;
          v56 = v3->ptr_38;
          v57 = ((unsigned __int64)((signed int)v77 * (signed __int64)(signed int)v54) >> 16) - v56->field_24;
          v77 = (unsigned __int16 *)v56->field_1C;
          v77 = (unsigned __int16 *)(v71 + ((unsigned __int64)((signed int)v77 * (signed __int64)v80) >> 16));
          v86 = (unsigned __int64)((signed int)v77 * (signed __int64)(signed int)v54) >> 16;
          v58 = (((v69 + v86 - v3->ptr_38->field_28) >> v27) - a1.field_2C) >> v74;
          a1.field_4 = (((v68 + v57) >> v27) - a1.field_30) >> v74;
          a1.field_0 = v58;
          a1.field_28 = v83;
          if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
          {
            if ( v3->pODMFace->uPolygonType == 1 )
              sr_sub_485BAE(&a1, &a2);
            else
              sr_sub_485AFF(&a1, &a2);
          }
          else
          {
            if ( v3->pODMFace->uPolygonType == 1 )
              sr_sub_4D71F8(&a1);
            else
              sr_sub_4D714C(&a1);
          }
          a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(
                                                      &a2,
                                                      v76,
                                                      v84,
                                                      v3,
                                                      pOutdoorCamera->building_gamme,
                                                      0,
                                                      0);
          v80 += pOutdoorCamera->int_fov_rad_inv << v74;
          --v78;
        }
        while ( v78 );
      }
      if ( !v81 )
        return 1;
      v83 = v3->v_18.y;
      v86 = (unsigned __int64)(v83 * (signed __int64)v80) >> 16;
      v84 = v66 + ((unsigned __int64)(v83 * (signed __int64)v80) >> 16);
      if ( v66 + (unsigned int)((unsigned __int64)(v83 * (signed __int64)v80) >> 16) )
      {
        v59 = abs((signed __int64)v66 + ((__int64)(v83 * (signed __int64)v80) >> 16));
        if ( abs(X) < v59 )
        {
          LODWORD(v60) = v72 << 16;
          HIDWORD(v60) = v72 >> 16;
          v86 = v60 / v84;
          HIWORD(v61) = (unsigned int)(v60 / v84) >> 16;
          LOWORD(v61) = 0;
          a1.field_24 = v61 | v3->field_50;
          v83 = v3->ptr_38->field_10;
          v83 = v67 + ((unsigned __int64)(v83 * (signed __int64)v80) >> 16);
          v86 = (unsigned __int64)(v83 * v60 / v84) >> 16;
          v62 = v3->ptr_38;
          v63 = ((unsigned __int64)(v83 * v60 / v84) >> 16) - v62->field_24;
          v83 = v62->field_1C;
          v83 = v71 + ((unsigned __int64)(v83 * (signed __int64)v80) >> 16);
          v86 = (unsigned __int64)(v83 * v60 / v84) >> 16;
          v64 = (((signed int)(v69 + ((unsigned __int64)(v83 * v60 / v84) >> 16) - v3->ptr_38->field_28) >> v27)
               - a1.field_2C) >> v74;
          a1.field_4 = (((v68 + v63) >> v27) - a1.field_30) >> v74;
          a1.field_0 = v64;
          a1.field_28 = v81;
          if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
          {
            if ( v3->pODMFace->uPolygonType == 1 )
              sr_sub_485BAE(&a1, &a2);
            else
              sr_sub_485AFF(&a1, &a2);
          }
          else
          {
            if ( v3->pODMFace->uPolygonType == 1 )
              sr_sub_4D71F8(&a1);
            else
              sr_sub_4D714C(&a1);
          }
          return 1;
        }
      }
    }
    else
    {
      a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v76, v79, v3, pOutdoorCamera->building_gamme, 1u, 1);
      v28 = v3->ptr_38;
      v85 = v10;
      v86 = v28->field_10;
      v85 = v10;
      v84 = v67 + ((unsigned __int64)(v86 * (signed __int64)v10) >> 16);
      v86 = v3->ptr_38->field_1C;
      v86 = v71 + ((unsigned __int64)(v86 * (signed __int64)v10) >> 16);
      v85 = (unsigned __int64)(v84 * (signed __int64)v79) >> 16;
      v29 = v3->ptr_38;
      v85 = v79;
      a1.field_30 = v68 + ((unsigned __int64)(v84 * (signed __int64)v79) >> 16) - v29->field_24;
      v85 = (unsigned __int64)(v86 * (signed __int64)v79) >> 16;
      v30 = ((unsigned __int64)(v86 * (signed __int64)v79) >> 16) - v3->ptr_38->field_28;
      a1.field_30 >>= v27;
      a1.field_2C = (v69 + v30) >> v27;
      a1.field_14 = dword_80AA20 >> v27;
      a1.field_18 = dword_80AA1C >> v27;
      a1.field_1C = dword_80AA18 >> v27;
      a1.field_20 = dword_80AA14 >> v27;
      v31 = v76->field_A;
      v32 = pRenderer->uTargetSurfacePitch * v76->field_A;
      v86 = v76->field_8;
      a1.pColorBuffer = &v77[v86 + v32];
      a1.pDepthBuffer = (unsigned int *)&pRenderer->pActiveZBuffer[v86 + 640 * v31];
      v80 = v10 - (pOutdoorCamera->int_fov_rad_inv << v74);
      if ( v78 > 0 )
      {
        v86 = v78;
        do
        {
          v78 = v3->v_18.y;
          v85 = (unsigned __int64)(v78 * (signed __int64)v80) >> 16;
          v84 = v66 + ((unsigned __int64)(v78 * (signed __int64)v80) >> 16);
          if ( v66 + (unsigned int)((unsigned __int64)(v78 * (signed __int64)v80) >> 16)
            && (v33 = abs((signed __int64)v66 + ((__int64)(v78 * (signed __int64)v80) >> 16)), abs((signed __int64)X) < v33) )
          {
            LODWORD(v34) = v72 << 16;
            HIDWORD(v34) = v72 >> 16;
            v85 = v34 / v84;
            v35 = v34 / v84;
            v84 = v34 / v84;
          }
          else
          {
            v84 = 1073741824;
            v35 = 1073741824;
          }
          HIWORD(v36) = HIWORD(v35);
          LOWORD(v36) = 0;
          a1.field_24 = v3->field_50 | v36;
          v78 = v3->ptr_38->field_10;
          v78 = v67 + ((unsigned __int64)(v78 * (signed __int64)v80) >> 16);
          v85 = (unsigned __int64)(v78 * (signed __int64)v35) >> 16;
          v37 = v3->ptr_38;
          v38 = ((unsigned __int64)(v78 * (signed __int64)v35) >> 16) - v37->field_24;
          v78 = v37->field_1C;
          v78 = v71 + ((unsigned __int64)(v78 * (signed __int64)v80) >> 16);
          v85 = (unsigned __int64)(v78 * (signed __int64)v35) >> 16;
          v39 = (((v69 + v85 - v3->ptr_38->field_28) >> v27) - a1.field_2C) >> v74;
          a1.field_4 = (((v68 + v38) >> v27) - a1.field_30) >> v74;
          a1.field_0 = v39;
          a1.field_28 = v83;
          if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
          {
            if ( v3->pODMFace->uPolygonType == 1 )
              sr_sub_485A24(&a1, (stru315 *)&a2);
            else
              sr_sub_485975(&a1, (stru315 *)&a2);
          }
          else
          {
            if ( v3->pODMFace->uPolygonType == 1 )
              sr_sub_4D705A(v2);
            else
              sr_sub_4D6FB0(v2);
          }
          a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(
                                                      &a2,
                                                      v76,
                                                      v84,
                                                      v3,
                                                      pOutdoorCamera->building_gamme,
                                                      1u,
                                                      0);
          v80 -= pOutdoorCamera->int_fov_rad_inv << v74;
          --v86;
        }
        while ( v86 );
      }
      if ( !v81 )
        return 1;
      v83 = v3->v_18.y;
      v76 = (Span *)((unsigned __int64)(v83 * (signed __int64)v80) >> 16);
      v84 = v66 + ((unsigned __int64)(v83 * (signed __int64)v80) >> 16);
      if ( v66 + (unsigned int)((unsigned __int64)(v83 * (signed __int64)v80) >> 16) )
      {
        v40 = abs((signed __int64)v66 + ((__int64)(v83 * (signed __int64)v80) >> 16));
        if ( abs(X) < v40 )
        {
          LODWORD(v41) = v72 << 16;
          HIDWORD(v41) = v72 >> 16;
          X = v41 / v84;
          HIWORD(v42) = (unsigned int)(v41 / v84) >> 16;
          LOWORD(v42) = 0;
          a1.field_24 = v42 | v3->field_50;
          v83 = v3->ptr_38->field_10;
          v83 = v67 + ((unsigned __int64)(v83 * (signed __int64)v80) >> 16);
          X = (unsigned __int64)(v83 * v41 / v84) >> 16;
          v43 = v3->ptr_38;
          v44 = ((unsigned __int64)(v83 * v41 / v84) >> 16) - v43->field_24;
          v83 = v43->field_1C;
          v83 = v71 + ((unsigned __int64)(v83 * (signed __int64)v80) >> 16);
          X = (unsigned __int64)(v83 * v41 / v84) >> 16;
          v45 = (((signed int)(v69 + ((unsigned __int64)(v83 * v41 / v84) >> 16) - v3->ptr_38->field_28) >> v27)
               - a1.field_2C) >> v74;
          a1.field_4 = (((v68 + v44) >> v27) - a1.field_30) >> v74;
          a1.field_0 = v45;
          a1.field_28 = v81;
          if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
          {
            if ( v3->pODMFace->uPolygonType == 1 )
              sr_sub_485A24(&a1, (stru315 *)&a2);
            else
              sr_sub_485975(&a1, (stru315 *)&a2);
          }
          else
          {
            if ( v3->pODMFace->uPolygonType == 1 )
              sr_sub_4D705A(v2);
            else
              sr_sub_4D6FB0(v2);
          }
          return 1;
        }
      }
    }
  }
  return 0;
}

//----- (004839BD) --------------------------------------------------------
signed int __fastcall sr_sub_4839BD(Span *ecx0, unsigned __int16 *pTargetSurface)
{
  stru315 *v2; // ebp@0
  int v3; // eax@1
  int v4; // edi@1
  stru148 *v5; // esi@1
  unsigned int v6; // ebx@1
  int v7; // ecx@1
  int v8; // ebx@1
  int v9; // ecx@1
  int v10; // eax@1
  stru149 *v11; // eax@1
  int v12; // edx@1
  int v13; // eax@1
  int v14; // edi@1
  int v15; // ecx@1
  int v16; // eax@1
  signed int v17; // edi@1
  int v18; // edi@2
  signed __int64 v19; // qtt@3
  int v20; // edi@3
  unsigned __int16 *v21; // eax@3
  Texture *v22; // eax@4
  Texture *v23; // eax@6
  Texture *v24; // eax@8
  Texture *v25; // eax@10
  stru149 *v26; // eax@13
  int v27; // edi@13
  signed int v28; // edx@13
  Texture *v29; // ebx@13
  int v30; // edi@13
  signed int v31; // edx@13
  signed int v32; // eax@13
  signed int v33; // eax@13
  int v34; // ebx@13
  int v35; // eax@15
  int v36; // ebx@15
  int v37; // eax@16
  signed __int64 v38; // qtt@17
  int v39; // ecx@17
  int v40; // eax@19
  stru149 *v41; // eax@21
  int v42; // ebx@21
  int v43; // ebx@21
  int v44; // eax@21
  char v45; // zf@25
  int v46; // eax@28
  int v47; // eax@28
  int v48; // ebx@28
  int v49; // eax@29
  signed __int64 v50; // qtt@30
  int v51; // ecx@30
  int v52; // eax@30
  int v53; // edx@31
  stru149 *v54; // eax@33
  int v55; // ebx@33
  signed int v56; // ebx@33
  int v57; // eax@33
  unsigned __int64 v58; // qax@33
  int v60; // [sp+Ch] [bp-BCh]@1
  Span *v61; // [sp+10h] [bp-B8h]@1
  int v62; // [sp+14h] [bp-B4h]@2
  int v63; // [sp+18h] [bp-B0h]@1
  stru315 a1; // [sp+1Ch] [bp-ACh]@1
  stru316 a2; // [sp+60h] [bp-68h]@13
  int v66; // [sp+88h] [bp-40h]@13
  int v67; // [sp+8Ch] [bp-3Ch]@1
  int v68; // [sp+90h] [bp-38h]@13
  int v69; // [sp+94h] [bp-34h]@3
  int v70; // [sp+98h] [bp-30h]@1
  int v71; // [sp+9Ch] [bp-2Ch]@1
  int v72; // [sp+A0h] [bp-28h]@1
  int v73; // [sp+A4h] [bp-24h]@13
  int v74; // [sp+A8h] [bp-20h]@1
  int v75; // [sp+ACh] [bp-1Ch]@3
  int v76; // [sp+B0h] [bp-18h]@1
  int v77; // [sp+B4h] [bp-14h]@1
  int X; // [sp+B8h] [bp-10h]@1
  int v79; // [sp+BCh] [bp-Ch]@21
  int v80; // [sp+C0h] [bp-8h]@13
  unsigned int v81; // [sp+C4h] [bp-4h]@1

  v3 = ecx0->field_A;
  v4 = ecx0->field_8;
  v5 = ecx0->pParent;
  v6 = v4 + pRenderer->uTargetSurfacePitch * ecx0->field_A;
  v61 = ecx0;
  v7 = ecx0->field_C;
  a1.pColorBuffer = &pTargetSurface[v6];
  v74 = v7;
  a1.pDepthBuffer = (unsigned int *)&pRenderer->pActiveZBuffer[v4 + 640 * v3];
  v8 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterX - v4);
  v9 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - v3);
  v10 = v5->ptr_38->field_14;
  v76 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterX - v4);
  v72 = v10;
  v81 = (unsigned __int64)(v10 * (signed __int64)v9) >> 16;
  v11 = v5->ptr_38;
  v12 = v81 + v11->field_C;
  v72 = v11->field_20;
  v67 = v12;
  v13 = ((unsigned __int64)(v72 * (signed __int64)v9) >> 16) + v5->ptr_38->field_18;
  v81 = v9;
  v70 = v13;
  v72 = v5->v_18.z;
  v81 = (unsigned __int64)(v72 * (signed __int64)v9) >> 16;
  v14 = v5->field_24;
  v15 = v81 + v5->v_18.x;
  v71 = v5->sTextureDeltaU << 16;
  v63 = v5->sTextureDeltaV << 16;
  v16 = v5->v_18.y;
  v17 = -v14;
  v60 = v15;
  v77 = v17;
  v81 = (unsigned __int64)(v76 * (signed __int64)v16) >> 16;
  X = v81 + v15;
  if ( !(v81 + v15) || (v62 = v17 >> 14, v18 = abs(v17 >> 14), v18 > abs(X)) )
    return 0;
  LODWORD(v19) = v77 << 16;
  HIDWORD(v19) = v77 >> 16;
  v69 = v19 / X;
  v20 = v19 / X;
  v21 = (unsigned __int16 *)v5->pTexture->pLevelOfDetail2;
  a1.pTextureLOD = (unsigned __int16 *)v5->pTexture->pLevelOfDetail2;
  v75 = 2;
  if ( v20 >= mipmapping_building_mm1 << 16 )
  {
    if ( v20 >= mipmapping_building_mm2 << 16 )
    {
      if ( v20 >= mipmapping_building_mm3 << 16 )
      {
        if ( bUseLoResSprites )
          goto LABEL_12;
        v25 = v5->pTexture;
        v75 = 3;
        v21 = (unsigned __int16 *)v25->pLevelOfDetail3;
      }
      else
      {
        v24 = v5->pTexture;
        v75 = 2;
        v21 = (unsigned __int16 *)v24->pLevelOfDetail2;
      }
    }
    else
    {
      v23 = v5->pTexture;
      v75 = 1;
      v21 = (unsigned __int16 *)v23->pLevelOfDetail1;
    }
  }
  else
  {
    v22 = v5->pTexture;
    v75 = 0;
    v21 = (unsigned __int16 *)v22->pLevelOfDetail0_prolly_alpha_mask;
  }
  a1.pTextureLOD = v21;
LABEL_12:
  if ( v21 )
  {
    a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v61, v20, v5, pOutdoorCamera->building_gamme, 1u, 1);
    a1.field_28 = 16;
    v66 = v74 >> 4;
    v81 = v8;
    v26 = v5->ptr_38;
    v72 = v74 - 16 * (v74 >> 4);
    v76 = v26->field_10;
    v81 = v8;
    v74 = v67 + ((unsigned __int64)(v76 * (signed __int64)v8) >> 16);
    v76 = v5->ptr_38->field_1C;
    v76 = v70 + ((unsigned __int64)(v76 * (signed __int64)v8) >> 16);
    v81 = (unsigned __int64)(v74 * (signed __int64)v20) >> 16;
    v27 = ((unsigned __int64)(v74 * (signed __int64)v20) >> 16) - v5->ptr_38->field_24;
    v81 = (unsigned __int64)(v76 * (signed __int64)v69) >> 16;
    v28 = v63 + ((unsigned __int64)(v76 * (signed __int64)v69) >> 16) - v5->ptr_38->field_28;
    v76 = v75 + bUseLoResSprites;
    v73 = v8 - 16 * pOutdoorCamera->int_fov_rad_inv;
    v29 = v5->pTexture;
    v30 = (v71 + v27) >> v76;
    v31 = v28 >> v76;
    v32 = (signed int)v29->uTextureWidth >> v75;
    v74 = (signed __int16)v75;
    v68 = v31;
    v80 = v32;
    v33 = (signed int)v29->uTextureHeight >> v75;
    v34 = v75 - v29->uWidthLn2;
    a1.field_8 = (v33 << 16) - 65536;
    v81 = 2 * pMiscTimer->uTotalGameTimeElapsed;
    a1.field_10 = v34 + 16;
    a1.field_C = v80 - 1;
    if ( v66 > 0 )
    {
      v74 = v66;
      v66 = 12 - v75;
      do
      {
        v80 = v5->v_18.y;
        v35 = (unsigned __int64)(v80 * (signed __int64)v73) >> 16;
        v36 = v35 + v60;
        X = v35 + v60;
        if ( v35 + v60 && (v80 = abs(v62), v37 = abs(v36), v80 <= v37) )
        {
          LODWORD(v38) = v77 << 16;
          HIDWORD(v38) = v77 >> 16;
          v80 = v38 / X;
          v39 = v38 / X;
          X = v38 / X;
        }
        else
        {
          X = 0x40000000u;
          v39 = 0x40000000u;
        }
        HIWORD(v40) = HIWORD(v39);
        if ( v39 <= v69 )
          HIWORD(v40) = HIWORD(v69);
        LOWORD(v40) = 0;
        a1.field_24 = v5->field_50 | v40;
        v79 = v5->ptr_38->field_10;
        v79 = v67 + ((unsigned __int64)(v79 * (signed __int64)v73) >> 16);
        v80 = (unsigned __int64)(v79 * (signed __int64)v39) >> 16;
        v41 = v5->ptr_38;
        v42 = ((unsigned __int64)(v79 * (signed __int64)v39) >> 16) - v41->field_24;
        v79 = v41->field_1C;
        v79 = v70 + ((unsigned __int64)(v79 * (signed __int64)v73) >> 16);
        v80 = (unsigned __int64)(v79 * (signed __int64)v39) >> 16;
        v43 = (v71 + v42) >> v76;
        v79 = (signed int)(v63 + ((unsigned __int64)(v79 * (signed __int64)v39) >> 16) - v5->ptr_38->field_28) >> v76;
        a1.field_4 = (v43 - v30) >> 4;
        a1.field_0 = (v79 - v68) >> 4;
        a1.field_30 = v30 + 4 * stru_5C6E00->Cos(v81 + (v68 >> v66));
        v44 = stru_5C6E00->Sin(v81 + (v30 >> v66));
        a1.field_2C = v68 + 4 * v44;
        if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
          sr_sub_485975(&a1, (stru315 *)&a2);
        else
          sr_sub_4D6FB0(v2);
        a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v61, X, v5, pOutdoorCamera->building_gamme, 1u, 0);
        v73 -= 16 * pOutdoorCamera->int_fov_rad_inv;
        v45 = v74-- == 1;
        a1.field_28 = 16;
        v30 = v43;
        v68 = v79;
      }
      while ( !v45 );
      v31 = v79;
    }
    if ( !v72 )
      return 1;
    v66 = 12 - v75;
    a1.field_30 = v30 + 4 * stru_5C6E00->Cos(v81 + (v31 >> (12 - v75)));
    v46 = stru_5C6E00->Sin(v81 + (v30 >> v66));
    a1.field_2C = v68 + 4 * v46;
    v79 = v5->v_18.y;
    v80 = (unsigned __int64)(v79 * (signed __int64)v73) >> 16;
    v47 = (unsigned __int64)(v79 * (signed __int64)v73) >> 16;
    v48 = v47 + v60;
    X = v47 + v60;
    if ( v47 + v60 )
    {
      v79 = abs(v62);
      v49 = abs(v48);
      if ( v79 <= v49 )
      {
        LODWORD(v50) = v77 << 16;
        HIDWORD(v50) = v77 >> 16;
        v77 = v50 / X;
        v51 = v50 / X;
        HIWORD(v52) = HIWORD(v69);
        if ( v51 <= v69 )
        {
          LOWORD(v52) = 0;
          a1.field_24 = v52 | v5->field_50;
        }
        else
        {
          HIWORD(v53) = HIWORD(v51);
          LOWORD(v53) = 0;
          a1.field_24 = v53 | v5->field_50;
        }
        v79 = v5->ptr_38->field_10;
        v77 = (unsigned __int64)(v79 * (signed __int64)v73) >> 16;
        v79 = v67 + ((unsigned __int64)(v79 * (signed __int64)v73) >> 16);
        v67 = (unsigned __int64)(v79 * (signed __int64)v51) >> 16;
        v54 = v5->ptr_38;
        v55 = v67 - v54->field_24;
        v79 = v54->field_1C;
        v56 = v71 + v55;
        v71 = (unsigned __int64)(v79 * (signed __int64)v73) >> 16;
        v57 = v70 + ((unsigned __int64)(v79 * (signed __int64)v73) >> 16);
        v79 = v57;
        v58 = v57 * (signed __int64)v51;
        v70 = v58 >> 16;
        LODWORD(v58) = (signed int)(v63 + (v58 >> 16) - v5->ptr_38->field_28) >> v76;
        a1.field_4 = ((v56 >> v76) - v30) >> 4;
        a1.field_0 = ((signed int)v58 - v68) >> 4;
        a1.field_28 = v72;
        if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
          sr_sub_485975(&a1, (stru315 *)&a2);
        else
          sr_sub_4D6FB0(v2);
        return 1;
      }
    }
  }
  return 0;
}
// 4D864C: using guessed type char byte_4D864C;
// 6BE0E4: using guessed type int mipmapping_building_mm1;
// 6BE0E8: using guessed type int mipmapping_building_mm2;
// 6BE0EC: using guessed type int mipmapping_building_mm3;

//----- (0048408A) --------------------------------------------------------
signed int sr_sub_48408A_prolly_odm_water_no_waves(Span *_this)
{
  stru315 *v1; // ebp@0
  Span *v2; // edi@1
  stru148 *v3; // esi@1
  int v4; // ecx@1
  stru149 *v5; // eax@1
  stru149 *v6; // eax@1
  int v7; // edx@1
  int v8; // eax@1
  int v9; // ebx@1
  int v10; // eax@1
  int v11; // ecx@1
  int v12; // eax@1
  int v13; // ecx@1
  int v14; // eax@1
  signed int v15; // ecx@1
  int v16; // ebx@1
  signed __int64 v17; // qtt@3
  stru149 *v18; // eax@3
  int v19; // ebx@3
  Texture *v20; // eax@4
  unsigned __int16 *v21; // eax@4
  Texture *v22; // eax@6
  Texture *v23; // ecx@8
  Texture *v24; // eax@10
  stru149 *v25; // eax@12
  signed int v26; // eax@12
  int v27; // ecx@12
  int v28; // eax@14
  int v29; // edx@14
  int v30; // ecx@14
  Texture *v31; // esi@14
  int v32; // edx@14
  int v33; // eax@14
  int v35; // [sp+Ch] [bp-8Ch]@1
  int v36; // [sp+10h] [bp-88h]@1
  stru316 a2; // [sp+14h] [bp-84h]@14
  stru315 a1; // [sp+3Ch] [bp-5Ch]@1
  int v39; // [sp+80h] [bp-18h]@1
  int v40; // [sp+84h] [bp-14h]@1
  int v41; // [sp+88h] [bp-10h]@1
  int v42; // [sp+8Ch] [bp-Ch]@1
  int v43; // [sp+90h] [bp-8h]@2
  int v44; // [sp+94h] [bp-4h]@1

  v2 = _this;
  v3 = _this->pParent;
  v4 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - _this->field_A);
  v5 = v3->ptr_38;
  v44 = v4;
  v42 = v5->field_14;
  v44 = (unsigned __int64)(v42 * (signed __int64)v4) >> 16;
  v6 = v3->ptr_38;
  v7 = v44 + v6->field_C;
  v42 = v6->field_20;
  v39 = v7;
  v8 = ((unsigned __int64)(v42 * (signed __int64)v4) >> 16) + v3->ptr_38->field_18;
  v44 = v4;
  v41 = v8;
  v42 = v3->v_18.z;
  v44 = (unsigned __int64)(v42 * (signed __int64)v4) >> 16;
  v9 = v44 + v3->v_18.x;
  v35 = stru_5C6E00->Sin(pIndoorCamera->sRotationY);
  v10 = stru_5C6E00->Cos(pIndoorCamera->sRotationY);
  v11 = v2->field_8;
  v36 = v10;
  a1.field_28 = v2->field_C;
  v12 = pViewport->uScreenCenterX - v11;
  v13 = v3->field_24;
  v42 = pOutdoorCamera->int_fov_rad_inv * v12;
  v14 = v3->v_18.y;
  v15 = -v13;
  v40 = v15;
  v16 = ((unsigned __int64)(v42 * (signed __int64)v14) >> 16) + v9;
  v44 = v16;
  if ( !v16 || (v43 = abs(v15 >> 14), v43 > abs(v16)) )
    return 0;
  LODWORD(v17) = v40 << 16;
  HIDWORD(v17) = v40 >> 16;
  v43 = v17 / v44;
  v18 = v3->ptr_38;
  v44 = v42;
  v40 = v18->field_10;
  v44 = v42;
  v40 = v39 + ((unsigned __int64)(v40 * (signed __int64)v42) >> 16);
  v39 = v3->ptr_38->field_1C;
  v44 = (unsigned __int64)(v39 * (signed __int64)v42) >> 16;
  v19 = v43;
  v41 += (unsigned __int64)(v39 * (signed __int64)v42) >> 16;
  a1.pTextureLOD = (unsigned __int16 *)v3->pTexture->pLevelOfDetail2;
  v44 = 2;
  if ( v43 < mipmapping_terrain_mm1 << 16 )
  {
    v20 = v3->pTexture;
    v44 = 0;
    v21 = (unsigned __int16 *)v20->pLevelOfDetail0_prolly_alpha_mask;
LABEL_11:
    a1.pTextureLOD = v21;
    goto LABEL_12;
  }
  if ( v43 < mipmapping_terrain_mm2 << 16 )
  {
    v22 = v3->pTexture;
    v44 = 1;
    v21 = (unsigned __int16 *)v22->pLevelOfDetail1;
    goto LABEL_11;
  }
  if ( v43 >= mipmapping_terrain_mm3 << 16 )
  {
    if ( !bUseLoResSprites )
    {
      v24 = v3->pTexture;
      v44 = 3;
      v21 = (unsigned __int16 *)v24->pLevelOfDetail3;
      goto LABEL_11;
    }
  }
  else
  {
    v23 = v3->pTexture;
    v44 = 2;
    a1.pTextureLOD = (unsigned __int16 *)v23->pLevelOfDetail2;
  }
LABEL_12:
  v43 = (unsigned __int64)(v40 * (signed __int64)v43) >> 16;
  v25 = v3->ptr_38;
  v43 = v19;
  a1.field_30 = ((unsigned __int64)(v40 * (signed __int64)v19) >> 16) - v25->field_24;
  v43 = (unsigned __int64)(v41 * (signed __int64)v19) >> 16;
  v26 = ((unsigned __int64)(v41 * (signed __int64)v19) >> 16) - v3->ptr_38->field_28;
  v27 = bUseLoResSprites + v44 + 2;
  a1.field_30 >>= v27;
  v41 = bUseLoResSprites + v44 + 2;
  a1.field_2C = v26 >> v27;
  if ( byte_80AA10 )
  {
    a1.field_14 = dword_80AA20 >> v27;
    a1.field_18 = dword_80AA1C >> v27;
    a1.field_1C = dword_80AA18 >> v27;
    a1.field_20 = dword_80AA14 >> v27;
  }
  v41 = pOutdoorCamera->int_fov_rad_inv;
  v42 = (signed int)((unsigned __int64)(pOutdoorCamera->int_fov_rad_inv * (signed __int64)v19) >> 16) >> v27;
  a1.field_4 = (unsigned __int64)(v42 * (signed __int64)v35) >> 16;
  v43 = (unsigned __int64)(v42 * (signed __int64)v36) >> 16;
  a1.field_0 = (unsigned __int64)(v42 * (signed __int64)v36) >> 16;
  a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v2, v19, v3, pOutdoorCamera->terrain_gamma, 1u, 1);
  LOWORD(v19) = 0;
  v28 = v2->field_A;
  v29 = v2->field_A;
  a1.field_24 = v19;
  v30 = v2->field_8;
  a1.pColorBuffer = &pRenderer->pTargetSurface[v30 + pRenderer->uTargetSurfacePitch * v29];
  a1.pDepthBuffer = (unsigned int *)&pRenderer->pActiveZBuffer[v30 + 640 * v28];
  v31 = v3->pTexture;
  v32 = ((signed int)v31->uTextureWidth >> v44) - 1;
  v33 = ((signed int)v31->uTextureHeight >> v44 << 16) - 65536;
  a1.field_10 = v44 - v31->uWidthLn2 + 16;
  a1.field_C = v32;
  a1.field_8 = v33;
  if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
  {
    if ( byte_80AA10 )
      sr_sub_485A24(&a1, (stru315 *)&a2);
    else
      sr_sub_485975(&a1, (stru315 *)&a2);
  }
  else
  {
    if ( byte_80AA10 )
      sr_sub_4D705A(v1);
    else
      sr_sub_4D6FB0(v1);
  }
  return 1;
}

//----- (00484442) --------------------------------------------------------
signed int sr_sub_484442(Span *_this)
{
  int v1; // ebp@0
  Span *v2; // edi@1
  stru148 *v3; // esi@1
  int v4; // ecx@1
  stru149 *v5; // eax@1
  stru149 *v6; // eax@1
  int v7; // edx@1
  int v8; // eax@1
  int v9; // ebx@1
  int v10; // eax@1
  int v11; // ecx@1
  int v12; // eax@1
  int v13; // ecx@1
  signed int v14; // ecx@1
  int v15; // ebx@1
  signed __int64 v16; // qtt@3
  int v17; // ecx@3
  int v18; // ebx@3
  int v19; // eax@3
  signed int v20; // ebx@3
  unsigned __int16 *v21; // eax@4
  stru149 *v22; // eax@12
  signed int v23; // eax@12
  int v24; // ecx@12
  int v25; // ecx@14
  unsigned int *v26; // eax@14
  Texture *v27; // esi@14
  signed int v28; // edi@14
  signed int v29; // eax@14
  signed int v31; // [sp+Ch] [bp-90h]@1
  int v32; // [sp+10h] [bp-8Ch]@1
  int v33; // [sp+14h] [bp-88h]@1
  stru316 v34; // [sp+18h] [bp-84h]@14
  stru315 v35; // [sp+40h] [bp-5Ch]@1
  int v36; // [sp+84h] [bp-18h]@1
  int v37; // [sp+88h] [bp-14h]@1
  int v38; // [sp+8Ch] [bp-10h]@1
  int v39; // [sp+90h] [bp-Ch]@1
  int v40; // [sp+94h] [bp-8h]@1
  int v41; // [sp+98h] [bp-4h]@1

  v2 = _this;
  v3 = _this->pParent;
  v4 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - _this->field_A);
  v5 = v3->ptr_38;
  v40 = v4;
  v39 = v5->field_14;
  v40 = (unsigned __int64)(v39 * (signed __int64)v4) >> 16;
  v6 = v3->ptr_38;
  v7 = v40 + v6->field_C;
  v39 = v6->field_20;
  v36 = v7;
  v8 = ((unsigned __int64)(v39 * (signed __int64)v4) >> 16) + v3->ptr_38->field_18;
  v40 = v4;
  v38 = v8;
  v39 = v3->v_18.z;
  v40 = (unsigned __int64)(v39 * (signed __int64)v4) >> 16;
  v9 = v40 + v3->v_18.x;
  v32 = stru_5C6E00->Sin(pIndoorCamera->sRotationY);
  v10 = stru_5C6E00->Cos(pIndoorCamera->sRotationY);
  v11 = v2->field_8;
  v33 = v10;
  v35.field_28 = v2->field_C;
  v12 = pViewport->uScreenCenterX - v11;
  v13 = v3->field_24;
  v41 = pOutdoorCamera->int_fov_rad_inv * v12;
  v14 = -v13;
  v31 = v14;
  v15 = ((unsigned __int64)(pOutdoorCamera->int_fov_rad_inv * v12 * (signed __int64)v3->v_18.y) >> 16) + v9;
  v37 = v15;
  if ( !v15 || (v39 = abs(v14 >> 14), v39 > abs(v15)) )
    return 0;
  LODWORD(v16) = v31 << 16;
  HIDWORD(v16) = v31 >> 16;
  v40 = v16 / v37;
  v17 = v16 / v37;
  v18 = v41;
  HIWORD(v19) = (unsigned int)(v16 / v37) >> 16;
  LOWORD(v19) = 0;
  v35.field_24 = v19;
  v37 = v36 + ((unsigned __int64)(v3->ptr_38->field_10 * (signed __int64)v41) >> 16);
  v36 = v3->ptr_38->field_1C;
  v41 = (unsigned __int64)(v36 * (signed __int64)v41) >> 16;
  v38 += (unsigned __int64)(v36 * (signed __int64)v18) >> 16;
  v20 = 2;
  v35.pTextureLOD = (unsigned __int16 *)v3->pTexture->pLevelOfDetail2;
  if ( v17 < mipmapping_terrain_mm1 << 16 )
  {
    v20 = 0;
    v21 = (unsigned __int16 *)v3->pTexture->pLevelOfDetail0_prolly_alpha_mask;
LABEL_11:
    v35.pTextureLOD = v21;
    goto LABEL_12;
  }
  if ( v17 < mipmapping_terrain_mm2 << 16 )
  {
    v20 = 1;
    v21 = (unsigned __int16 *)v3->pTexture->pLevelOfDetail1;
    goto LABEL_11;
  }
  if ( v17 < mipmapping_terrain_mm3 << 16 )
  {
    v21 = (unsigned __int16 *)v3->pTexture->pLevelOfDetail2;
    goto LABEL_11;
  }
  if ( !bUseLoResSprites )
  {
    v20 = 3;
    v21 = (unsigned __int16 *)v3->pTexture->pLevelOfDetail3;
    goto LABEL_11;
  }
LABEL_12:
  v41 = (unsigned __int64)(v37 * (signed __int64)v17) >> 16;
  v22 = v3->ptr_38;
  v41 = v17;
  v35.field_30 = ((unsigned __int64)(v37 * (signed __int64)v17) >> 16) - v22->field_24;
  v23 = ((unsigned __int64)(v38 * (signed __int64)v17) >> 16) - v3->ptr_38->field_28;
  v24 = bUseLoResSprites + v20 + 2;
  v35.field_30 >>= v24;
  v38 = bUseLoResSprites + v20 + 2;
  v35.field_2C = v23 >> v24;
  if ( byte_80AA10 )
  {
    v35.field_14 = dword_80AA20 >> v24;
    v35.field_18 = dword_80AA1C >> v24;
    v35.field_1C = dword_80AA18 >> v24;
    v35.field_20 = dword_80AA14 >> v24;
  }
  v38 = pOutdoorCamera->int_fov_rad_inv;
  v39 = (signed int)((unsigned __int64)(pOutdoorCamera->int_fov_rad_inv * (signed __int64)v40) >> 16) >> v24;
  v35.field_4 = (unsigned __int64)(v39 * (signed __int64)v32) >> 16;
  v41 = (unsigned __int64)(v39 * (signed __int64)v33) >> 16;
  v35.field_0 = (unsigned __int64)(v39 * (signed __int64)v33) >> 16;
  v35.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&v34, v2, v40, v3, pOutdoorCamera->terrain_gamma, 1u, 1);
  v25 = v2->field_8;
  v26 = (unsigned int *)&pRenderer->pActiveZBuffer[v25 + 640 * v2->field_A];
  v35.pColorBuffer = &pRenderer->pTargetSurface[v25 + pRenderer->uTargetSurfacePitch * v2->field_A];
  v35.pDepthBuffer = v26;
  v27 = v3->pTexture;
  v28 = (signed int)v27->uTextureWidth >> v20;
  v29 = (signed int)v27->uTextureHeight >> v20;
  v35.field_10 = v20 - v27->uWidthLn2 + 16;
  v35.field_C = v28 - 1;
  v35.field_8 = (v29 << 16) - 65536;
  if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
  {
    if ( byte_80AA10 )
      sr_sub_485D3E(&v35, &v34);
    else
      sr_sub_485C89(&v35, &v34);
  }
  else
  {
    if ( byte_80AA10 )
      sr_sub_4D72EC(v1);
    else
      sr_sub_4D73DF(v1);
  }
  return 1;
}

//----- (004847EB) --------------------------------------------------------
int sr_sub_4847EB(Span *_this)
{
  stru315 *v1; // ebp@0
  int v2; // ebx@1
  int v3; // edx@1
  stru148 *v4; // esi@1
  int v5; // eax@1
  signed int v6; // eax@3
  int v7; // edi@3
  stru149 *v8; // eax@3
  stru149 *v9; // eax@3
  int v10; // edx@3
  int v11; // eax@3
  signed int v12; // ebx@3
  int v13; // ebx@4
  signed __int64 v14; // qtt@5
  int v15; // eax@5
  signed int v16; // ebx@5
  unsigned __int16 *v17; // ecx@6
  stru149 *v18; // eax@14
  stru149 *v19; // eax@14
  signed int v20; // eax@14
  int v21; // ecx@14
  Texture *v22; // edx@16
  signed int v23; // eax@16
  int v24; // ebx@16
  int v25; // edi@17
  int v26; // ebx@17
  int v27; // eax@17
  int v28; // edi@17
  int v29; // eax@18
  signed __int64 v30; // qtt@19
  int v31; // ecx@19
  int v32; // eax@19
  stru149 *v33; // eax@21
  signed int v34; // edi@21
  int v35; // ebx@21
  signed int v36; // edi@21
  signed __int64 v37; // qtt@21
  signed int v38; // ebx@21
  int v39; // ebx@29
  int v40; // eax@32
  unsigned __int64 v41; // qax@32
  int v42; // edi@32
  int v43; // eax@33
  signed __int64 v44; // qtt@34
  int v45; // ecx@34
  int v46; // eax@34
  stru149 *v47; // eax@36
  signed int v48; // edi@36
  int v49; // eax@36
  int v50; // eax@47
  unsigned __int64 v51; // qax@47
  int v52; // edi@47
  int v53; // eax@48
  signed __int64 v54; // qtt@49
  int v55; // ecx@49
  int v56; // eax@49
  stru149 *v57; // eax@51
  signed int v58; // edi@51
  int v59; // eax@51
  Span *v61; // [sp+Ch] [bp-B0h]@1
  int v62; // [sp+10h] [bp-ACh]@3
  int v63; // [sp+14h] [bp-A8h]@3
  int v64; // [sp+18h] [bp-A4h]@3
  int v65; // [sp+1Ch] [bp-A0h]@3
  signed int v66; // [sp+20h] [bp-9Ch]@3
  signed int v67; // [sp+24h] [bp-98h]@3
  int v68; // [sp+28h] [bp-94h]@1
  char v69; // [sp+2Ch] [bp-90h]@1
  stru315 sr; // [sp+30h] [bp-8Ch]@1
  stru316 sr2; // [sp+74h] [bp-48h]@14
  int v72; // [sp+9Ch] [bp-20h]@5
  int v73; // [sp+A0h] [bp-1Ch]@1
  int v74; // [sp+A4h] [bp-18h]@3
  int v75; // [sp+A8h] [bp-14h]@21
  int v76; // [sp+ACh] [bp-10h]@1
  int v77; // [sp+B0h] [bp-Ch]@14
  int v78; // [sp+B4h] [bp-8h]@3
  int v79; // [sp+B8h] [bp-4h]@3

  v2 = _this->field_A;
  v3 = _this->field_8;
  v4 = _this->pParent;
  v73 = 0;
  v61 = _this;
  sr.pDepthBuffer = (unsigned int *)&pRenderer->pActiveZBuffer[v3 + 640 * v2];
  v76 = v3;
  v5 = _this->field_C;
  sr.pColorBuffer = &pRenderer->pTargetSurface[v3 + pRenderer->uTargetSurfacePitch * v2];
  v68 = texmapping_terrain_subdivsize;
  v69 = texmapping_terrain_subdivpow2;
  if ( v5 >= texmapping_terrain_subdivsize )
    v73 = texmapping_terrain_subdivsize - (v3 & (texmapping_terrain_subdivsize - 1));
  v6 = v5 - v73;
  v67 = v6 >> texmapping_terrain_subdivpow2;
  v62 = v6 - (v6 >> texmapping_terrain_subdivpow2 << texmapping_terrain_subdivpow2);
  v7 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterX - v76);
  v8 = v4->ptr_38;
  v79 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterX - v76);
  v78 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - v2);
  v76 = v8->field_14;
  v78 = (unsigned __int64)(v76 * (signed __int64)(pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - v2))) >> 16;
  v9 = v4->ptr_38;
  v10 = v78 + v9->field_C;
  v76 = v9->field_20;
  v65 = v10;
  v11 = ((unsigned __int64)(v76 * (signed __int64)(pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - v2))) >> 16)
      + v4->ptr_38->field_18;
  v78 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - v2);
  v64 = v11;
  v76 = v4->v_18.z;
  v78 = (unsigned __int64)(v76 * (signed __int64)(pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - v2))) >> 16;
  v12 = -v4->field_24;
  v63 = v78 + v4->v_18.x;
  v66 = -v4->field_24;
  v78 = (unsigned __int64)(v79 * (signed __int64)v4->v_18.y) >> 16;
  v74 = v78 + v63;
  if ( !(v78 + v63) || (v76 = v12 >> 14, v13 = abs(v12 >> 14), v13 > abs(v74)) )
    return 0;
  LODWORD(v14) = v66 << 16;
  HIDWORD(v14) = v66 >> 16;
  v72 = v14 / v74;
  sr.pTextureLOD = (unsigned __int16 *)v4->pTexture->pLevelOfDetail2;
  v15 = v14 / v74;
  v16 = 2;
  if ( v15 >= mipmapping_terrain_mm1 << 16 )
  {
    if ( v15 >= mipmapping_terrain_mm2 << 16 )
    {
      if ( v15 >= mipmapping_terrain_mm3 << 16 )
      {
        if ( bUseLoResSprites )
          goto LABEL_14;
        v16 = 3;
        v17 = (unsigned __int16 *)v4->pTexture->pLevelOfDetail3;
      }
      else
      {
        v17 = (unsigned __int16 *)v4->pTexture->pLevelOfDetail2;
      }
    }
    else
    {
      v16 = 1;
      v17 = (unsigned __int16 *)v4->pTexture->pLevelOfDetail1;
    }
  }
  else
  {
    v16 = 0;
    v17 = (unsigned __int16 *)v4->pTexture->pLevelOfDetail0_prolly_alpha_mask;
  }
  sr.pTextureLOD = v17;
LABEL_14:
  sr.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&sr2, v61, v15, v4, pOutdoorCamera->terrain_gamma, 1u, 1);
  v18 = v4->ptr_38;
  v78 = v7;
  v79 = v18->field_10;
  v78 = v7;
  v77 = v65 + ((unsigned __int64)(v79 * (signed __int64)v7) >> 16);
  v79 = v4->ptr_38->field_1C;
  v79 = v64 + ((unsigned __int64)(v79 * (signed __int64)v7) >> 16);
  v78 = (unsigned __int64)(v77 * (signed __int64)v72) >> 16;
  v19 = v4->ptr_38;
  v78 = v72;
  sr.field_30 = ((unsigned __int64)(v77 * (signed __int64)v72) >> 16) - v19->field_24;
  v78 = (unsigned __int64)(v79 * (signed __int64)v72) >> 16;
  v20 = ((unsigned __int64)(v79 * (signed __int64)v72) >> 16) - v4->ptr_38->field_28;
  v21 = bUseLoResSprites + v16 + 2;
  sr.field_30 >>= v21;
  v78 = bUseLoResSprites + v16 + 2;
  sr.field_2C = v20 >> v21;
  if ( byte_80AA10 )
  {
    sr.field_14 = dword_80AA20 >> v21;
    sr.field_18 = dword_80AA1C >> v21;
    sr.field_1C = dword_80AA18 >> v21;
    sr.field_20 = dword_80AA14 >> v21;
  }
  v22 = v4->pTexture;
  v79 = (signed int)v22->uTextureWidth >> v16;
  v23 = (signed int)v22->uTextureHeight >> v16;
  v24 = v16 - v22->uWidthLn2 + 16;
  sr.field_8 = (v23 << 16) - 65536;
  sr.field_10 = v24;
  sr.field_C = v79 - 1;
  if ( v73 )
  {
    v25 = v7 - v73 * pOutdoorCamera->int_fov_rad_inv;
    v26 = v25;
    v77 = v4->v_18.y;
    v79 = v25;
    v27 = (unsigned __int64)(v77 * (signed __int64)v25) >> 16;
    v28 = v27 + v63;
    v74 = v27 + v63;
    if ( !(v27 + v63) || (v77 = abs(v76), v29 = abs(v28), v77 > v29) )
      return 0;
    LODWORD(v30) = v66 << 16;
    HIDWORD(v30) = v66 >> 16;
    v77 = v30 / v74;
    v31 = v30 / v74;
    HIWORD(v32) = HIWORD(v72);
    if ( v72 <= v31 )
      HIWORD(v32) = HIWORD(v31);
    LOWORD(v32) = 0;
    v77 = v26;
    sr.field_24 = v32;
    v74 = v4->ptr_38->field_10;
    v74 = v65 + ((unsigned __int64)(v74 * (signed __int64)v26) >> 16);
    v77 = (unsigned __int64)(v74 * (signed __int64)v31) >> 16;
    v33 = v4->ptr_38;
    v77 = v26;
    v34 = ((unsigned __int64)(v74 * (signed __int64)v31) >> 16) - v33->field_24;
    v74 = v33->field_1C;
    v74 = v64 + ((unsigned __int64)(v74 * (signed __int64)v26) >> 16);
    v77 = (unsigned __int64)(v74 * (signed __int64)v31) >> 16;
    v35 = (v77 - v4->ptr_38->field_28) >> v78;
    v74 = v73 << 16;
    v36 = (v34 >> v78) - sr.field_30;
    LODWORD(v37) = v36 << 16;
    HIDWORD(v37) = v36 >> 16;
    v38 = v35 - sr.field_2C;
    sr.field_4 = v37 / (v73 << 16);
    v75 = v73 << 16;
    LODWORD(v37) = v38 << 16;
    HIDWORD(v37) = v38 >> 16;
    v77 = v37 / (v73 << 16);
    sr.field_0 = v37 / (v73 << 16);
    sr.field_28 = v73;
    if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
    {
      if ( byte_80AA10 )
        sr_sub_485A24(&sr, (stru315 *)&sr2);
      else
        sr_sub_485975(&sr, (stru315 *)&sr2);
    }
    else
    {
      if ( byte_80AA10 )
        sr_sub_4D705A(v1);
      else
        sr_sub_4D6FB0(v1);
    }
    v39 = v79 - (pOutdoorCamera->int_fov_rad_inv << v69);
  }
  else
  {
    v79 = v7 - (pOutdoorCamera->int_fov_rad_inv << v69);
    v39 = v7 - (pOutdoorCamera->int_fov_rad_inv << v69);
  }
  sr.field_28 = v68;
  while ( v67 > 0 )
  {
    v40 = v4->v_18.y;
    --v67;
    v75 = v40;
    v41 = v40 * (signed __int64)v39;
    v79 = v41 >> 16;
    LODWORD(v41) = v41 >> 16;
    v42 = v41 + v63;
    v74 = v41 + v63;
    if ( !((int)v41 + v63) || (v75 = abs(v76), v43 = abs(v42), v75 > v43) )
      return 0;
    LODWORD(v44) = v66 << 16;
    HIDWORD(v44) = v66 >> 16;
    v73 = v44 / v74;
    v45 = v44 / v74;
    HIWORD(v46) = HIWORD(v72);
    if ( v72 <= v45 )
      HIWORD(v46) = HIWORD(v45);
    LOWORD(v46) = 0;
    v79 = v39;
    sr.field_24 = v46;
    v75 = v4->ptr_38->field_10;
    v75 = v65 + ((unsigned __int64)(v75 * (signed __int64)v39) >> 16);
    v79 = (unsigned __int64)(v75 * (signed __int64)v45) >> 16;
    v47 = v4->ptr_38;
    v79 = v39;
    v48 = ((unsigned __int64)(v75 * (signed __int64)v45) >> 16) - v47->field_24;
    v75 = v47->field_1C;
    v75 = v64 + ((unsigned __int64)(v75 * (signed __int64)v39) >> 16);
    v79 = (unsigned __int64)(v75 * (signed __int64)v45) >> 16;
    v49 = (((v79 - v4->ptr_38->field_28) >> v78) - sr.field_2C) >> v69;
    sr.field_4 = ((v48 >> v78) - sr.field_30) >> v69;
    sr.field_0 = v49;
    if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
    {
      if ( byte_80AA10 )
        sr_sub_485A24(&sr, (stru315 *)&sr2);
      else
        sr_sub_485975(&sr, (stru315 *)&sr2);
    }
    else
    {
      if ( byte_80AA10 )
        sr_sub_4D705A(v1);
      else
        sr_sub_4D6FB0(v1);
    }
    sr.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&sr2, v61, v73, v4, pOutdoorCamera->terrain_gamma, 1u, 0);
    sr.field_28 = v68;
    v39 -= pOutdoorCamera->int_fov_rad_inv << v69;
  }
  if ( !v62 )
    return 1;
  v50 = v4->v_18.y;
  v75 = v50;
  v51 = v50 * (signed __int64)v39;
  v79 = v51 >> 16;
  LODWORD(v51) = v51 >> 16;
  v52 = v51 + v63;
  v74 = v51 + v63;
  if ( (int)v51 + v63 )
  {
    v75 = abs(v76);
    v53 = abs(v52);
    if ( v75 <= v53 )
    {
      LODWORD(v54) = v66 << 16;
      HIDWORD(v54) = v66 >> 16;
      v76 = v54 / v74;
      v55 = v54 / v74;
      HIWORD(v56) = HIWORD(v72);
      if ( v72 <= v55 )
        HIWORD(v56) = HIWORD(v55);
      LOWORD(v56) = 0;
      v76 = v39;
      sr.field_24 = v56;
      v75 = v4->ptr_38->field_10;
      v75 = v65 + ((unsigned __int64)(v75 * (signed __int64)v39) >> 16);
      v76 = (unsigned __int64)(v75 * (signed __int64)v55) >> 16;
      v57 = v4->ptr_38;
      v76 = v39;
      v58 = ((unsigned __int64)(v75 * (signed __int64)v55) >> 16) - v57->field_24;
      v75 = v57->field_1C;
      v75 = v64 + ((unsigned __int64)(v75 * (signed __int64)v39) >> 16);
      v76 = (unsigned __int64)(v75 * (signed __int64)v55) >> 16;
      v59 = (((v76 - v4->ptr_38->field_28) >> v78) - sr.field_2C) >> v69;
      sr.field_4 = ((v58 >> v78) - sr.field_30) >> v69;
      sr.field_0 = v59;
      sr.field_28 = v62;
      if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
      {
        if ( byte_80AA10 )
          sr_sub_485A24(&sr, (stru315 *)&sr2);
        else
          sr_sub_485975(&sr, (stru315 *)&sr2);
      }
      else
      {
        if ( byte_80AA10 )
          sr_sub_4D705A(v1);
        else
          sr_sub_4D6FB0(v1);
      }
      return 1;
    }
  }
  return 0;
}
// 4D864C: using guessed type char byte_4D864C;
// 6BE050: using guessed type int texmapping_terrain_subdivsize;
// 6BE054: using guessed type int texmapping_terrain_subdivpow2;
// 6BE0F0: using guessed type int mipmapping_terrain_mm1;
// 6BE0F4: using guessed type int mipmapping_terrain_mm2;
// 6BE0F8: using guessed type int mipmapping_terrain_mm3;
// 80AA10: using guessed type char byte_80AA10;
// 80AA14: using guessed type int dword_80AA14;
// 80AA18: using guessed type int dword_80AA18;
// 80AA1C: using guessed type int dword_80AA1C;
// 80AA20: using guessed type int dword_80AA20;

//----- (00485407) --------------------------------------------------------
signed int __fastcall sr_sub_485407_prolly_odm_water_wavy(Span *a1)
{
  stru315 *v1; // ebp@0
  int v2; // eax@1
  int v3; // edx@1
  unsigned int v4; // edi@1
  stru148 *v5; // esi@1
  int v6; // ecx@1
  int v7; // ebx@1
  int v8; // ecx@1
  stru149 *v9; // eax@1
  stru149 *v10; // eax@1
  int v11; // edx@1
  int v12; // eax@1
  int v13; // eax@1
  int v14; // ecx@1
  signed int v15; // edi@1
  int v16; // edi@2
  signed __int64 v17; // qtt@3
  int v18; // edi@3
  int v19; // eax@3
  unsigned __int8 *pLOD; // eax@3
  Texture *v21; // eax@4
  Texture *v22; // eax@6
  Texture *v23; // eax@8
  Texture *v24; // eax@10
  stru149 *v25; // eax@13
  stru149 *v26; // eax@13
  signed int v27; // ebx@13
  stru149 *v28; // eax@13
  Texture *v29; // esi@13
  signed int v30; // ebx@13
  signed int v31; // edi@13
  signed int v32; // edx@13
  signed int v33; // eax@13
  int v34; // esi@13
  int v35; // eax@13
  unsigned __int64 v36; // qax@13
  int v37; // eax@13
  unsigned __int64 v38; // qax@13
  char v39; // cl@14
  stru316 a2; // [sp+Ch] [bp-90h]@13
  stru315 a1a; // [sp+34h] [bp-68h]@1
  Span *v43; // [sp+78h] [bp-24h]@1
  int v44; // [sp+7Ch] [bp-20h]@1
  int v45; // [sp+80h] [bp-1Ch]@1
  int v46; // [sp+84h] [bp-18h]@1
  Span *v47; // [sp+88h] [bp-14h]@1
  int v48; // [sp+8Ch] [bp-10h]@1
  int v49; // [sp+90h] [bp-Ch]@3
  int i; // [sp+94h] [bp-8h]@3
  int X; // [sp+98h] [bp-4h]@1

  v2 = a1->field_A;
  v3 = a1->field_8;
  v4 = v3 + pRenderer->uTargetSurfacePitch * a1->field_A;
  v5 = a1->pParent;
  v43 = a1;
  v6 = a1->field_C;
  a1a.pColorBuffer = &pRenderer->pTargetSurface[v4];
  v46 = v6;
  v7 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterX - v3);
  v8 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - v2);
  a1a.pDepthBuffer = (unsigned int *)&pRenderer->pActiveZBuffer[v3 + 640 * v2];
  v9 = v5->ptr_38;
  v47 = (Span *)v7;
  X = v8;
  v48 = v9->field_14;
  X = (unsigned __int64)(v48 * (signed __int64)v8) >> 16;
  v10 = v5->ptr_38;
  v11 = X + v10->field_C;
  v48 = v10->field_20;
  v44 = v11;
  v12 = ((unsigned __int64)(v48 * (signed __int64)v8) >> 16) + v5->ptr_38->field_18;
  X = v8;
  v45 = v12;
  v48 = v5->v_18.z;
  X = (unsigned __int64)(v48 * (signed __int64)v8) >> 16;
  v13 = v5->v_18.y;
  v14 = X + v5->v_18.x;
  v15 = -v5->field_24;
  v48 = -v5->field_24;
  X = ((unsigned __int64)(v7 * (signed __int64)v13) >> 16) + v14;
  if ( !X || (v16 = abs(v15 >> 14), v16 > abs(X)) )
    return 0;
  LODWORD(v17) = v48 << 16;
  HIDWORD(v17) = v48 >> 16;
  i = v17 / X;
  v18 = v17 / X;
  HIWORD(v19) = (unsigned int)(v17 / X) >> 16;
  LOWORD(v19) = 0;
  a1a.field_24 = v19;
  pLOD = v5->pTexture->pLevelOfDetail2;
  a1a.pTextureLOD = (unsigned __int16 *)v5->pTexture->pLevelOfDetail2;
  v49 = 2;
  if ( v18 >= mipmapping_terrain_mm1 << 16 )
  {
    if ( v18 >= mipmapping_terrain_mm2 << 16 )
    {
      if ( v18 >= mipmapping_terrain_mm3 << 16 )
      {
        if ( bUseLoResSprites )
          goto LABEL_12;
        v24 = v5->pTexture;
        v49 = 3;
        pLOD = v24->pLevelOfDetail3;
      }
      else
      {
        v23 = v5->pTexture;
        v49 = 2;
        pLOD = v23->pLevelOfDetail2;
      }
    }
    else
    {
      v22 = v5->pTexture;
      v49 = 1;
      pLOD = v22->pLevelOfDetail1;
    }
  }
  else
  {
    v21 = v5->pTexture;
    v49 = 0;
    pLOD = v21->pLevelOfDetail0_prolly_alpha_mask;
  }
  a1a.pTextureLOD = (unsigned __int16 *)pLOD;
LABEL_12:
  if ( !pLOD )
    return 0;
  a1a.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v43, v18, v5, pOutdoorCamera->terrain_gamma, 1u, 1);
  a1a.field_28 = 16;
  v43 = (Span *)(v46 >> 4);
  X = v7;
  v25 = v5->ptr_38;
  v48 = v46 - 16 * (v46 >> 4);
  v46 = v25->field_10;
  X = v7;
  v46 = v44 + ((unsigned __int64)(v46 * (signed __int64)v7) >> 16);
  v44 = v5->ptr_38->field_1C;
  v45 += (unsigned __int64)(v44 * (signed __int64)v7) >> 16;
  X = (unsigned __int64)(v46 * (signed __int64)v18) >> 16;
  v26 = v5->ptr_38;
  X = v18;
  v27 = ((unsigned __int64)(v46 * (signed __int64)v18) >> 16) - v26->field_24;
  X = (unsigned __int64)(v45 * (signed __int64)v18) >> 16;
  v28 = v5->ptr_38;
  v29 = v5->pTexture;
  v44 = bUseLoResSprites + v49 + 2;
  v30 = v27 >> v44;
  v31 = (signed int)(((unsigned __int64)(v45 * (signed __int64)v18) >> 16) - v28->field_28) >> v44;
  v32 = (signed int)v29->uTextureWidth >> v49;
  v33 = (signed int)v29->uTextureHeight >> v49;
  v34 = v49 - v29->uWidthLn2;
  a1a.field_8 = (v33 << 16) - 65536;
  X = 2 * pMiscTimer->uTotalGameTimeElapsed;
  v45 = pOutdoorCamera->int_fov_rad_inv;
  a1a.field_10 = v34 + 16;
  a1a.field_C = v32 - 1;
  i = (unsigned __int64)(pOutdoorCamera->int_fov_rad_inv * (signed __int64)i) >> 16;
  v47 = (Span *)(i >> v44);
  v35 = stru_5C6E00->Sin(pIndoorCamera->sRotationY);
  v36 = (signed int)v47 * (signed __int64)v35;
  i = v36 >> 16;
  a1a.field_4 = v36 >> 16;
  v37 = stru_5C6E00->Cos(pIndoorCamera->sRotationY);
  v38 = (signed int)v47 * (signed __int64)v37;
  i = v38 >> 16;
  a1a.field_0 = v38 >> 16;
  if ( (signed int)v43 > 0 )
  {
    v47 = v43;
    v39 = 12 - v49;
    for ( i = 12 - v49; ; v39 = i )
    {
      a1a.field_30 = v30 + 4 * stru_5C6E00->Cos(X + (v31 >> v39));
      a1a.field_2C = v31 + 4 * stru_5C6E00->Sin(X + (v30 >> i));
      if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
        sr_sub_485975(&a1a, (stru315 *)&a2);
      else
        sr_sub_4D6FB0(v1);
      a1a.field_28 = 16;
      v30 += 16 * a1a.field_4;
      v31 += 16 * a1a.field_0;
      v47 = (Span *)((char *)v47 - 1);
      if ( !v47 )
        break;
    }
  }
  if ( v48 )
  {
    i = 12 - v49;
    a1a.field_30 = v30 + 4 * stru_5C6E00->Cos(X + (v31 >> (12 - v49)));
    a1a.field_2C = v31 + 4 * stru_5C6E00->Sin(X + (v30 >> i));
    a1a.field_28 = v48;
    if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
      sr_sub_485975(&a1a, (stru315 *)&a2);
    else
      sr_sub_4D6FB0(v1);
  }
  return 1;
}

//----- (0048585C) --------------------------------------------------------
signed int __fastcall sr_sub_48585C_mb_DrawSpan(Span *a1, unsigned __int16 *pRenderTarget, int a4)
{
  Span *v3; // esi@1
  stru148 *v4; // edi@1
  int v5; // ebx@2
  signed __int64 v6; // qtt@3
  int v7; // ebx@3
  signed int v8; // ecx@3
  void *v9; // eax@5
  int v10; // ecx@5
  unsigned __int16 *pPixels; // [sp+Ch] [bp-14h]@1
  signed int v13; // [sp+10h] [bp-10h]@1
  int X; // [sp+18h] [bp-8h]@1

  v3 = a1;
  pPixels = pRenderTarget;
  v4 = a1->pParent;
  v13 = -v4->field_24;
  X = ((unsigned __int64)(pOutdoorCamera->int_fov_rad_inv
                        * (pViewport->uScreenCenterX - (signed int)a1->field_8)
                        * (signed __int64)v4->v_18.y) >> 16)
    + ((unsigned __int64)(v4->v_18.z
                        * (signed __int64)(pOutdoorCamera->int_fov_rad_inv
                                         * (pViewport->uScreenCenterY - (signed int)a1->field_A))) >> 16)
    + v4->v_18.x;
  if ( X && (v5 = abs(-v4->field_24 >> 14), v5 <= abs(X)) )
  {
    LODWORD(v6) = v13 << 16;
    HIDWORD(v6) = v13 >> 16;
    v7 = v6 / X;
    v8 = v6 / X;
  }
  else
  {
    v7 = pOutdoorCamera->shading_dist_mist << 16;
    v8 = pOutdoorCamera->shading_dist_mist << 16;
  }
  v9 = sr_sub_47C178(v8, v4, pOutdoorCamera->terrain_gamma, a4);
  fill_pixels_fast(*((short *)v9 + v4->pTexture->uDecompressedSize), pPixels, v3->field_C);
  HIWORD(v10) = HIWORD(v7);
  LOWORD(v10) = 0;
  j_memset32(v10, &pRenderer->pActiveZBuffer[v3->field_8 + 640 * v3->field_A], v3->field_C);
  return 1;
}

//----- (00485975) --------------------------------------------------------
stru315 *__fastcall sr_sub_485975(stru315 *a1, stru315 *a2)
{
  stru315 *result; // eax@1
  int i; // ecx@1
  int v4; // esi@2
  int v5; // esi@2
  int v6; // ecx@2
  int v7; // esi@3
  int v8; // edi@3
  int v9; // ebx@3
  int v10; // ecx@8
  unsigned __int16 *v11; // esi@10
  unsigned int *v12; // ecx@12
  int v13; // esi@12
  int v14; // [sp+0h] [bp-4h]@2

  result = a1;
  for ( i = a1->field_28; i; i = result->field_28 )
  {
    v4 = result->field_8 & result->field_2C;
    result->field_28 = i - 1;
    v5 = (result->field_C & HIWORD(result->field_30)) + (v4 >> result->field_10);
    v6 = *((char *)result->pTextureLOD + v5);
    v14 = *((char *)result->pTextureLOD + v5);
    if ( a2->field_20 )
    {
      v7 = HIWORD(a2->field_10);
      v8 = a2->field_C;
      v9 = v7;
      if ( v7 >= v8 )
        v9 = a2->field_C;
      if ( a2->field_8 - v9 <= 0 )
      {
        v10 = 0;
      }
      else
      {
        if ( v7 >= v8 )
          v7 = a2->field_C;
        v10 = a2->field_8 - v7;
      }
      v11 = (unsigned __int16 *)a2->field_24;
      v6 = v14 + (v10 << 8);
    }
    else
    {
      v11 = result->field_34_palette;
    }
    *result->pColorBuffer = v11[v6];
    v12 = result->pDepthBuffer;
    v13 = result->field_24;
    ++result->pColorBuffer;
    *v12 = v13;
    ++result->pDepthBuffer;
    a2->field_10 += a2->field_18;
    result->field_30 += result->field_4;
    result->field_2C += result->field_0;
  }
  --result->field_28;
  return result;
}

//----- (00485A24) --------------------------------------------------------
stru315 *__fastcall sr_sub_485A24(stru315 *a1, stru315 *a2)
{
  stru315 *result; // eax@1
  int i; // ecx@1
  int v4; // ecx@2
  int v5; // ecx@4
  int v6; // ecx@6
  int v7; // ecx@8
  int v8; // esi@10
  int v9; // ecx@10
  int v10; // esi@11
  int v11; // edi@11
  int v12; // ebx@11
  int v13; // ecx@16
  unsigned __int16 *v14; // esi@18
  unsigned int *v15; // ecx@20
  int v16; // esi@20
  int v17; // [sp+0h] [bp-4h]@10

  result = a1;
  for ( i = a1->field_28; i; i = result->field_28 )
  {
    result->field_28 = i - 1;
    v4 = result->field_18;
    if ( result->field_30 > v4 )
      result->field_30 = v4;
    v5 = result->field_20;
    if ( result->field_2C > v5 )
      result->field_2C = v5;
    v6 = result->field_14;
    if ( result->field_30 < v6 )
      result->field_30 = v6;
    v7 = result->field_1C;
    if ( result->field_2C < v7 )
      result->field_2C = v7;
    v8 = (result->field_C & HIWORD(result->field_30)) + ((result->field_2C & result->field_8) >> result->field_10);
    v9 = *((char *)result->pTextureLOD + v8);
    v17 = *((char *)result->pTextureLOD + v8);
    if ( a2->field_20 )
    {
      v10 = HIWORD(a2->field_10);
      v11 = a2->field_C;
      v12 = v10;
      if ( v10 >= v11 )
        v12 = a2->field_C;
      if ( a2->field_8 - v12 <= 0 )
      {
        v13 = 0;
      }
      else
      {
        if ( v10 >= v11 )
          v10 = a2->field_C;
        v13 = a2->field_8 - v10;
      }
      v14 = (unsigned __int16 *)a2->field_24;
      v9 = v17 + (v13 << 8);
    }
    else
    {
      v14 = result->field_34_palette;
    }
    *result->pColorBuffer = v14[v9];
    v15 = result->pDepthBuffer;
    v16 = result->field_24;
    ++result->pColorBuffer;
    *v15 = v16;
    ++result->pDepthBuffer;
    a2->field_10 += a2->field_18;
    result->field_30 += result->field_4;
    result->field_2C += result->field_0;
  }
  --result->field_28;
  return result;
}

//----- (00485AFF) --------------------------------------------------------
stru315 *__fastcall sr_sub_485AFF(stru315 *a1, stru316 *a2)
{
  stru315 *result; // eax@1
  int i; // ecx@1
  int v4; // esi@2
  int v5; // esi@2
  int v6; // ecx@2
  int v7; // esi@3
  int v8; // edi@3
  int v9; // ebx@3
  int v10; // ecx@8
  unsigned __int16 *v11; // esi@10
  unsigned int *v12; // ecx@12
  int v13; // esi@12
  int v14; // [sp+0h] [bp-4h]@2

  result = a1;
  for ( i = a1->field_28; i; i = result->field_28 )
  {
    v4 = result->field_8 & result->field_2C;
    result->field_28 = i - 1;
    v5 = (result->field_C & HIWORD(result->field_30)) + (v4 >> result->field_10);
    v6 = *((char *)result->pTextureLOD + v5);
    v14 = *((char *)result->pTextureLOD + v5);
    if ( a2->field_20 )
    {
      v7 = HIWORD(a2->field_14);
      v8 = a2->field_C;
      v9 = v7;
      if ( v7 >= v8 )
        v9 = a2->field_C;
      if ( a2->field_8 - v9 <= 0 )
      {
        v10 = 0;
      }
      else
      {
        if ( v7 >= v8 )
          v7 = a2->field_C;
        v10 = a2->field_8 - v7;
      }
      v11 = a2->field_24_palette;
      v6 = v14 + (v10 << 8);
    }
    else
    {
      v11 = result->field_34_palette;
    }
    *result->pColorBuffer = v11[v6];
    v12 = result->pDepthBuffer;
    v13 = result->field_24;
    --result->pColorBuffer;
    *v12 = v13;
    --result->pDepthBuffer;
    a2->field_14 -= a2->field_18;
    result->field_30 += result->field_4;
    result->field_2C += result->field_0;
  }
  --result->field_28;
  return result;
}

//----- (00485BAE) --------------------------------------------------------
stru315 *__fastcall sr_sub_485BAE(stru315 *a1, stru316 *a2)
{
  stru315 *result; // eax@1
  int i; // ecx@1
  int v4; // ecx@2
  int v5; // ecx@4
  int v6; // ecx@6
  int v7; // ecx@8
  int v8; // esi@10
  int v9; // ecx@10
  int v10; // esi@11
  int v11; // edi@11
  int v12; // ebx@11
  int v13; // ecx@16
  unsigned __int16 *v14; // esi@18
  unsigned int *v15; // ecx@20
  int v16; // esi@20
  int v17; // [sp+0h] [bp-4h]@10

  result = a1;
  for ( i = a1->field_28; i; i = result->field_28 )
  {
    result->field_28 = i - 1;
    v4 = result->field_18;
    if ( result->field_30 > v4 )
      result->field_30 = v4;
    v5 = result->field_20;
    if ( result->field_2C > v5 )
      result->field_2C = v5;
    v6 = result->field_14;
    if ( result->field_30 < v6 )
      result->field_30 = v6;
    v7 = result->field_1C;
    if ( result->field_2C < v7 )
      result->field_2C = v7;
    v8 = (result->field_C & HIWORD(result->field_30)) + ((result->field_2C & result->field_8) >> result->field_10);
    v9 = *((char *)result->pTextureLOD + v8);
    v17 = *((char *)result->pTextureLOD + v8);
    if ( a2->field_20 )
    {
      v10 = HIWORD(a2->field_14);
      v11 = a2->field_C;
      v12 = v10;
      if ( v10 >= v11 )
        v12 = a2->field_C;
      if ( a2->field_8 - v12 <= 0 )
      {
        v13 = 0;
      }
      else
      {
        if ( v10 >= v11 )
          v10 = a2->field_C;
        v13 = a2->field_8 - v10;
      }
      v14 = a2->field_24_palette;
      v9 = v17 + (v13 << 8);
    }
    else
    {
      v14 = result->field_34_palette;
    }
    *result->pColorBuffer = v14[v9];
    v15 = result->pDepthBuffer;
    v16 = result->field_24;
    --result->pColorBuffer;
    *v15 = v16;
    --result->pDepthBuffer;
    a2->field_14 -= a2->field_18;
    result->field_30 += result->field_4;
    result->field_2C += result->field_0;
  }
  --result->field_28;
  return result;
}

//----- (00485C89) --------------------------------------------------------
stru315 *__fastcall sr_sub_485C89(stru315 *a1, stru316 *a2)
{
  stru315 *result; // eax@1
  int i; // ecx@1
  int v4; // esi@2
  int v5; // esi@2
  int v6; // ecx@2
  int v7; // esi@4
  int v8; // edi@4
  int v9; // ecx@9
  unsigned __int16 *v10; // esi@11
  unsigned int *v11; // ecx@14
  int v12; // esi@14
  int v13; // [sp+0h] [bp-4h]@2

  result = a1;
  for ( i = a1->field_28; i; i = result->field_28 )
  {
    v4 = result->field_8 & result->field_2C;
    result->field_28 = i - 1;
    v5 = (result->field_C & HIWORD(result->field_30)) + (v4 >> result->field_10);
    v6 = *((char *)result->pTextureLOD + v5);
    v13 = *((char *)result->pTextureLOD + v5);
    if ( *((char *)result->pTextureLOD + v5) )
    {
      if ( a2->field_20 )
      {
        v7 = HIWORD(a2->field_10);
        v8 = v7;
        if ( v7 >= a2->field_C )
          v8 = a2->field_C;
        if ( a2->field_8 - v8 <= 0 )
        {
          v9 = 0;
        }
        else
        {
          if ( v7 >= a2->field_C )
            v7 = a2->field_C;
          v9 = a2->field_8 - v7;
        }
        v10 = a2->field_24_palette;
        v6 = v13 + (v9 << 8);
      }
      else
      {
        v10 = result->field_34_palette;
      }
      *result->pColorBuffer = v10[v6];
    }
    v11 = result->pDepthBuffer;
    v12 = result->field_24;
    ++result->pColorBuffer;
    *v11 = v12;
    ++result->pDepthBuffer;
    a2->field_10 += a2->field_18;
    result->field_30 += result->field_4;
    result->field_2C += result->field_0;
  }
  --result->field_28;
  return result;
}

//----- (00485D3E) --------------------------------------------------------
stru315 *__fastcall sr_sub_485D3E(stru315 *a1, stru316 *a2)
{
  stru315 *result; // eax@1
  int i; // ecx@1
  int v4; // ecx@2
  int v5; // ecx@4
  int v6; // ecx@6
  int v7; // ecx@8
  int v8; // esi@10
  int v9; // ecx@10
  int v10; // esi@12
  int v11; // edi@12
  int v12; // ecx@17
  unsigned __int16 *v13; // esi@19
  unsigned int *v14; // ecx@22
  int v15; // esi@22
  int v16; // [sp+0h] [bp-4h]@10

  result = a1;
  for ( i = a1->field_28; i; i = result->field_28 )
  {
    result->field_28 = i - 1;
    v4 = result->field_18;
    if ( result->field_30 > v4 )
      result->field_30 = v4;
    v5 = result->field_20;
    if ( result->field_2C > v5 )
      result->field_2C = v5;
    v6 = result->field_14;
    if ( result->field_30 < v6 )
      result->field_30 = v6;
    v7 = result->field_1C;
    if ( result->field_2C < v7 )
      result->field_2C = v7;
    v8 = (result->field_C & HIWORD(result->field_30)) + ((result->field_2C & result->field_8) >> result->field_10);
    v9 = *((char *)result->pTextureLOD + v8);
    v16 = *((char *)result->pTextureLOD + v8);
    if ( *((char *)result->pTextureLOD + v8) )
    {
      if ( a2->field_20 )
      {
        v10 = HIWORD(a2->field_10);
        v11 = v10;
        if ( v10 >= a2->field_C )
          v11 = a2->field_C;
        if ( a2->field_8 - v11 <= 0 )
        {
          v12 = 0;
        }
        else
        {
          if ( v10 >= a2->field_C )
            v10 = a2->field_C;
          v12 = a2->field_8 - v10;
        }
        v13 = a2->field_24_palette;
        v9 = v16 + (v12 << 8);
      }
      else
      {
        v13 = result->field_34_palette;
      }
      *result->pColorBuffer = v13[v9];
    }
    v14 = result->pDepthBuffer;
    v15 = result->field_24;
    ++result->pColorBuffer;
    *v14 = v15;
    ++result->pDepthBuffer;
    a2->field_10 += a2->field_18;
    result->field_30 += result->field_4;
    result->field_2C += result->field_0;
  }
  --result->field_28;
  return result;
}

//----- (00485E1F) --------------------------------------------------------
void *__fastcall sr_sub_485E1F(stru316 *a1, Span *a2, int a3, stru148 *a4, int a5, unsigned __int8 a6, char a7)
{
  stru316 *v7; // esi@1
  signed int *v8; // edi@1
  signed int *v9; // ebx@1
  char v10; // zf@1
  int v11; // eax@1
  Span *v12; // ecx@3
  double v13; // ST24_8@3
  double v14; // ST24_8@3
  int v15; // eax@3
  signed int v16; // ST14_4@4
  char v17; // dl@4
  signed int v18; // ST10_4@4
  void *v19; // eax@4
  signed int v20; // ST14_4@5
  char v21; // dl@5
  int v22; // ST10_4@5
  signed int v23; // ST14_4@6
  char v24; // dl@6
  Span *v26; // [sp+10h] [bp-8h]@1
  char v27; // [sp+16h] [bp-2h]@1
  char v28; // [sp+17h] [bp-1h]@1
  float v29; // [sp+30h] [bp+18h]@3
  float v30; // [sp+30h] [bp+18h]@3

  v7 = a1;
  v26 = a2;
  v8 = &a1->field_C;
  v9 = &a1->field_8;
  v10 = a1->field_0 == 0;
  v27 = a1->field_4 != 0;
  v28 = !v10;
  sr_sub_47BEB1(a3, a4, a5, 0, &a1->field_8, &a1->field_C, (int)&v27, (int)&v28);
  v7->field_24_palette = (unsigned __int16 *)sr_sub_47C28C_get_palette(a4, v28, *v9, *v8);
  v11 = a4->field_108;
  v7->field_20 = v11;
  if ( v11 )
  {
    if ( a7 )
    {
      v12 = v26;
      v29 = v26->field_10 * 31.0;
      v13 = v29 + 6.7553994e15;
      v7->field_10 = LODWORD(v13) << 16;
      v30 = v12->field_14 * 31.0;
      v14 = v30 + 6.7553994e15;
      v15 = v7->field_10;
      v7->field_14 = LODWORD(v14) << 16;
      v7->field_18 = -((v15 - (LODWORD(v14) << 16)) / v12->field_C);
    }
    v16 = *v8;
    v17 = v28;
    v18 = *v9;
    v7->field_1C = a6;
    v19 = sr_sub_47C28C_get_palette(a4, v17, v18, v16);
  }
  else
  {
    v20 = *v8;
    v21 = v28;
    v7->field_10 = 0;
    v7->field_14 = 0;
    v22 = *v9;
    v7->field_18 = 0;
    v7->field_1C = 0;
    v19 = sr_sub_47C1CA(a4, v21, v22, v20);
  }
  v23 = *v8;
  v24 = v28;
  v7->field_24_palette = (unsigned __int16 *)v19;
  return sr_sub_47C1CA(a4, v24, *v9, v23);
}

//----- (00485F53) --------------------------------------------------------
void __thiscall sub_485F53(Vec2_int_ *v)
{
  ++v->y;
  if ( v->y > 1000 )
    v->y = 0;
}

//----- (00485F64) --------------------------------------------------------
void OutdoorCamera::_485F64()
{
  int v1; // eax@1
  int v2; // eax@2
  signed __int64 v3; // qtt@4
  int v4; // eax@4

  this->uCameraFovInDegrees = 75;
  v1 = stru_5C6E00->uPiMask & 0xD5;
  if ( v1 >= (signed int)stru_5C6E00->uIntegerHalfPi )
    v2 = -stru_5C6E00->pTanTable[stru_5C6E00->uIntegerPi - v1];
  else
    v2 = stru_5C6E00->pTanTable[v1];
  LODWORD(v3) = (viewparams->uSomeZ - viewparams->uSomeX) << 31;
  HIDWORD(v3) = (viewparams->uSomeZ - viewparams->uSomeX) << 15 >> 16;
  v4 = (signed int)(v3 / v2) >> 16;
  this->int_fov_rad = v4;
  this->field_4C = 360000;
  this->int_fov_rad_inv = 65536 / v4;
  this->field_50 = 115;
  unnamed_6BE060[1] = 1;
  RotationToInts();
}

//----- (0048600E) --------------------------------------------------------
void OutdoorCamera::RotationToInts()
{
  camera_rotation_y_int_sine   = stru_5C6E00->Sin(pIndoorCamera->sRotationY);
  camera_rotation_y_int_cosine = stru_5C6E00->Cos(pIndoorCamera->sRotationY);
  camera_rotation_x_int_sine   = stru_5C6E00->Sin(pIndoorCamera->sRotationX);
  camera_rotation_x_int_cosine = stru_5C6E00->Cos(pIndoorCamera->sRotationX);
}

//----- (0048607B) --------------------------------------------------------
void stru148::_48607B(stru149 *a2)
{
  this->pTexture = 0;
  this->ptr_38 = a2;
}

//----- (00486089) --------------------------------------------------------
void stru148::_486089_normalize_v_18()
{
  stru148 *v1; // esi@1
  double v2; // st7@1
  double v3; // st6@1
  float v4; // ST18_4@2
  double v5; // st5@1
  float v6; // ST14_4@2
  double v7; // st7@1
  float v8; // ST24_4@2
  float v9; // ST20_4@2
  double v10; // ST0C_8@2
  float v11; // ST18_4@2
  double v12; // ST0C_8@2
  float v13; // ST14_4@2
  double v14; // ST0C_8@2
  float v15; // [sp+20h] [bp-8h]@1

  v1 = this;
  v2 = (double)this->v_18.x;
  v15 = v2;
  v3 = (double)this->v_18.y;
  v5 = (double)this->v_18.z;
  v7 = sqrt(v5 * v5 + v3 * v3 + v2 * v2);
  if ( v7 == 0.0 )
  {
    v1->v_18.x = 0;
    v1->v_18.y = 0;
    v1->v_18.z = 65536;
  }
  else
  {
    v8 = 1.0 / v7;
    v9 = v8 * v15 * 65536.0;
    v10 = v9 + 6.7553994e15;
    v1->v_18.x = LODWORD(v10);
    v4 = v3;
    v11 = v8 * v4 * 65536.0;
    v12 = v11 + 6.7553994e15;
    v1->v_18.y = LODWORD(v12);
    v6 = v5;
    v13 = v8 * v6 * 65536.0;
    v14 = v13 + 6.7553994e15;
    v1->v_18.z = LODWORD(v14);
  }
}

//----- (0048616B) --------------------------------------------------------
int stru149::_48616B(int a2, int a3, int a4, int a5, int a6, int a7)
{
  int v7; // ebx@1
  int v8; // esi@1
  int v9; // edi@1
  int v10; // eax@1
  int v11; // edx@1
  int v12; // esi@2
  int v13; // eax@2
  int v14; // ST10_4@3
  int v15; // esi@3
  int v16; // eax@5
  int v17; // ST0C_4@6
  int v18; // eax@8
  int v19; // ST0C_4@9
  int v20; // eax@10
  int v21; // edx@10
  int v22; // eax@10
  int result; // eax@10
  int v24; // [sp+14h] [bp-14h]@1
  int v25; // [sp+18h] [bp-10h]@1
  int v26; // [sp+1Ch] [bp-Ch]@1
  int v27; // [sp+24h] [bp-4h]@1
  int v28; // [sp+30h] [bp+8h]@10
  int v29; // [sp+3Ch] [bp+14h]@10

  v25 = pOutdoorCamera->camera_rotation_x_int_cosine;
  v7 = pOutdoorCamera->camera_rotation_y_int_sine;
  v27 = pOutdoorCamera->camera_rotation_x_int_sine;
  v8 = -pIndoorCamera->pos.y;
  v9 = pOutdoorCamera->camera_rotation_y_int_cosine;
  v26 = -pIndoorCamera->pos.z;
  v24 = -pIndoorCamera->pos.x;
  v10 = pOutdoorCamera->camera_rotation_y_int_cosine * -pIndoorCamera->pos.x;
  v11 = v10 + pOutdoorCamera->camera_rotation_y_int_sine * -pIndoorCamera->pos.y;
  if ( pIndoorCamera->sRotationX )
  {
    v14 = v10 + pOutdoorCamera->camera_rotation_y_int_sine * -pIndoorCamera->pos.y;
    v15 = pOutdoorCamera->camera_rotation_y_int_cosine * v8 - pOutdoorCamera->camera_rotation_y_int_sine * v24;
    this->field_0_party_dir_x = ((unsigned __int64)(v11 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_cosine) >> 16)
                  + ((unsigned __int64)(-65536
                                      * pIndoorCamera->pos.z
                                      * (signed __int64)pOutdoorCamera->camera_rotation_x_int_sine) >> 16);
    this->field_4_party_dir_y = v15;
    v12 = v25;
    v13 = ((unsigned __int64)((v26 << 16) * (signed __int64)v25) >> 16)
        - ((unsigned __int64)(v14 * (signed __int64)v27) >> 16);
  }
  else
  {
    this->field_4_party_dir_y = pOutdoorCamera->camera_rotation_y_int_cosine * v8 - pOutdoorCamera->camera_rotation_y_int_sine * v24;
    v12 = v25;
    this->field_0_party_dir_x = v11;
    v13 = v26 << 16;
  }
  this->field_8 = v13;
  if ( pIndoorCamera->sRotationX )
  {
    v17 = ((unsigned __int64)(a2 * (signed __int64)v9) >> 16) + ((unsigned __int64)(a3 * (signed __int64)v7) >> 16);
    this->field_C = ((unsigned __int64)(v17 * (signed __int64)v12) >> 16)
                  + ((unsigned __int64)(a4 * (signed __int64)v27) >> 16);
    this->field_10 = ((unsigned __int64)(a3 * (signed __int64)v9) >> 16)
                   - ((unsigned __int64)(a2 * (signed __int64)v7) >> 16);
    v16 = ((unsigned __int64)(a4 * (signed __int64)v12) >> 16) - ((unsigned __int64)(v17 * (signed __int64)v27) >> 16);
  }
  else
  {
    this->field_C = ((unsigned __int64)(a2 * (signed __int64)v9) >> 16)
                  + ((unsigned __int64)(a3 * (signed __int64)v7) >> 16);
    this->field_10 = ((unsigned __int64)(a3 * (signed __int64)v9) >> 16)
                   - ((unsigned __int64)(a2 * (signed __int64)v7) >> 16);
    v16 = a4;
  }
  this->field_14 = v16;
  if ( pIndoorCamera->sRotationX )
  {
    v19 = ((unsigned __int64)(a5 * (signed __int64)v9) >> 16) + ((unsigned __int64)(a6 * (signed __int64)v7) >> 16);
    this->field_18 = ((unsigned __int64)(v19 * (signed __int64)v12) >> 16)
                   + ((unsigned __int64)(a7 * (signed __int64)v27) >> 16);
    this->field_1C = ((unsigned __int64)(a6 * (signed __int64)v9) >> 16)
                   - ((unsigned __int64)(a5 * (signed __int64)v7) >> 16);
    v18 = ((unsigned __int64)(a7 * (signed __int64)v12) >> 16) - ((unsigned __int64)(v19 * (signed __int64)v27) >> 16);
  }
  else
  {
    this->field_18 = ((unsigned __int64)(a5 * (signed __int64)v9) >> 16)
                   + ((unsigned __int64)(a6 * (signed __int64)v7) >> 16);
    this->field_1C = ((unsigned __int64)(a6 * (signed __int64)v9) >> 16)
                   - ((unsigned __int64)(a5 * (signed __int64)v7) >> 16);
    v18 = a7;
  }
  this->field_18 = -this->field_18;
  this->field_1C = -this->field_1C;
  this->field_20 = v18;
  v20 = this->field_C;
  this->field_20 = -this->field_20;
  v21 = ((unsigned __int64)(v20 * (signed __int64)this->field_0_party_dir_x) >> 16)
      + ((unsigned __int64)(this->field_10 * (signed __int64)this->field_4_party_dir_y) >> 16)
      + ((unsigned __int64)(this->field_14 * (signed __int64)this->field_8) >> 16);
  v28 = this->field_18;
  v22 = this->field_0_party_dir_x;
  this->field_24 = v21;
  v29 = (unsigned __int64)(v28 * (signed __int64)v22) >> 16;
  result = (unsigned __int64)(this->field_1C * (signed __int64)this->field_4_party_dir_y) >> 16;
  this->field_28 = v29 + result + ((unsigned __int64)(this->field_20 * (signed __int64)this->field_8) >> 16);
  return result;
}

//----- (0048653D) --------------------------------------------------------
int stru149::_48653D(int a2, int a3, int a4, int a5, int a6, int a7)
{
  stru149 *v7; // esi@1
  int v8; // edi@1
  int v9; // eax@1
  //int v10; // edx@1
  //int v11; // ecx@1
  int v12; // eax@1
  int v13; // ebx@2
  int v14; // ecx@2
  int v15; // eax@2
  int v16; // ST14_4@3
  int v17; // ST10_4@3
  int v18; // eax@5
  int v19; // ST10_4@6
  int v20; // eax@8
  int v21; // ST10_4@9
  int v22; // eax@10
  int v23; // ecx@10
  int v24; // eax@10
  int result; // eax@10
  //int v26; // [sp+14h] [bp-14h]@1
  int v27; // [sp+18h] [bp-10h]@1
  int v28; // [sp+1Ch] [bp-Ch]@1
  int v29; // [sp+24h] [bp-4h]@1
  int v30; // [sp+30h] [bp+8h]@10
  int v31; // [sp+3Ch] [bp+14h]@10

  v7 = this;
  v8 = stru_5C6E00->Cos(pBLVRenderParams->sPartyRotY);
  v29 = stru_5C6E00->Sin(pBLVRenderParams->sPartyRotY);
  v28 = stru_5C6E00->Cos(pBLVRenderParams->sPartyRotX);
  v9 = stru_5C6E00->Sin(pBLVRenderParams->sPartyRotX);
  //v11 = -pBLVRenderParams->vPartyPos.y;
  //v26 = -pBLVRenderParams->vPartyPos.x;
  v27 = v9;
  v12 = -pBLVRenderParams->vPartyPos.z;
  if ( pBLVRenderParams->sPartyRotX )
  {
    v16 = v8 * -pBLVRenderParams->vPartyPos.x + v29 * -pBLVRenderParams->vPartyPos.y;
    v13 = v28;
    v17 = -65536 * pBLVRenderParams->vPartyPos.z;
    v7->field_0_party_dir_x = ((unsigned __int64)(v16 * (signed __int64)v28) >> 16)
                + ((unsigned __int64)(-65536 * pBLVRenderParams->vPartyPos.z * (signed __int64)v27) >> 16);
    v7->field_4_party_dir_y = v8 * -pBLVRenderParams->vPartyPos.y - v29 * -pBLVRenderParams->vPartyPos.x;
    v14 = v27;
    v15 = ((unsigned __int64)(v17 * (signed __int64)v28) >> 16) - ((unsigned __int64)(v16 * (signed __int64)v27) >> 16);
  }
  else
  {
    v7->field_0_party_dir_x = v8 * -pBLVRenderParams->vPartyPos.x + v29 * -pBLVRenderParams->vPartyPos.y;
    v13 = v28;
    v7->field_4_party_dir_y = v8 * -pBLVRenderParams->vPartyPos.y - v29 * -pBLVRenderParams->vPartyPos.x;
    v14 = v27;
    v15 = v12 << 16;
  }
  v7->field_8 = v15;
  if ( pBLVRenderParams->sPartyRotX )
  {
    v19 = ((unsigned __int64)(a2 * (signed __int64)v8) >> 16) + ((unsigned __int64)(a3 * (signed __int64)v29) >> 16);
    v7->field_C = ((unsigned __int64)(v19 * (signed __int64)v13) >> 16)
                + ((unsigned __int64)(a4 * (signed __int64)v14) >> 16);
    v7->field_10 = ((unsigned __int64)(a3 * (signed __int64)v8) >> 16)
                 - ((unsigned __int64)(a2 * (signed __int64)v29) >> 16);
    v18 = ((unsigned __int64)(a4 * (signed __int64)v13) >> 16) - ((unsigned __int64)(v19 * (signed __int64)v14) >> 16);
  }
  else
  {
    v7->field_C = ((unsigned __int64)(a2 * (signed __int64)v8) >> 16)
                + ((unsigned __int64)(a3 * (signed __int64)v29) >> 16);
    v7->field_10 = ((unsigned __int64)(a3 * (signed __int64)v8) >> 16)
                 - ((unsigned __int64)(a2 * (signed __int64)v29) >> 16);
    v18 = a4;
  }
  v7->field_14 = v18;
  if ( pBLVRenderParams->sPartyRotX )
  {
    v21 = ((unsigned __int64)(a5 * (signed __int64)v8) >> 16) + ((unsigned __int64)(a6 * (signed __int64)v29) >> 16);
    v7->field_18 = ((unsigned __int64)(v21 * (signed __int64)v13) >> 16)
                 + ((unsigned __int64)(a7 * (signed __int64)v14) >> 16);
    v7->field_1C = ((unsigned __int64)(a6 * (signed __int64)v8) >> 16)
                 - ((unsigned __int64)(a5 * (signed __int64)v29) >> 16);
    v20 = ((unsigned __int64)(a7 * (signed __int64)v13) >> 16) - ((unsigned __int64)(v21 * (signed __int64)v14) >> 16);
  }
  else
  {
    v7->field_18 = ((unsigned __int64)(a5 * (signed __int64)v8) >> 16)
                 + ((unsigned __int64)(a6 * (signed __int64)v29) >> 16);
    v7->field_1C = ((unsigned __int64)(a6 * (signed __int64)v8) >> 16)
                 - ((unsigned __int64)(a5 * (signed __int64)v29) >> 16);
    v20 = a7;
  }
  v7->field_18 = -v7->field_18;
  v7->field_1C = -v7->field_1C;
  v7->field_20 = v20;
  v22 = v7->field_C;
  v7->field_20 = -v7->field_20;
  v23 = ((unsigned __int64)(v22 * (signed __int64)v7->field_0_party_dir_x) >> 16)
      + ((unsigned __int64)(v7->field_10 * (signed __int64)v7->field_4_party_dir_y) >> 16)
      + ((unsigned __int64)(v7->field_14 * (signed __int64)v7->field_8) >> 16);
  v30 = v7->field_18;
  v24 = v7->field_0_party_dir_x;
  v7->field_24 = v23;
  v31 = (unsigned __int64)(v30 * (signed __int64)v24) >> 16;
  result = (unsigned __int64)(v7->field_1C * (signed __int64)v7->field_4_party_dir_y) >> 16;
  v7->field_28 = v31 + result + ((unsigned __int64)(v7->field_20 * (signed __int64)v7->field_8) >> 16);
  return result;
}

//----- (0048694B) --------------------------------------------------------
int stru149::_48694B()
{
  int v1; // eax@1
  int v2; // ST04_4@1
  int v3; // ST00_4@1
  int v4; // eax@1
  int v5; // ST0C_4@1
  int result; // eax@1

  v1 = this->field_C;
  this->field_18 = -this->field_18;
  this->field_1C = -this->field_1C;
  this->field_20 = -this->field_20;
  v2 = (unsigned __int64)(v1 * (signed __int64)this->field_0_party_dir_x) >> 16;
  v3 = this->field_18;
  v4 = this->field_0_party_dir_x;
  this->field_24 = v2
                 + ((unsigned __int64)(this->field_10 * (signed __int64)this->field_4_party_dir_y) >> 16)
                 + ((unsigned __int64)(this->field_14 * (signed __int64)this->field_8) >> 16);
  v5 = (unsigned __int64)(v3 * (signed __int64)v4) >> 16;
  result = (unsigned __int64)(this->field_1C * (signed __int64)this->field_4_party_dir_y) >> 16;
  this->field_28 = v5 + result + ((unsigned __int64)(this->field_20 * (signed __int64)this->field_8) >> 16);
  return result;
}

//----- (00486A28) --------------------------------------------------------
void OutdoorCamera::AllocSoftwareDrawBuffers()
{
  if ( !this || !pSpans )
  {
    ReleaseSoftwareDrawBuffers();
    pSpans = (Span *)pAllocator->AllocNamedChunk(pSpans, 0x493E0u, "SPANS");
    pEdges = (Edge *)pAllocator->AllocNamedChunk(pEdges, 0x4C2C0u, "EDGES");
    pSurfs = (Surf *)pAllocator->AllocNamedChunk(pSurfs, 0x11940u, "SURFS");
    pNewEdges = (Edge *)pAllocator->AllocNamedChunk(pNewEdges, 0x6180u, "NEWEDGES");
    memset(pSpans, 0, 0x493E0u);
    memset(pEdges, 0, 0x4C2C0u);
    memset(pSurfs, 0, 0x11940u);
    memset(pNewEdges, 0, 0x6180u);
  }
}

//----- (00486AFC) --------------------------------------------------------
void OutdoorCamera::ReleaseSoftwareDrawBuffers()
{
  pAllocator->FreeChunk(pSpans);
  pAllocator->FreeChunk(pEdges);
  pAllocator->FreeChunk(pSurfs);
  pAllocator->FreeChunk(pNewEdges);
  pSpans = 0;
  pEdges = 0;
  pSurfs = 0;
  pNewEdges = 0;
}

//----- (00486B4E) --------------------------------------------------------
char __fastcall sr_sub_486B4E_push_outdoor_edges(RenderVertexSoft *a1, int *a2, int *a3, stru148 *a4)//maybe DrawPolygonSW
{
  stru148 *v4; // esi@1
  RenderVertexSoft *v5; // edi@1
  char v6; // zf@1
  unsigned int v7; // eax@3
  int v8; // ebx@3
  int *v9; // ecx@7
  int v10; // ebx@8
  int v11; // eax@10
  double v12; // st7@14
  int *v13; // edx@14
  double v14; // st6@14
  double v15; // st7@16
  int v16; // edi@16
  double v17; // st7@16
  double v18; // st7@16
  int v19; // edi@18
  double v20; // st7@18
  double v21; // st7@18
  Edge *i; // edx@20
  double v23; // st7@28
  Edge *v24; // eax@28
  std::string v26; // [sp-18h] [bp-98h]@2
  const char *v27; // [sp-8h] [bp-88h]@2
  int v28; // [sp-4h] [bp-84h]@2
  double v29; // [sp+Ch] [bp-74h]@28
  double v30; // [sp+14h] [bp-6Ch]@28
  double v31; // [sp+1Ch] [bp-64h]@20
  double v32; // [sp+24h] [bp-5Ch]@16
  double v33; // [sp+2Ch] [bp-54h]@14
  unsigned int v34; // [sp+34h] [bp-4Ch]@2
  unsigned __int64 v35; // [sp+38h] [bp-48h]@28
  int v36; // [sp+40h] [bp-40h]@28
  int v37; // [sp+44h] [bp-3Ch]@20
  float v38; // [sp+48h] [bp-38h]@18
  int v39; // [sp+4Ch] [bp-34h]@16
  int v40; // [sp+50h] [bp-30h]@14
  int v41; // [sp+54h] [bp-2Ch]@3
  RenderVertexSoft *v42; // [sp+58h] [bp-28h]@1
  int v43; // [sp+5Ch] [bp-24h]@14
  int v44; // [sp+60h] [bp-20h]@6
  int v45; // [sp+64h] [bp-1Ch]@6
  unsigned int v46; // [sp+68h] [bp-18h]@7
  int *v47; // [sp+6Ch] [bp-14h]@1
  int v48; // [sp+70h] [bp-10h]@7
  float *v49; // [sp+74h] [bp-Ch]@7
  float v50; // [sp+78h] [bp-8h]@10
  float v51; // [sp+7Ch] [bp-4h]@14

  v4 = a4;
  v5 = a1;
  v47 = a2;
  v6 = (HIBYTE(a4->flags) & 0x40) == 0;
  v42 = a1;
  if ( !v6 )
  {
          MessageBoxW(nullptr, L"The Texture Frame Table is not a supported feature.", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Odspan.cpp:162", 0);
  }
  LOBYTE(v7) = v4->field_108;
  v8 = v4->uNumVertices;
  v4->field_108 = 0;
  BYTE3(a4) = v7;
  v41 = v8;
  if ( v8 > 0 )
  {
    if ( (signed int)pOutdoorCamera->uNumSurfs < 1999 )
    {
      v7 = pOutdoorCamera->uNumEdges;
      if ( (signed int)pOutdoorCamera->uNumEdges < 5979 )
      {
        v4->uEdgeList1Size = 0;
        v4->uEdgeList2Size = 0;
        v45 = -1;
        v34 = v7;
        v28 = v8;
        v27 = (const char *)v5;
        v44 = 10000;
        pGame->pLightmapBuilder->_45CB89(v5, v8);
        if ( v8 > 0 )
        {
          v9 = a3;
          v48 = 1;
          v49 = &v5->flt_2C;
          v46 = (char *)v47 - (char *)a3;
          do
          {
            v10 = v48;
            ++pOutdoorCamera->uNumEdges;
            if ( v48 >= v41 )
              v10 = 0;
            v11 = *v9;
            LODWORD(v50) = *v9;
            if ( SLODWORD(v50) > v45 )
              v45 = v11;
            if ( v11 < v44 )
              v44 = v11;
            v12 = (double)SLODWORD(v50);
            v13 = &a3[v10];
            v51 = v12;
            v14 = (double)*v13;
            v50 = v14;
            *(float *)&v40 = v14 - v12;
            v33 = *(float *)&v40 + 6.7553994e15;
            v43 = LODWORD(v33);
            if ( LODWORD(v33) )
            {
              if ( SLODWORD(v33) >= 0 )
              {
                v19 = (int)((char *)v9 + v46);
                ptr_80C978_Edges->field_8 = 1;
                LODWORD(v38) = (int)&v47[v10];
                v40 = *(unsigned int *)LODWORD(v38) - *(int *)v19;
                v6 = BYTE3(a4) == 0;
                v20 = (double)v40;
                v40 = *v13 - *v9;
                v21 = v20 / (double)v40;
                ptr_80C978_Edges->field_4 = v21;
                ptr_80C978_Edges->field_0 = (v51 - (double)*v9) * v21 + (double)*(signed int *)v19;
                if ( !v6 )
                {
                  ptr_80C978_Edges->field_1C = *v49;
                  ptr_80C978_Edges->field_20 = v42[v10].flt_2C;
                  ptr_80C978_Edges->field_24 = (double)*(signed int *)v19;
                  ptr_80C978_Edges->field_28 = (double)(signed int)*(unsigned int *)LODWORD(v38);
                  ptr_80C978_Edges->field_2C = (double)*v9;
                  ptr_80C978_Edges->field_30 = (double)*v13;
                  v4->pEdgeList1[v4->uEdgeList1Size++] = ptr_80C978_Edges;
                }
              }
              else
              {
                v32 = v51 + 6.7553994e15;
                v39 = LODWORD(v32);
                v51 = v50;
                v15 = (double)SLODWORD(v32);
                ptr_80C978_Edges->field_8 = 0;
                v16 = (int)&v47[v10];
                v50 = v15;
                v40 = *(int *)((char *)v9 + v46) - *(int *)v16;
                v6 = BYTE3(a4) == 0;
                v17 = (double)v40;
                v40 = *v9 - *v13;
                v18 = v17 / (double)v40;
                ptr_80C978_Edges->field_4 = v18;
                ptr_80C978_Edges->field_0 = (v51 - (double)*v13) * v18 + (double)*(signed int *)v16;
                if ( !v6 )
                {
                  ptr_80C978_Edges->field_1C = v42[v10].flt_2C;
                  ptr_80C978_Edges->field_20 = *v49;
                  ptr_80C978_Edges->field_24 = (double)*(signed int *)v16;
                  ptr_80C978_Edges->field_28 = (double)*(int *)((char *)v9 + v46);
                  ptr_80C978_Edges->field_2C = (double)*v13;
                  ptr_80C978_Edges->field_30 = (double)*v9;
                  v4->pEdgeList2[v4->uEdgeList2Size++] = ptr_80C978_Edges;
                }
              }
              v31 = v51 + 6.7553994e15;
              v37 = LODWORD(v31);
              for ( i = &pNewEdges[LODWORD(v31)]; i->pNext->field_0 < (double)ptr_80C978_Edges->field_0; i = i->pNext )
                ;
              if ( i->field_0 != ptr_80C978_Edges->field_0 || i->field_8 || ptr_80C978_Edges->field_8 != 1 )
              {
                ptr_80C978_Edges->pNext = i->pNext;
                i->pNext = ptr_80C978_Edges;
              }
              else
              {
                ptr_80C978_Edges->pNext = i;
                i->pPrev->pNext = ptr_80C978_Edges;
              }
              v23 = v50 - 1.0;
              *(float *)&v40 = v23;
              v38 = v23;
              v30 = v38 + 6.7553994e15;
              v36 = LODWORD(v30);
              ptr_80C978_Edges->ptr_18 = ptr_80CA10[LODWORD(v30)];
              v29 = *(float *)&v40 + 6.7553994e15;
              v35 = __PAIR__(v40, LODWORD(v29));
              v24 = ptr_80C978_Edges;
              ptr_80CA10[LODWORD(v29)] = ptr_80C978_Edges;
              v24->pSurf = ptr_80C97C_Surfs;
              if ( ptr_80C978_Edges < &pEdges[5999] )
                ++ptr_80C978_Edges;
            }
            ++v48;
            v49 += 12;
            ++v9;
          }
          while ( v48 - 1 < v41 );
        }
        LOBYTE(v7) = v34;
        if ( pOutdoorCamera->uNumEdges != v34 )
        {
          v4->ptr_48 = 0;
          ptr_80C97C_Surfs->field_22 = 0;
          ptr_80C97C_Surfs->pParent = v4;
          ptr_80C97C_Surfs->field_4 = v4->field_4;
          ptr_80C97C_Surfs->field_8 = v4->field_8;
          ptr_80C97C_Surfs->field_0 = v4->field_0;
          ptr_80C97C_Surfs->field_C = v4->field_C;
          ptr_80C97C_Surfs->field_10 = v4->field_10;
          LOBYTE(v7) = (char)pSurfs + 28;
          if ( ptr_80C97C_Surfs < &pSurfs[1999] )
          {
            ++ptr_80C97C_Surfs;
            ++pOutdoorCamera->uNumSurfs;
          }
          if ( BYTE3(a4) )
            v4->field_108 = 1;
        }
      }
    }
  }
  return v7;
}

//----- (0043F953) --------------------------------------------------------
void PrepareBspRenderList_BLV()
{
  pBspRenderer->num_faces = 0;

  if (pBLVRenderParams->uPartySectorID)
  {
    pBspRenderer->nodes[0].uSectorID = pBLVRenderParams->uPartySectorID;
    pBspRenderer->nodes[0].uViewportW = pBLVRenderParams->uViewportW;
    pBspRenderer->nodes[0].uViewportZ = pBLVRenderParams->uViewportZ;
    pBspRenderer->nodes[0].uViewportY = pBLVRenderParams->uViewportY;
    pBspRenderer->nodes[0].uViewportX = pBLVRenderParams->uViewportX;
    pBspRenderer->nodes[0].field_C._43F9E1(pBLVRenderParams->uViewportX,
                                           pBLVRenderParams->uViewportY,
                                           pBLVRenderParams->uViewportZ,
                                           pBLVRenderParams->uViewportW);
    pBspRenderer->nodes[0].uFaceID = -1;
    pBspRenderer->nodes[0].viewing_portal_id = -1;
    pBspRenderer->num_nodes = 1;
    AddBspNodeToRenderList(0);
  }

  pBspRenderer->MakeVisibleSectorList();
}

//----- (0043F9E1) --------------------------------------------------------
void BspRenderer_stru2::_43F9E1(__int16 x, int y, __int16 z, int w)
{
  _viewport_space_y = y;
  _viewport_space_w = w;

  for (uint i = 0; i < 480; ++i)
  {
    if ( i < y || i > w )
    {
      array_18[i] = 640;
      array_3D8[i] = -1;
    }
    else
    {
      array_18[i] = x;
      array_3D8[i] = z;
    } 
  }
}

//----- (0043FA33) --------------------------------------------------------
void __fastcall PrepareDecorationsRenderList_BLV(unsigned int uDecorationID, unsigned int uSectorID)
{
  LevelDecoration *v2; // esi@1
  DecorationDesc *v3; // ebx@2
  __int16 v4; // ax@2
  double v5; // st7@3
  int v6; // eax@5
  int v7; // edx@5
  unsigned int v8; // edi@5
  int v9; // edi@5
  int v10; // eax@7
  SpriteFrame *v11; // eax@7
  SpriteFrame *v12; // esi@7
  int v13; // eax@7
  int v14; // ebx@16
  RenderBillboard *v15; // ecx@17
  char v16; // zf@18
  IndoorCameraD3D **v17; // eax@19
  double v18; // st7@19
  //float v19; // eax@19
  signed __int64 v20; // qtt@19
  signed __int64 v21; // qtt@20
  //int v22; // edx@21
  //int v23; // eax@21
  Particle_sw local_0; // [sp+Ch] [bp-A0h]@3
  //double v25; // [sp+74h] [bp-38h]@19
  //unsigned int v26; // [sp+7Ch] [bp-30h]@1
  int a2; // [sp+80h] [bp-2Ch]@5
  int a3; // [sp+84h] [bp-28h]@5
  int a1; // [sp+88h] [bp-24h]@5
  int v30; // [sp+8Ch] [bp-20h]@7
  //float v31; // [sp+90h] [bp-1Ch]@1
  int a5; // [sp+94h] [bp-18h]@17
  int z; // [sp+98h] [bp-14h]@15
  int a6; // [sp+9Ch] [bp-10h]@17
  int y; // [sp+A0h] [bp-Ch]@15
  int x; // [sp+A4h] [bp-8h]@15
  int v37; // [sp+A8h] [bp-4h]@5

  //v26 = uDecorationID;
  //LODWORD(v31) = uSectorID;
  v2 = &pLevelDecorations[uDecorationID];
  if (v2->field_2 & 0x20)
    return;

    v3 = &pDecorationList->pDecorations[v2->uDecorationDescID];
    v4 = v3->uFlags;
    if (v3->uFlags & DECORATION_EMITS_FIRE)
    {
      memset(&local_0, 0, 0x68u);               // fire,  like at the Pit's tavern
      v5 = (double)v2->vPosition.x;
      local_0.type = ParticleType_Bitmap | ParticleType_Rotating | ParticleType_8;
      local_0.uDiffuse = 0xFF3C1E;
      local_0.x = v5;
      local_0.y = (double)v2->vPosition.y;
      local_0.z = (double)v2->vPosition.z;
      local_0.flt_10 = 0.0;
      local_0.flt_14 = 0.0;
      local_0.flt_18 = 0.0;
      local_0.flt_28 = 1.0;
      local_0.timeToLive = (rand() & 0x80) + 128;
      local_0.uTextureID = pBitmaps_LOD->LoadTexture("effpar01");
      pGame->pParticleEngine->AddParticle(&local_0);
      return;
    }


      if (v4 & DECORATION_DONT_DRAW)
        return;

        v6 = v2->vPosition.x;
        v7 = v2->vPosition.z;
        a2 = v2->vPosition.y;
        a1 = v6;
        a3 = v7;
        v8 = v2->field_10_y_rot
           + ((signed int)stru_5C6E00->uIntegerPi >> 3)
           - stru_5C6E00->Atan2(v6 - pBLVRenderParams->vPartyPos.x, a2 - pBLVRenderParams->vPartyPos.y);
        v37 = pBLVRenderParams->field_0_timer_;
        v9 = ((signed int)(stru_5C6E00->uIntegerPi + v8) >> 8) & 7;
        if (pParty->bTurnBasedModeOn)
          v37 = pMiscTimer->uTotalGameTimeElapsed;
        v10 = abs(v2->vPosition.x + v2->vPosition.y);
        v11 = pSpriteFrameTable->GetFrame(v3->uSpriteID, v37 + v10);
        v30 = 0;
        v12 = v11;
        v13 = v11->uFlags;
        if ( v13 & 2 )
          v30 = 2;
        if ( v13 & 0x40000 )
          v30 |= 0x40u;
        if ( v13 & 0x20000 )
          LOBYTE(v30) = v30 | 0x80;
        if ( (256 << v9) & v13 )
          v30 |= 4u;
        if ( pGame->pIndoorCameraD3D->ApplyViewTransform_TrueIfStillVisible(a1, a2, a3, &x, &y, &z, 1) )
        {
          v14 = abs(x);
          if ( v14 >= abs(y) )
          {
            pGame->pIndoorCameraD3D->Project(x, y, z, &a5, &a6);

            v15 = &pBillboardRenderList[uNumBillboardsToDraw];
            assert(uNumBillboardsToDraw < 500);

              ++uNumBillboardsToDraw;
              ++uNumDecorationsDrawnThisFrame;
              v16 = pRenderer->pRenderD3D == 0;
              v15->uHwSpriteID = v12->pHwSpriteIDs[v9];
              v15->uPalette = v12->uPaletteIndex;
              v15->uIndoorSectorID = uSectorID;
              if ( v16 )
              {
                LODWORD(v21) = pBLVRenderParams->field_40 << 16;
                HIDWORD(v21) = pBLVRenderParams->field_40 >> 16;
                v37 = v21 / x;
                //LODWORD(v31) = v12->scale;
                v37 = v21 / x;
                v15->_screenspace_x_scaler_packedfloat = (unsigned __int64)(v12->scale * v21 / x) >> 16;
                v37 = (unsigned __int64)(v12->scale * (signed __int64)v37) >> 16;
              }
              else
              {
                v17 = &pGame->pIndoorCameraD3D;
                v15->fov_x = pGame->pIndoorCameraD3D->fov_x;
                v18 = (*v17)->fov_y;
                //v19 = v15->fov_x;
                v15->fov_y = v18;
                //v31 = v19;
                //v25 = v19 + 6.7553994e15;
                //v25 = floorf(v15->fov_x + 0.5f);
                LODWORD(v20) = 0;
                HIDWORD(v20) = floorf(v15->fov_x + 0.5f);
                v37 = v20 / x;
                //LODWORD(v31) = v12->scale;
                v37 = (unsigned __int64)(v12->scale * v20 / x) >> 16;
                v15->_screenspace_x_scaler_packedfloat = (unsigned __int64)(v12->scale * v20 / x) >> 16;
                //v31 = v15->fov_y;
                //v25 = v31 + 6.7553994e15;
                //v25 = floorf(v15->fov_y + 0.5f);
                LODWORD(v20) = 0;
                HIDWORD(v20) = floorf(v15->fov_y + 0.5f);
                v37 = v20 / x;
                v37 = (unsigned __int64)(v12->scale * v20 / x) >> 16;
              }
              //HIWORD(v22) = HIWORD(x);
              //LOWORD(v22) = 0;
              v15->_screenspace_y_scaler_packedfloat = v37;
              v15->field_1E = v30;
              v15->world_x = a1;
              v15->world_y = a2;
              v15->world_z = a3;
              v15->uScreenSpaceX = a5;
              v15->uScreenSpaceY = a6;
              //v23 = 8 * uDecorationID;
              //LOBYTE(v23) = PID(OBJECT_Decoration,uDecorationID);

              //v15->sZValue = v22 + v23;
              v15->actual_z = HIWORD(x);
              v15->object_pid = PID(OBJECT_Decoration,uDecorationID);

              v15->uTintColor = 0;
              v15->pSpriteFrame = v12;
          }
        }
}

//----- (0044028F) --------------------------------------------------------
void PrepareItemsRenderList_BLV()
{
  ObjectDesc *v1; // ebx@4
  __int16 v2; // ax@5
  RenderBillboard *v3; // esi@12
  SpriteFrame *v4; // eax@12
  SpriteFrame *v5; // ebx@12
  unsigned int v6; // eax@12
  int v7; // ecx@12
  int v8; // edx@12
  int v9; // ecx@12
  unsigned __int16 v10; // ax@12
  int *v11; // eax@20
  //char v12; // zf@26
  __int64 v18; // ST5C_4@27
  signed __int64 v19; // qtt@28
  int v20; // ST5C_4@28
  //int v21; // edx@29
  __int16 v22; // ax@29
  //int v23; // eax@29
  SpriteFrame *v24; // [sp+1Ch] [bp-40h]@12
  //__int16 a5; // [sp+28h] [bp-34h]@12
  int a6; // [sp+2Ch] [bp-30h]@12
  int a2; // [sp+30h] [bp-2Ch]@12
  int a1; // [sp+34h] [bp-28h]@12
  int v30; // [sp+38h] [bp-24h]@12
  int v31; // [sp+38h] [bp-24h]@27
  int a3; // [sp+40h] [bp-1Ch]@12
  signed __int16 v34; // [sp+44h] [bp-18h]@14
  int v35; // [sp+48h] [bp-14h]@25
  int v36; // [sp+4Ch] [bp-10h]@25
  signed int z; // [sp+50h] [bp-Ch]@24
  signed int y; // [sp+54h] [bp-8h]@24
  signed int x; // [sp+58h] [bp-4h]@24

  for (uint i = 0; i < uNumSpriteObjects; ++i)
  {
    auto p = pSpriteObjects + i;
    if (p->uObjectDescID)
    {
      v1 = &pObjectList->pObjects[p->uObjectDescID];
        if ( !(v1->uFlags & 1) )
         {
          if ( ((v2 = p->uType, v2 < 1000) || v2 >= 10000)
            && (v2 < 500 || v2 >= 600)
            && (v2 < 811 || v2 >= 815)
            || pGame->pStru6Instance->_4A81CA(p))
          {
            //a5 = p->uSectorID;
            a1 = p->vPosition.x;
            a2 = p->vPosition.y;
            a3 = p->vPosition.z;
            v3 = &pBillboardRenderList[uNumBillboardsToDraw];
            v4 = pSpriteFrameTable->GetFrame(v1->uSpriteID, p->uSpriteFrameID);
            v5 = v4;
            v24 = v4;
            v30 = v4->uFlags;
            a6 = v4->uGlowRadius * p->field_22_glow_radius_multiplier;
            v6 = stru_5C6E00->Atan2(p->vPosition.x - pBLVRenderParams->vPartyPos.x,
                                    p->vPosition.y - pBLVRenderParams->vPartyPos.y);
            LOWORD(v7) = p->uFacing;
            v8 = v30;
            v9 = ((signed int)(stru_5C6E00->uIntegerPi + ((signed int)stru_5C6E00->uIntegerPi >> 3) + v7 - v6) >> 8) & 7;
            v10 = v5->pHwSpriteIDs[v9];
            v3->uHwSpriteID = v10;
            if ( v30 & 0x20 )
            {
              v8 = v30;
              a3 -= (signed int)((unsigned __int64)(v5->scale * (signed __int64)pSprites_LOD->pSpriteHeaders[(signed __int16)v10].uHeight) >> 16) >> 1;
            }
            v34 = 0;
            if ( v8 & 2 )
              v34 = 2;
            if ( v8 & 0x40000 )
              v34 |= 0x40u;
            if ( v8 & 0x20000 )
              LOBYTE(v34) = v34 | 0x80;
            v11 = (int *)(256 << v9);
            if ( (256 << v9) & v8 )
              v34 |= 4u;
            if ( a6 )
            {
              LOBYTE(v11) = byte_4E94D3;
              pMobileLightsStack->AddLight(
                a1,
                a2,
                a3,
                p->uSectorID,
                a6,
                v1->uParticleTrailColorR,
                v1->uParticleTrailColorG,
                v1->uParticleTrailColorB,
                byte_4E94D3);
            }
            if ( pGame->pIndoorCameraD3D->ApplyViewTransform_TrueIfStillVisible(
                   a1,
                   a2,
                   a3,
                   &x,
                   &y,
                   &z,
                   1) )
            {
              pGame->pIndoorCameraD3D->Project(x, y, z, &v36, &v35);

              assert(uNumBillboardsToDraw < 500);
              //if ( (signed int)uNumBillboardsToDraw >= 500 )
              //  return;
              ++uNumBillboardsToDraw;
              ++uNumSpritesDrawnThisFrame;
              p->uAttributes |= 1u;
              //v12 = pRenderer->pRenderD3D == 0;
              v3->uPalette = v24->uPaletteIndex;
              v3->uIndoorSectorID = p->uSectorID;
              if ( pRenderer->pRenderD3D )
              {
                v3->fov_x = pGame->pIndoorCameraD3D->fov_x;
                v3->fov_y = pGame->pIndoorCameraD3D->fov_y;
                LODWORD(v18) = 0;
                HIDWORD(v18) = (int)floorf(v3->fov_x + 0.5f);
                v18 = v18 / x;
                v3->_screenspace_x_scaler_packedfloat = (unsigned __int64)(v24->scale * v18) >> 16;
                v31 = (unsigned __int64)(v24->scale * v18) >> 16;
              }
              else
              {
                LODWORD(v19) = pBLVRenderParams->field_40 << 16;
                HIDWORD(v19) = pBLVRenderParams->field_40 >> 16;
                v20 = v19 / x;
                v3->_screenspace_x_scaler_packedfloat = (unsigned __int64)(v24->scale * v19 / x) >> 16;
                v31 = (unsigned __int64)(v24->scale * (signed __int64)v20) >> 16;
              }
              //HIWORD(v21) = HIWORD(x);
              //LOWORD(v21) = 0;
              v3->_screenspace_y_scaler_packedfloat = v31;
              v3->field_1E = v34;
              v3->world_x = a1;
              v3->world_y = a2;
              v3->world_z = a3;
              v3->uScreenSpaceX = v36;
              v22 = v35;
              v3->uTintColor = 0;
              v3->uScreenSpaceY = v22;
              //v23 = 8 * i;
              //LOBYTE(v23) = PID(OBJECT_Item,i);
              v3->pSpriteFrame = v24;
              //v12 = (p->uAttributes & 0x20) == 0;
              //v3->sZValue = v21 + v23;
              v3->actual_z = HIWORD(x);
              v3->object_pid = PID(OBJECT_Item,i);
              if (p->uAttributes & 0x20)
              {
                if ( !pRenderer->pRenderD3D )
                  v3->sZValue = 0;
              }
            }
          }
        }
      }
  }
}

//----- (00440639) --------------------------------------------------------
void AddBspNodeToRenderList(unsigned int node_id)
{
  //int v1; // ebx@1
  signed int v2; // edi@1
  BLVSector *v3; // esi@1

  //v1 = sector_id;
  v2 = 0;
  v3 = &pIndoor->pSectors[pBspRenderer->nodes[node_id].uSectorID];
  if ( pRenderer->pRenderD3D )
  {
    for (uint i = 0; i < v3->uNumNonBSPFaces; ++i)
      //Log::Warning(L"Non-BSP face: %X", v3->pFaceIDs[v2]);
      pBspRenderer->AddFaceToRenderList_d3d(node_id, v3->pFaceIDs[i]);
  }
  else
  {
    if ( v3->uNumNonBSPFaces > 0 )
    {
      do
        pBspRenderer->AddFaceToRenderList_sw(node_id, v3->pFaceIDs[v2++]);
      while ( v2 < v3->uNumNonBSPFaces );
    }
  }
  if ( v3->field_0 & 0x10 )
    sub_4406BC(node_id, v3->uFirstBSPNode);
}

//----- (004406BC) --------------------------------------------------------
void __fastcall sub_4406BC(unsigned int node_id, unsigned int uFirstNode)
{
  BLVSector *v2; // esi@2
  BSPNode *v3; // edi@2
  BLVFace *v4; // eax@2
  int v5; // ecx@2
  __int16 v6; // ax@6
  int v7; // ebp@10
  int v8; // ebx@10
  __int16 v9; // di@18
  //int v10; // [sp+10h] [bp-Ch]@1
  bool v11; // [sp+14h] [bp-8h]@5
  BspRenderer_stru0 *v12; // [sp+18h] [bp-4h]@1

  //Log::Warning(L"sub_4406BC(%u, %u)", a1, uFirstNode);

  //v10 = a1;
  v12 = &pBspRenderer->nodes[node_id];
  while ( 1 )
  {
    v2 = &pIndoor->pSectors[v12->uSectorID];
    v3 = &pIndoor->pNodes[uFirstNode];
    v4 = &pIndoor->pFaces[v2->pFaceIDs[v3->uCoplanarOffset]];
    v5 = v4->pFacePlane_old.dist
       + pBLVRenderParams->vPartyPos.x * v4->pFacePlane_old.vNormal.x
       + pBLVRenderParams->vPartyPos.y * v4->pFacePlane_old.vNormal.y
       + pBLVRenderParams->vPartyPos.z * v4->pFacePlane_old.vNormal.z;
    if (v4->Portal() && v4->uSectorID != v12->uSectorID )
      v5 = -v5;
    v11 = v5 > 0;
    if ( v5 <= 0 )
      v6 = v3->uFront;
    else
      v6 = v3->uBack;
    if ( v6 != -1 )
      sub_4406BC(node_id, v6);
    v7 = v3->uCoplanarOffset;
    v8 = v7 + v3->uCoplanarSize;

    //Log::Warning(L"Node %u: %X to %X (%hX)", uFirstNode, v7, v8, v2->pFaceIDs[v7]);
    
    if ( pRenderer->pRenderD3D )
    {
      while ( v7 < v8 )
        pBspRenderer->AddFaceToRenderList_d3d(node_id, v2->pFaceIDs[v7++]);
    }
    else
    {
      while ( v7 < v8 )
        pBspRenderer->AddFaceToRenderList_sw(node_id, v2->pFaceIDs[v7++]);
    }
    v9 = v11 ? v3->uFront : v3->uBack;
    if ( v9 == -1 )
      break;
    uFirstNode = v9;
  }
}

//----- (00440DF5) --------------------------------------------------------
int stru167_wrap::Push(__int16 a2, __int16 a3, __int16 a4, int a5, __int16 bgr)
{
  int result; // eax@1

  pElements[uNumElements].field_6_rnd_value = a2;
  pElements[uNumElements].field_8_rnd_value = a3;
  pElements[uNumElements].field_A_rnd_value = a4;
  pElements[uNumElements].field_C_time_left = rand() % 64 + 256;
  pElements[uNumElements].field_E_time_to_live = pElements[uNumElements].field_C_time_left;
  result = 3 * uNumElements;
  pElements[uNumElements++].bgr16 = bgr;
  if (uNumElements >= 100 )
    uNumElements = 0;
   return result;
}

//----- (00440E91) --------------------------------------------------------
void stru167_wrap::_440E91(__int16 x, int y, int z, int a5, __int16 bgr)
{
  stru167_wrap *v6; // edi@1
  int i; // esi@1
  int v8; // ST08_4@2
  int v9; // ST04_4@2
  int v10; // eax@2

  v6 = this;
  for ( i = 0; i < rand() % 6 + 5; ++i )
  {
    v8 = z + rand() % 33;
    v9 = rand() % 33 + y - 16;
    v10 = rand();
    Push(v10 % 33 + x - 16, v9, v8, a5, bgr);
  }
}

//----- (00440F07) --------------------------------------------------------
void stru167_wrap::_440F07()
{
  for (uint i = 0; i < 100; ++i)
  {
    if (pElements[i].field_C_time_left > 0)
    {
      pElements[i].field_A_rnd_value += rand() % 5 + 4;
      pElements[i].field_6_rnd_value += rand() % 5 - 2;
      pElements[i].field_8_rnd_value += rand() % 5 - 2;
      pElements[i].field_C_time_left -= (short)pEventTimer->uTimeElapsed;
    }
  }
}

//----- (0044100D) --------------------------------------------------------
bool __cdecl sub_44100D()
{
  return pCurrentScreen == SCREEN_NPC_DIALOGUE || pCurrentScreen == SCREEN_CHARACTERS ||
         pCurrentScreen > SCREEN_LOADGAME && pCurrentScreen <= SCREEN_E ||
         pCurrentScreen > SCREEN_VIDEO && pCurrentScreen <= SCREEN_INPUT_BLV || pCurrentScreen == SCREEN_CASTING;
}
// 4E28F8: using guessed type int pCurrentScreen;

//----- (00441A4E) --------------------------------------------------------
__int16 __fastcall sub_441A4E(int a1)
{
  __int16 result; // ax@1
  int v2; // ebx@1
  char *v3; // esi@1
  int v4; // edi@4
  int v5; // ecx@4
  SpriteFrame *v6; // eax@6
  SpriteFrame *v7; // edi@6
  int v8; // eax@6
  unsigned __int16 v9; // ax@6
  RenderBillboardTransform_local0 v10; // [sp+Ch] [bp-5Ch]@1
  int v11; // [sp+5Ch] [bp-Ch]@6
  int v12; // [sp+60h] [bp-8h]@1
  int v13; // [sp+64h] [bp-4h]@6

  v10.uParentBillboardID = -1;
  v10.pTarget = pRenderer->pTargetSurface;
  v10.pTargetZ = pRenderer->pActiveZBuffer;
  v10.uTargetPitch = pRenderer->field_10;
  result = 0;
  v2 = a1;
  v10.uViewportX = 0;
  v10.uViewportY = 0;
  v10.uViewportZ = 639;
  v10.uViewportW = 479;
  v12 = 0;
  v3 = (char *)&pOtherOverlayList->pOverlays[0].field_C;
  do
  {
    if ( *((short *)v3 - 3) > 0 )
    {
      result = *((short *)v3 - 6);
      if ( result >= 300 )
      {
        v4 = result;
        v5 = result == v2 + 320 | result == v2 + 330 | result == v2 + 340 | result == v2 + 350;
        result = v2 + 310;
        if ( v4 == v2 + 310 | v5 )
        {
          if ( !*(short *)v3 )
          {
            v6 = pSpriteFrameTable->GetFrame(
                   pOverlayList->pOverlays[*((short *)v3 - 5)].uSpriteFramesetID,
                   *((short *)v3 - 4));
            v7 = v6;
            v11 = *((int *)v3 + 1);
            v13 = v6->scale;
            v13 = (unsigned __int64)(v11 * (signed __int64)v13) >> 16;
            v10.uScreenSpaceX = *((short *)v3 - 2);
            v10.uScreenSpaceY = *((short *)v3 - 1);
            v10._screenspace_x_scaler_packedfloat = v13;
            v10._screenspace_y_scaler_packedfloat = v13;
            v10.pPalette = PaletteManager::Get_Dark_or_Red_LUT(v6->uPaletteIndex, 0, 1);
            v8 = *((short *)v3 - 5);
            v10.sZValue = 0;
            v10.uFlags = 0;
            v9 = pOverlayList->pOverlays[v8].uOverlayType;
            if ( !v9 || v9 == 2 )
              v10.uScreenSpaceY += pSprites_LOD->pSpriteHeaders[v7->pHwSpriteIDs[0]].uHeight >> 1;
            result = pSprites_LOD->pSpriteHeaders[v7->pHwSpriteIDs[0]]._4AD2D1(&v10, 0);
            ++v12;
            if ( v12 == 5 )
              break;
          }
        }
      }
    }
    v3 += 20;
  }
  while ( (signed int)v3 < (signed int)&pOverlayList->pOverlays );
  return result;
}

//----- (00443801) --------------------------------------------------------
void Initialize2DA()
{
 
  int i;
	char* test_string;
	unsigned char c;
	bool break_loop;
	unsigned int temp_str_len;
	char* tmp_pos;
	int decode_step;

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

	for (i=0;i<525;++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 2:
					{
					if ( !_strnicmp(test_string, "wea", 3) )
						{
						p2DEvents[i].uType = BildingType_WeaponShop;
						break;
						}
					if ( !_strnicmp(test_string, "arm", 3) )
						{
						p2DEvents[i].uType = BildingType_ArmorShop;
						break;
						}
					if ( !_strnicmp(test_string, "mag", 3) )
						{
						p2DEvents[i].uType = BildingType_MagicShop;
						break;
						}
					if ( !_strnicmp(test_string, "alc", 3) )
						{
						p2DEvents[i].uType = BildingType_AlchemistShop;
						break;
						}
					if ( !_strnicmp(test_string, "sta", 3) )
						{
						p2DEvents[i].uType = BildingType_Stables;
						break;
						}
					if ( !_strnicmp(test_string, "boa", 3) )
						{
						p2DEvents[i].uType = BildingType_Boats;
						break;
						}
					if ( !_strnicmp(test_string, "tem", 3) )
						{
						p2DEvents[i].uType = BildingType_Temple;
						break;
						}
					if ( !_strnicmp(test_string, "tra", 3) )
						{
						p2DEvents[i].uType = BildingType_Training;
						break;
						}
					if ( !_strnicmp(test_string, "tow", 3) )
						{
						p2DEvents[i].uType = BildingType_TownHall;
						break;
						}

					if ( !_strnicmp(test_string, "tav", 3) )
						{
						p2DEvents[i].uType = BildingType_Tavern;
						break;
						}
					if ( !_strnicmp(test_string, "ban", 3) )
						{
						p2DEvents[i].uType = BildingType_Bank;
						break;
						}
					if ( !_strnicmp(test_string, "fir", 3) )
						{
						p2DEvents[i].uType = BildingType_FireGuild;
						break;
						}
					if ( !_strnicmp(test_string, "air", 3) )
						{
						p2DEvents[i].uType = BildingType_AirGuild;
						break;
						}
					if ( !_strnicmp(test_string, "wat", 3) )
						{
						p2DEvents[i].uType = BildingType_WaterGuild;
						break;
						}
					if ( !_strnicmp(test_string, "ear", 3) )
						{
						p2DEvents[i].uType = BildingType_EarthGuild;
						break;
						}
					if ( !_strnicmp(test_string, "spi", 3) )
						{
						p2DEvents[i].uType = BildingType_SpiritGuild;
						break;
						}
					if ( !_strnicmp(test_string, "min", 3) )
						{
						p2DEvents[i].uType = BildingType_MindGuild;
						break;
						}
					if ( !_strnicmp(test_string, "bod", 3) )
						{
						p2DEvents[i].uType = BildingType_BodyGuild;
						break;
						}
					if ( !_strnicmp(test_string, "lig", 3) )
						{
						p2DEvents[i].uType = BildingType_LightGuild;
						break;
						}
					if ( !_strnicmp(test_string, "dar", 3) )
						{
						p2DEvents[i].uType = BildingType_DarkGuild;
						break;
						}
					if ( !_strnicmp(test_string, "ele", 3) )
						{
						p2DEvents[i].uType = BildingType_14;
						break;
						}
					if ( !_strnicmp(test_string, "sel", 3) )
						{
						p2DEvents[i].uType = BildingType_15;
						break;
						}
					if ( !_strnicmp(test_string, "mir", 3) )
						{
						p2DEvents[i].uType = BildingType_16;
						break;
						}
					if ( !_strnicmp(test_string, "mer", 3) )
						{
						p2DEvents[i].uType = BildingType_TownHall;
						break;
						}
					p2DEvents[i].uType = BildingType_18;
					}
					break;

				case 4:
					p2DEvents[i].uAnimationID = atoi(test_string);
					break;
				case 5:
					p2DEvents[i].pName = RemoveQuotes(test_string);
					break;
				case 6:
					p2DEvents[i].pProprieterName = RemoveQuotes(test_string);
					break;
				case 7:
					p2DEvents[i].pProprieterTitle = RemoveQuotes(test_string);
					break;
				case 8:
					p2DEvents[i].field_14 = atoi(test_string);
					break;
				case 9:
					p2DEvents[i]._state = atoi(test_string);
					break;
				case 10:
					p2DEvents[i]._rep = atoi(test_string);
					break;
				case 11:
					p2DEvents[i]._per = atoi(test_string);
					break;
				case 12:
					p2DEvents[i].fPriceMultiplier = atof(test_string);
					break;
				case 13:
					p2DEvents[i].flt_24 = atof(test_string);
					break;
				case 15:
					p2DEvents[i].field_1C = atoi(test_string);
					break;
				case 18:
					p2DEvents[i].uOpenTime = atoi(test_string);
					break;
				case 19:
					p2DEvents[i].uCloseTime = atoi(test_string);
					break;
				case 20:
					p2DEvents[i].uExitPicID = atoi(test_string);
					break;
				case 21:
					p2DEvents[i].uExitMapID = atoi(test_string);
					break;
				case 22:
					p2DEvents[i]._quest_related = atoi(test_string);
					break;
				case 23:
					p2DEvents[i].pEnterText = RemoveQuotes(test_string);
					break;
					}
				}
			++decode_step;
			test_string=tmp_pos+1;
			} while ((decode_step<24)&&!break_loop);
		}

}

//----- (00443E31) --------------------------------------------------------
void LoadLevel_InitializeLevelStr()
    {
  
  char Args[100]; 
  int string_num;
  int max_string_length;
  int current_string_length;
  int prev_string_offset;

  if (sizeof(pLevelStrOffsets) != 2000)
    Log::Warning(L"pLevelStrOffsets: deserialization warning");
  memset(pLevelStrOffsets, 0, 2000);
  
  max_string_length = 0;
  string_num = 1;
  prev_string_offset = 0;
  pLevelStrOffsets[0]=0;
  for (uint i = 0; i < uLevelStrFileSize; ++i)
  {
      if ( !pLevelStr[i] )
      {
        pLevelStrOffsets[string_num] = i + 1;
		++string_num;
        if ( i - prev_string_offset > max_string_length )
          max_string_length = i - prev_string_offset;
        prev_string_offset = i;
      }
  }

  uLevelStrNumStrings = string_num - 1;
  if ( max_string_length > 800 )
  {
    sprintf(Args, "MAX_EVENT_TEXT_LENGTH needs to be increased to %lu", max_string_length+1);
    Abortf(Args);
  }

  if ( uLevelStrNumStrings > 0 )
  {
    for(uint i = 0; i <uLevelStrNumStrings ; ++i) 
    {
      if ( RemoveQuotes(&pLevelStr[pLevelStrOffsets[i]]) != &pLevelStr[pLevelStrOffsets[i]] )
        ++pLevelStrOffsets[i]; 
    }
  }
}

//----- (00443F95) --------------------------------------------------------
void __cdecl OnMapLeave()
{
 _evt_raw *test_event;
  if ( uLevelEVT_NumEvents > 0 )
  {
    for (uint i = 0; i < uLevelEVT_NumEvents; ++i)
    {
		test_event=(_evt_raw*)&pLevelEVT[pLevelEVT_Index[i].uEventOffsetInEVT];
      if ( test_event->_e_type== EVENT_OnMapLeave )
      {
        start_event_seq_number = pLevelEVT_Index[i].event_sequence_num;
        EventProcessor(pLevelEVT_Index[i].uEventID, 0, 1);
        start_event_seq_number = 0;
      }
    }
  }
}

//----- (00443FDC) --------------------------------------------------------
void OnMapLoad()
{
	stru176 *v3; // esi@7
	__int16 v4; // cx@9
	__int16 v5; // di@9
	int v6; // eax@9
	signed __int64 v8; // qax@26
	unsigned int v9; // ecx@26
	signed __int64 v10; // qax@26
	signed __int64 v11; // qax@26
	int v12; // ST50_4@26
	signed __int64 v13; // qax@26
	signed __int64 v14; // qax@26
	int v15; // ST58_4@26
	signed __int64 v16; // qax@26
	int hours; // ebx@26
	unsigned __int64 v18; // [sp+Ch] [bp-44h]@12
	signed __int64 seconds; // [sp+14h] [bp-3Ch]@26
	unsigned __int64 v20; // [sp+1Ch] [bp-34h]@7
	int minutes; // [sp+2Ch] [bp-24h]@26
	int years; // [sp+34h] [bp-1Ch]@26
	int weeks; // [sp+38h] [bp-18h]@26
	int v26; // [sp+3Ch] [bp-14h]@15
	int days; // [sp+3Ch] [bp-14h]@26
	int months; // [sp+40h] [bp-10h]@26
	__int16 v29; // [sp+46h] [bp-Ah]@9
	__int16 v30; // [sp+48h] [bp-8h]@9
	__int16 v31; // [sp+4Ah] [bp-6h]@9
	__int16 v32; // [sp+4Ch] [bp-4h]@9
	__int16 v33; // [sp+4Eh] [bp-2h]@9

	for (uint i = 0; i < uLevelEVT_NumEvents; ++i)
	{
		auto pEvent = pLevelEVT_Index[i];

		auto _evt = (_evt_raw *)(pLevelEVT + pEvent.uEventOffsetInEVT);

		if (_evt->_e_type == EVENT_PlaySound)
		{
			pSoundList->LoadSound(EVT_DWORD(_evt->v5), 0);
		}
		else if (_evt->_e_type == EVENT_OnMapReload)
		{
			start_event_seq_number = pEvent.event_sequence_num;
			EventProcessor(pEvent.uEventID, 0, 0);
			start_event_seq_number = 0;
		}
		else if (_evt->_e_type == EVENT_OnTimer || _evt->_e_type == EVENT_OnLongTimer)
		{
			v3 = &array_5B5928_timers[dword_5B65C8_timers_count];
			v20 = pOutdoor->loc_time.uLastVisitDay;
			if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
				v20 = pIndoor->stru1.uLastVisitDay;

			v3->timer_evt_type = _evt->_e_type;
			v3->timer_evt_ID = pEvent.uEventID;
			v3->timer_evt_seq_num = pEvent.event_sequence_num;

			v3->field_10 = _evt->v5;
			v3->field_12 = _evt->v6;
			v3->field_14 = _evt->v7;
			v3->field_16 = _evt->v8;
			v3->field_18 = _evt->v9;
			v3->field_1A = _evt->v10;


			v6 = ((unsigned short)_evt->v12 << 8) + _evt->v11;

			v3->time_left_to_fire = ((unsigned short)_evt->v12 << 8) + _evt->v11;
            v3->fire_interval = ((unsigned short)_evt->v12 << 8) + _evt->v11;
			if (v3->timer_evt_type  == EVENT_OnLongTimer && !(short)v6 )
			{
				if ( v20 )
					v18 = pParty->uTimePlayed - v20;
				else
					v18 = 0i64;
				v26 = (signed int)(signed __int64)((double)(signed __int64)v18 * 0.234375) / 60 / 60 / 24;

				if ( v26 / 7 / 4 / 12 )
				{
					if ( v3->field_10 )
					{
						++dword_5B65C8_timers_count;
                        v3->next_fire_time = 0;
						continue;
					}
				}
				if (v26 / 7 / 4 != 0 && v3->field_12 != 0 ||
					v26 / 7 != 0 && v3->field_14 != 0 ||
					v26 != 0 || !v20)
				{
					++dword_5B65C8_timers_count;
					v3->next_fire_time = 0;
					continue;
				}
			}
			else
			{
				v8 = (signed __int64)((double)(signed __int64)pParty->uTimePlayed * 0.234375);
				v9 = v8;
				v10 = (signed int)v8 / 60;
				minutes = v10 % 60;
				v11 = (signed int)(v10 / 60);
				v12 = v11 % 24;
				v13 = (signed int)(v11 / 24);
				days = v13 % 7;
				v14 = (signed int)(v13 / 7);
				v15 = v14 % 4;
				v16 = (signed int)(v14 / 4);
				years = v16 / 12;

				auto _1 = (unsigned __int64)((double)pParty->uTimePlayed * 0.234375) >> 32;
				auto _2 = ((__int64)v9 << 32) | _1;

				seconds = _2 % 60;
				//v19 = (signed __int64)__PAIR__((unsigned __int64)(signed __int64)((double)(signed __int64)pParty->uTimePlayed * 0.234375) >> 32,
				//                        v9)
				//    % 60;

				hours = v12;
				weeks = v15;
				months = v16 % 12;
				if ( v3->field_10 )
				{
					++years;
				}
				else
				{
					if ( v3->field_12 )
					{
						++months;
					}
					else
					{
						if ( v3->field_14 )
						{
							++weeks;
						}
						else
						{
							++days;
							minutes = v3->field_18;
							hours = v3->field_16;
							seconds = v3->field_1A;
						}
					}
				}
                v3->next_fire_time = (signed __int64)((double)((seconds
					+ 60 * minutes
					+ 3600 * hours
					+ 0x93A80 * weeks
					+ 0x15180 * days
					+ 0x24EA00 * (months + 12i64 * years)) << 7)
					* 0.033333335);

				++dword_5B65C8_timers_count;
			}
		}
	}
}

//----- (00444360) --------------------------------------------------------
void __thiscall Level_LoadEvtAndStr(const char *pLevelName)
{
  char pContainerName[120]; // [sp+8h] [bp-98h]@1

  sprintf(pContainerName, "%s.evt", pLevelName);
  uLevelEVT_Size = LoadEventsToBuffer(pContainerName, pLevelEVT, 0x2400u);

  sprintf(pContainerName, "%s.str", pLevelName);
  uLevelStrFileSize = LoadEventsToBuffer(pContainerName, pLevelStr, 0x2400u);
  if (uLevelStrFileSize)
    LoadLevel_InitializeLevelStr();
}

//----- (004443D5) --------------------------------------------------------
char *__cdecl _4443D5_GetMinimapRightClickText()
{
  int v0; // ST20_4@1
  unsigned int v1; // esi@1
  signed int v2; // ebx@1
  double v3; // st7@1
  int v4; // esi@3
  int v5; // edi@4
  int v6; // eax@4
  int v7; // eax@4
  BSPModel *v8; // ecx@4
  unsigned __int8 v9; // zf@5
  char v10; // sf@5
  unsigned __int8 v11; // of@5
  ODMFace *v12; // eax@6
  __int16 v13; // cx@6
  const char *v14; // eax@8
  const char *v15; // edi@8
  char *result; // eax@12
  unsigned int v17; // eax@14
  unsigned int v18; // [sp+Ch] [bp-20h]@1
  int v19; // [sp+10h] [bp-1Ch]@1
  int v20; // [sp+14h] [bp-18h]@1
  char *v21; // [sp+18h] [bp-14h]@1
  unsigned int pY; // [sp+1Ch] [bp-10h]@1
  int v23; // [sp+20h] [bp-Ch]@1
  int v24; // [sp+24h] [bp-8h]@1
  int pX; // [sp+28h] [bp-4h]@1

  v24 = pParty->vPosition.x;
  v0 = pParty->vPosition.y;
  v1 = pOutdoor->uNumBModels;
  *(float *)&v23 = (double)(signed int)viewparams->uMinimapZoom * 0.000015258789;
  v2 = 0;
  v18 = pOutdoor->uNumBModels;
  v21 = 0;
  pMouse->GetClickPos((unsigned int *)&pX, &pY);
  v3 = 1.0 / *(float *)&v23;
  v23 = pX - 557;
  v19 = (signed __int64)((double)(pX - 557) * v3 + (double)v24);
  v20 = (signed __int64)((double)v0 - (double)(signed int)(pY - 74) * v3);
  if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor || (*(float *)&v23 = 0.0, (signed int)v1 <= 0) )
  {
LABEL_14:
    v17 = pMapStats->GetMapInfo(pCurrentMapName);
    if ( v17 == v2 )
      result = "No Maze Info for this maze on file!";
    else
      result = pMapStats->pInfos[v17].pName;
  }
  else
  {
    v4 = 0;
    while ( 1 )
    {
      pX = pOutdoor->pBModels[v4].vBoundingCenter.x - v19;
      pY = pOutdoor->pBModels[v4].vBoundingCenter.y - v20;
      v5 = abs((signed)pY);
      v6 = abs((signed)pX);
      v7 = int_get_vector_length(v6, v5, v2);
      v8 = &pOutdoor->pBModels[0];
      if ( v7 < 2 * pOutdoor->pBModels[v4].sBoundingRadius )
      {
        v11 = __OFSUB__(pOutdoor->pBModels[v4].uNumFaces, v2);
        v9 = pOutdoor->pBModels[v4].uNumFaces == v2;
        v10 = ((pOutdoor->pBModels[v4].uNumFaces - v2) & 0x80000000u) != 0;
        v24 = v2;
        if ( !((unsigned __int8)(v10 ^ v11) | v9) )
        {
          do
          {
            v12 = &v8[v4].pFaces[v2 / 0x134u];
            v13 = v12->sCogTriggeredID;
            if ( v13 )
            {
              if ( !(BYTE2(v12->uAttributes) & 0x10) )
              {
                v14 = GetEventHintString(v13);
                v15 = v14;
                if ( v14 )
                {
                  if ( _strcmpi(v14, "") )
                    v21 = (char *)v15;
                }
              }
            }
            ++v24;
            v8 = pOutdoor->pBModels;
            v2 += 308;
          }
          while ( v24 < (signed int)pOutdoor->pBModels[v4].uNumFaces );
        }
        result = v21;
        v2 = 0;
        if ( v21 )
          break;
      }
      ++v23;
      ++v4;
      if ( v23 >= (signed int)v18 )
        goto LABEL_14;
    }
  }
  return result;
}

//----- (00444564) --------------------------------------------------------
const char *__cdecl sub_444564()
{
  double v0; // st7@3
  int v1; // ebx@3
  int v2; // edi@3
  int v3; // eax@3
  int v5; // edi@6
  int v6; // eax@6
  int v7; // eax@6
  unsigned __int8 v9; // zf@7
  unsigned __int8 v10; // sf@7
  ODMFace *v11; // eax@9
  __int16 v12; // cx@9
  const char *v13; // eax@11
  const char *v14; // edi@11
  const char *result; // eax@15
  unsigned int v16; // [sp+0h] [bp-20h]@3
  const char *v17; // [sp+4h] [bp-1Ch]@3
  unsigned int pY; // [sp+8h] [bp-18h]@3
  float v19; // [sp+Ch] [bp-14h]@1
  int v20;
  int v21; // [sp+14h] [bp-Ch]@1
  unsigned int v22; // [sp+18h] [bp-8h]@8
  int pX; // [sp+1Ch] [bp-4h]@3

  v20 = viewparams->sViewCenterX;
  v21 = viewparams->sViewCenterY;
  v19 = (double)viewparams->field_2C * 0.000015258789;
  if ( viewparams->field_2C == 384 )
  {
    v20 = viewparams->indoor_center_x;
    v21 = viewparams->indoor_center_y;
  }
  v17 = 0;
  v16 = pOutdoor->uNumBModels;
  pMouse->GetClickPos((unsigned int *)&pX, &pY);
  v0 = 1.0 / v19;
  v1 = (signed __int64)((double)(pX - 229) * v0 + (double)v20);
  LODWORD(v19) = (signed __int64)((double)v21 - (double)(signed int)(pY - 181) * v0);
  v2 = abs(v1 + 22528) / 512;
  v3 = abs((signed)LODWORD(v19) - 22528);
  result = 0;
  if ( pOutdoor->_47F04C(v2, v3 / 512)
    && uCurrentlyLoadedLevelType == LEVEL_Outdoor
    && (signed int)v16 > 0 )
  {
	for(int i = 0; i < pOutdoor->uNumBModels && !v17; i++)
    {
      pX = pOutdoor->pBModels[i].vBoundingCenter.x - v1;
      pY = pOutdoor->pBModels[i].vBoundingCenter.y - LODWORD(v19);
      v5 = abs((signed)pY);
      v6 = abs((signed)pX);
      v7 = int_get_vector_length(v6, v5, 0);
      if ( v7 < pOutdoor->pBModels[i].sBoundingRadius )
      {
        if ( pOutdoor->pBModels[i].uNumFaces > 0 )
        {
		  for(int j = 0; j < pOutdoor->pBModels[i].uNumFaces; j++)
          {
			v11 = &pOutdoor->pBModels[i].pFaces[j];//&v8[v4]->pFaces[v22 / 0x134];
            v12 = v11->sCogTriggeredID;
            if ( v12 )
            {
              if ( !(BYTE2(v11->uAttributes) & 0x10) )
              {
                v13 = GetEventHintString(v12);
                v14 = v13;
                if ( v13 )
                {
                  if ( _strcmpi(v13, "") )
                    v17 = v14;
                }
              }
            }
          }
        }
        result = v17;
      }
    }
  }
  return result;
}

//----- (00444A51) --------------------------------------------------------
void TransitionUI_Draw()
{
  MapInfo *pMapInfo; // esi@5
  char *v1; // eax@6
  std::string v3; // [sp-18h] [bp-84h]@11
  unsigned int v4; // [sp-10h] [bp-7Ch]@12
  int v5; // [sp-Ch] [bp-78h]@12
  const char *v6; // [sp-8h] [bp-74h]@11
  signed int v7; // [sp-4h] [bp-70h]@11
  GUIWindow v8; // [sp+Ch] [bp-60h]@1
  unsigned int v9; // [sp+60h] [bp-Ch]@1
  unsigned int v10; // [sp+64h] [bp-8h]@1
  int a3; // [sp+6Bh] [bp-1h]@11

  memcpy(&v8, pPrimaryWindow, sizeof(v8));
  v10 = pMapStats->GetMapInfo(pCurrentMapName);
  v9 = IndoorLocation::GetLocationIndex(dword_591164_teleport_map_name);
  pRenderer->DrawTextureIndexed(0x1DDu, 0, pTexture_Dialogue_Background);
  pRenderer->DrawTextureIndexed(pNPCPortraits_x[0][0] - 4, pNPCPortraits_y[0][0] - 4, pIcons_LOD->GetTexture(uTextureID_50795C));
  pRenderer->DrawTextureIndexed(pNPCPortraits_x[0][0], pNPCPortraits_y[0][0], pTexture_outside);
  uTextureID_507B04 = uTextureID_right_panel;
  pRenderer->DrawTextureTransparent(468, 0, pIcons_LOD->GetTexture(uTextureID_right_panel));
  pRenderer->DrawTextureIndexed(556, 451, pIcons_LOD->GetTexture(uTextureID_x_x_u));
  pRenderer->DrawTextureIndexed(476, 451, pIcons_LOD->GetTexture(uTextureID_x_ok_u));
  if ( (pVideoPlayer->AnyMovieLoaded() || v9) && *dword_591164_teleport_map_name != ' ' )
    v10 = pMapStats->GetMapInfo(dword_591164_teleport_map_name);
  pMapInfo = &pMapStats->pInfos[v10];
  v8.uFrameX = 493;
  v8.uFrameWidth = 126;
  v8.uFrameZ = 366;
  v8.DrawTitleText(pFontCreate, 0, 5u, 0, pMapInfo->pName, 3);
  v8.uFrameX = 483;
  v8.uFrameWidth = 148;
  v8.uFrameZ = 334;

  v1 = "";
  if ( uCurrentHouse_Animation )
  {
    v1 = pTransitionStrings[uCurrentHouse_Animation];
    v4 = (212 - pFontCreate->CalcTextHeight(v1, &v8, 0, 0)) / 2 + 101;
    v8.DrawTitleText(pFontCreate, 0, v4, 0, v1, 3);
  }
  else if ( v10 )
  {
    sprintfex(pTmpBuf, pGlobalTXT_LocalizationStrings[409], pMapInfo->pName);// "Do you wish to leave %s?"
    v4 = (212 - pFontCreate->CalcTextHeight(pTmpBuf, &v8, 0, 0)) / 2 + 101;
    v8.DrawTitleText(pFontCreate, 0, v4, 0, pTmpBuf, 3);
  }
  else assert(false);

  _unused_5B5924_is_travel_ui_drawn = true;
}

//----- (00444C8F) --------------------------------------------------------
void UI_CreateTravelDialogue()
{
  //signed int v0; // eax@1
  unsigned int v1; // eax@6
  GUIWindow *result; // eax@9
  //const char *v3; // [sp-4h] [bp-2Ch]@2
  char pContainer[32]; // [sp+0h] [bp-28h]@1

  pEventTimer->Pause();
  /*v0 = const_2();
  sprintf(pContainer, "evt%02d", v0);
  if ( pParty->uAlignment )
  {
    if ( pParty->uAlignment != 2 )
      goto LABEL_6;
    v3 = "-c";
  }
  else
  {
    v3 = "-b";
  }
  strcat(pContainer, v3);
LABEL_6:*/
  switch (pParty->alignment)
  {
    case PartyAlignment_Good:    sprintf(pContainer, "evt%02d-b", const_2()); break;
    case PartyAlignment_Neutral: sprintf(pContainer, "evt%02d", const_2());   break;
    case PartyAlignment_Evil:    sprintf(pContainer, "evt%02d-c", const_2()); break;
    default: assert(false);
  }

  pTexture_Dialogue_Background = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture(pContainer, TEXTURE_16BIT_PALETTE)];
  pTexture_outside = &pIcons_LOD->pTextures[pIcons_LOD->LoadTexture("outside", TEXTURE_16BIT_PALETTE)];
  v1 = pMapStats->GetMapInfo(pCurrentMapName);
  if ( v1 )
    sprintfex(sHouseName, pGlobalTXT_LocalizationStrings[410], pMapStats->pInfos[v1].pName);// "Leave %s"
  else
    strcpy(sHouseName, pGlobalTXT_LocalizationStrings[79]);// "Exit"
  pDialogueWindow = GUIWindow::Create(0, 0, 640, 480, WINDOW_ChangeLocation, 0, (int)sHouseName);
}

//----- (00444D80) --------------------------------------------------------
signed int __cdecl GetTravelTime()
{
  signed int v0; // esi@1

  v0 = uDefaultTravelTime_ByFoot;
  if ( CheckHiredNPCSpeciality(Guide) )
    --v0;
  if ( CheckHiredNPCSpeciality(Tracker) )
    v0 -= 2;
  if ( CheckHiredNPCSpeciality(Pathfinder) )
    v0 -= 3;
  if ( CheckHiredNPCSpeciality(Explorer) )
    --v0;
  if ( v0 < 1 )
    v0 = 1;
  return v0;
}
// 6BD07C: using guessed type int uDefaultTravelTime_ByFoot;

//----- (00444DCA) --------------------------------------------------------
void __cdecl TravelUI_Draw()
{
  unsigned int v0; // edi@1
  MapInfo *v1; // edi@2
  signed int v3; // eax@2
  int v4; // eax@5
  const char *v5; // [sp-Ch] [bp-90h]@3
  signed int v6; // [sp-8h] [bp-8Ch]@3
  GUIWindow v7; // [sp+Ch] [bp-78h]@1
  char pDestinationMapName[32]; // [sp+60h] [bp-24h]@1
  unsigned int v9; // [sp+80h] [bp-4h]@1

  memcpy(&v7, pPrimaryWindow, sizeof(v7));
  v9 = pMapStats->GetMapInfo(pCurrentMapName);
  pOutdoor->GetTravelDestination(pParty->vPosition.x, pParty->vPosition.y, pDestinationMapName, 20);
  v0 = pMapStats->GetMapInfo(pDestinationMapName);
  pRenderer->DrawTextureIndexed(0x1DDu, 0, pTexture_Dialogue_Background);
  pRenderer->DrawTextureTransparent(0x1D4u, 0, &pIcons_LOD->pTextures[uTextureID_507B04]);
  pRenderer->DrawTextureIndexed(pNPCPortraits_x[0][0], pNPCPortraits_y[0][0], pTexture_outside);
  pRenderer->DrawTextureIndexed(0x22Cu, 0x1C3u, pIcons_LOD->GetTexture(uTextureID_x_x_u));
  pRenderer->DrawTextureIndexed(0x1DCu, 0x1C3u, pIcons_LOD->GetTexture(uTextureID_x_ok_u));
  if ( v0 )
  {
    v1 = &pMapStats->pInfos[v0];
    v7.uFrameX = 493;
    v7.uFrameWidth = 126;
    v7.uFrameZ = 366;
    v7.DrawTitleText(pFontCreate, 0, 4u, 0, v1->pName, 3);
    v7.uFrameX = 483;
    v7.uFrameWidth = 148;
    v7.uFrameZ = 334;
    v3 = GetTravelTime();
    if ( v3 == 1 )
    {
      v6 = 1;
      v5 = pGlobalTXT_LocalizationStrings[663]; // "It will take %d day to cross to %s."
    }
    else
    {
      v6 = v3;
      v5 = pGlobalTXT_LocalizationStrings[128]; // "It will take %d days to travel to %s."
    }
    sprintfex(pTmpBuf, v5, v6, v1->pName);
    strcat(pTmpBuf, "\n \n");
    sprintfex(pTmpBuf2, pGlobalTXT_LocalizationStrings[126], pMapStats->pInfos[v9].pName);
    strcat(pTmpBuf, pTmpBuf2);
    v4 = pFontCreate->CalcTextHeight(pTmpBuf, &v7, 0, 0);
    v7.DrawTitleText(pFontCreate, 0, (212 - v4) / 2 + 101, 0, pTmpBuf, 3u);
    _unused_5B5924_is_travel_ui_drawn = 1;
  }
}

//----- (00444FBE) --------------------------------------------------------
void __cdecl DrawBranchlessDialogueUI()
{
  GUIFont *v0; // esi@1
  int v1; // esi@4
  char *v2; // eax@6
  int v3; // edi@12
  char Str[200]; // [sp+Ch] [bp-120h]@12
  GUIWindow v5; // [sp+D4h] [bp-58h]@4
  GUIFont *pFont; // [sp+128h] [bp-4h]@1

  v0 = pFontArrus;
  pFont = pFontArrus;
  if ( current_npc_text && !byte_5B0938[0] )
    strcpy(byte_5B0938, current_npc_text);
  v5.uFrameWidth = game_viewport_width;
  v5.uFrameZ = 452;
  v1 = pFontArrus->CalcTextHeight(byte_5B0938, &v5, 12, 0) + 7;
  if ( 352 - v1 < 8 )
  {
    pFont = pFontCreate;
    v1 = pFontCreate->CalcTextHeight(byte_5B0938, &v5, 12, 0) + 7;
  }
  pRenderer->_4A6A68(
    8u,
    352 - v1,
    (Texture *)(uTextureID_Leather != -1 ? (int)&pIcons_LOD->pTextures[uTextureID_Leather] : 0),
    (uTextureID_Leather != -1 ? pIcons_LOD->pTextures[uTextureID_Leather].uTextureHeight : 26) - v1);
  pRenderer->DrawTextureIndexed(8u, 347 - v1, pTexture_591428);
  v2 = FitTextInAWindow(byte_5B0938, pFont, &v5, 0xCu, 0);
  pGUIWindow2->DrawText(pFont, 12, 354 - v1, 0, v2, 0, 0, 0);
  pRenderer->DrawTextureRGB(0, 0x160u, pTexture_StatusBar);
  if ( pGUIWindow2->field_40 != 1 )
  {
    if ( pGUIWindow2->field_40 == 2 )
    {
      pGUIWindow2->field_40 = 0;
      strcpy(GameUI_Footer_TimedString, (const char *)pKeyActionMap->pPressedKeysBuffer);
LABEL_16:
      sub_4452BB();
      return;
    }
    if ( pGUIWindow2->field_40 != 3 )
      return;
    pGUIWindow2->field_40 = 0;
LABEL_15:
    memset(GameUI_Footer_TimedString, 0, 0xC8u);
    goto LABEL_16;
  }
  if ( pGUIWindow2->ptr_1C == (void *)26 )
  {
    sprintf(Str, "%s %s", GameUI_Footer_TimedString, pKeyActionMap->pPressedKeysBuffer);
    v3 = pFontLucida->GetLineWidth(Str);
    pGUIWindow2->DrawText(pFontLucida, 13, 357, 0, Str, 0, 0, 0);
    pGUIWindow2->DrawFlashingInputCursor(v3 + 13, 357, pFontLucida);
    return;
  }
  if ( pKeyActionMap->pPressedKeysBuffer[0] )
  {
    pKeyActionMap->_459ED1(0);
    goto LABEL_15;
  }
}

//----- (004451A8) --------------------------------------------------------
void __fastcall sub_4451A8_press_any_key(int a1, int a2, int a4)
{
  int v3; // esi@1
  int v4; // edi@1

  v3 = a2;
  v4 = a1;
  if ( !pGUIWindow2 )
  {
    if ( pParty->uFlags & 2 )
      pGame->Draw();
    if ( !start_event_seq_number )
      pAudioPlayer->StopChannels(-1, -1);
    pMiscTimer->Pause();
    pEventTimer->Pause();
    dword_5C3418 = v4;
    dword_5C341C = v3;
    _591094_decoration = activeLevelDecoration;
    pGUIWindow2 = GUIWindow::Create(0, 0, 640u, 480u, WINDOW_GreetingNPC, a4, 0);
    pGUIWindow2->CreateButton(61u, 424u, 0x1Fu, 0x28u, 2, 94, UIMSG_SelectCharacter, 1u, 0x31u, "", 0);
    pGUIWindow2->CreateButton(177u, 424u, 0x1Fu, 0x28u, 2, 94, UIMSG_SelectCharacter, 2u, 0x32u, "", 0);
    pGUIWindow2->CreateButton(292u, 424u, 0x1Fu, 0x28u, 2, 94, UIMSG_SelectCharacter, 3u, 0x33u, "", 0);
    pGUIWindow2->CreateButton(407u, 424u, 0x1Fu, 0x28u, 2, 94, UIMSG_SelectCharacter, 4u, 0x34u, "", 0);
  }
}

//----- (004452BB) --------------------------------------------------------
void __cdecl sub_4452BB()
{
  pGUIWindow2->Release();
  pGUIWindow2 = 0;
  activeLevelDecoration = _591094_decoration;
  start_event_seq_number = dword_5C341C;
  EventProcessor(dword_5C3418, 0, 1);
  start_event_seq_number = 0;
  activeLevelDecoration = NULL;
  pEventTimer->Resume();
}

//----- (00445308) --------------------------------------------------------
const char *GetProfessionActionText(int a1)
{
  if ( a1 == 10
    || a1 == 11
    || a1 == 12
    || a1 == 33
    || a1 == 34
    || a1 == 39
    || a1 == 40
    || a1 == 41
    || a1 == 42
    || a1 == 43
    || a1 == 52 )
    return pNPCStats->pProfessions[a1 - 1].pActionText;
  else
    return pNPCTopics[407].pTopic;
}

//----- (00445350) --------------------------------------------------------
void __cdecl DrawDialogueUI()
{
  NPCData *pNPC; // ebx@2
  int pGreetType; // eax@2
  unsigned __int16 v2; // di@2
  //unsigned int v3; // eax@2
  char *v4; // esi@3
  //int v5; // eax@11
  //char *v6; // ecx@13
  //char *v7; // eax@16
  //unsigned int v8; // edi@19
  //char *v9; // ecx@27
  char *v10; // eax@29
  //int v11; // eax@30
  int v12; // esi@39
  char *v13; // eax@41
  GUIButton *v14; // eax@43
  //GUIButton *v15; // edi@43
  signed int v16; // eax@44
  //unsigned int v23; // eax@53
  //const char *v24; // eax@59
  //unsigned __int16 v30; // cx@83
  int v31; // ecx@86
  int v32; // ebx@93
  unsigned int v33; // eax@93
  GUIWindow *v34; // ecx@93
  int v35; // esi@93
  int i; // eax@93
  GUIButton *v37; // eax@94
  int v38; // eax@95
  signed int v39; // esi@99
  signed int v40; // eax@102
  unsigned int v41; // ebx@102
  int v42; // edi@102
  GUIButton *v43; // esi@103
  int v44; // eax@104
  unsigned int v45; // ecx@104
  unsigned __int16 *v46; // edx@104
  unsigned __int16 v47; // ax@104
  GUIWindow pWindow; // [sp+4h] [bp-110h]@39
  int v49; // [sp+Ch] [bp-108h]@39
  int v50; // [sp+14h] [bp-100h]@39
  GUIWindow v51; // [sp+58h] [bp-BCh]@2
  GUIWindow v52; // [sp+ACh] [bp-68h]@42
  char *Str; // [sp+100h] [bp-14h]@104
  //int v54; // [sp+104h] [bp-10h]@2
  //unsigned __int16 *v55; // [sp+108h] [bp-Ch]@82
  GUIFont *pOutString; // [sp+10Ch] [bp-8h]@39
  char *pInString=NULL; // [sp+110h] [bp-4h]@32

  if ( !pDialogueWindow )
    return;
  memcpy(&v51, pDialogueWindow, sizeof(v51));
  pNPC = GetNPCData(sDialogue_SpeakingActorNPC_ID);
  pGreetType = GetGreetType(sDialogue_SpeakingActorNPC_ID);
  v51.uFrameWidth -= 10;
  v51.uFrameZ -= 10;
  //v54 = v1;
  GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
  GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xE1u, 0xCDu, 0x23u);
  v2 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0x15u, 0x99u, 0xE9u);
  pRenderer->DrawTextureIndexed(477, 0, pTexture_Dialogue_Background);
  pRenderer->DrawTextureTransparent(468, 0, (Texture *)(uTextureID_507B04 != -1 ? &pIcons_LOD->pTextures[uTextureID_507B04] : 0));
  pRenderer->DrawTextureIndexed(pNPCPortraits_x[0][0] - 4, pNPCPortraits_y[0][0] - 4, (Texture *)(uTextureID_50795C != -1 ? &pIcons_LOD->pTextures[uTextureID_50795C] : 0));
  pRenderer->DrawTextureIndexed(pNPCPortraits_x[0][0], pNPCPortraits_y[0][0], pDialogueNPCPortraits[0]);

  if (pNPC->uProfession)
  {
    assert(pNPC->uProfession < sizeof(aNPCProfessionNames) / sizeof(*aNPCProfessionNames)); // sometimes buffer overflows; errors emerge both here and in dialogue text
    sprintfex(pTmpBuf, pGlobalTXT_LocalizationStrings[429], pNPC->pName, aNPCProfessionNames[pNPC->uProfession]);//^Pi[%s] %s
  }
  else
    strcpy(pTmpBuf, pNPC->pName);

  v51.DrawTitleText(pFontArrus, 483, 112, v2, pTmpBuf, 3);
  pParty->GetPartyFame();

  pInString = nullptr;
  switch (uDialogueType)
  {
    case DIALOGUE_13:
      pInString = BuilDialogueString(pNPCStats->pProfessions[pNPC->uProfession - 1].pJoinText, uActiveCharacter - 1, 0, 0, 0, 0);
    break;

    case DIALOGUE_PROFESSION_DETAILS:
    {
      auto prof = pNPCStats->pProfessions + pNPC->uProfession - 1;

      if (dialogue_show_profession_details)
        pInString = BuilDialogueString(prof->pBenefits, uActiveCharacter - 1, 0, 0, 0, 0);
      else if (pNPC->Hired())
        pInString = BuilDialogueString(prof->pDismissText, uActiveCharacter - 1, 0, 0, 0, 0);
      else
        pInString = BuilDialogueString(prof->pJoinText, uActiveCharacter - 1, 0, 0, 0, 0);
    }
    break;


    case DIALOGUE_ARENA_WELCOME:
      pInString = pGlobalTXT_LocalizationStrings[574]; // "Welcome to the Arena of Life and Death.  Remember, you are only allowed one arena combat per visit.  To fight an arena battle, select the option that best describes your abilities and return to me- if you survive:"
    break;

    case DIALOGUE_ARENA_FIGHT_NOT_OVER_YET:
      pInString = pGlobalTXT_LocalizationStrings[577]; //"Get back in there you wimps:"
    break;

    case DIALOGUE_ARENA_REWARD:
      sprintfex(pTmpBuf, pGlobalTXT_LocalizationStrings[576], gold_transaction_amount);// "Congratulations on your win: here's your stuff: %u gold."
      pInString = pTmpBuf;
    break;

    case DIALOGUE_ARENA_ALREADY_WON:
      pInString = pGlobalTXT_LocalizationStrings[582]; // "You already won this trip to the Arena:"
    break;

    default:
      if (uDialogueType > DIALOGUE_18 && uDialogueType < DIALOGUE_23 && !byte_5B0938[0])
      {
        pInString = (char *)current_npc_text;
      }
      else if (pGreetType == 1)//QuestNPC_greet
      {
        if (pNPC->greet)
        {
          if ((pNPC->uFlags & 3) == 2)
            pInString = pNPCStats->pNPCGreetings[pNPC->greet - 1].pGreeting2;
          else
            pInString = pNPCStats->pNPCGreetings[pNPC->greet - 1].pGreeting1;
        }
      }
      else if (pGreetType == 2)//HiredNPC_greet
      {
        auto prof = pNPCStats->pProfessions + pNPC->uProfession - 1;

        if (pNPC->Hired())
          pInString = BuilDialogueString(prof->pDismissText, uActiveCharacter - 1, 0, 0, 0, 0);
        else
          pInString = BuilDialogueString(prof->pJoinText, uActiveCharacter - 1, 0, 0, 0, 0);
      }
    break;
  }

  if (pInString)
  {
    pWindow.uFrameWidth = game_viewport_width;
    pWindow.uFrameZ = 452;
    auto font = pFontArrus;
    v12 = pFontArrus->CalcTextHeight(pInString, &pWindow, 13, 0) + 7;
    if ( 352 - v12 < 8 )
    {
      font = pFontCreate;
       v12 = pFontCreate->CalcTextHeight(pInString, &pWindow, 13, 0) + 7;
    }
    if (uTextureID_Leather != -1)
      pRenderer->_4A6A68(8, 352 - v12, &pIcons_LOD->pTextures[uTextureID_Leather], pIcons_LOD->pTextures[uTextureID_Leather].uTextureHeight - v12);
    pRenderer->DrawTextureIndexed(8u, 347 - v12, pTexture_591428);
    v13 = FitTextInAWindow(pInString, font,  &pWindow, 0xDu, 0);
    pDialogueWindow->DrawText(font, 13, 354 - v12, 0, v13, 0, 0, 0);
  }


  memcpy(&v52, pDialogueWindow, sizeof(v52));
  v52.uFrameX = 483;
  v52.uFrameWidth = 148;
  v52.uFrameZ = 334;
  for (int i = v52.pStartingPosActiveItem;
       i < v52.pStartingPosActiveItem + v52.pNumPresenceButton; ++i)
  {
    v14 = v52.GetControl(i);
    //v15 = v14;
    if ( !v14 )
      break;
    v16 = v14->msg_param;

    if ( v16 > 88 )
      v14->pButtonName[0] = 0;
	else if (v16 == 88)
      strcpy(v14->pButtonName, pGlobalTXT_LocalizationStrings[581]); // Lord
    else if (v16 == 87)
      strcpy(v14->pButtonName, pGlobalTXT_LocalizationStrings[580]); // Knight
    else if (v16 == 86)
      strcpy(v14->pButtonName, pGlobalTXT_LocalizationStrings[579]); // Squire
    else if (v16 == 85)
      strcpy(v14->pButtonName, pGlobalTXT_LocalizationStrings[578]); // Page
    else if (v16 == 77)
      strcpy(v14->pButtonName, pGlobalTXT_LocalizationStrings[407]); // Details
    else if (v16 == 76)
    {
      if (pNPC->Hired())
        sprintf(v14->pButtonName, (const char*)pGlobalTXT_LocalizationStrings[408], pNPC->pName); // Release %s
      else
        strcpy(v14->pButtonName, pGlobalTXT_LocalizationStrings[406]); // Hire
    }
	else if (v16 == 24)
    {
      __debugbreak(); // learn conditions of this event
      auto topic = pNPCTopics[pNPC->evt_F - 1].pTopic;//(&dword_721660)[8 * v23];
      if (!topic)
      {
        v14->pButtonName[0] = 0;
        v14->msg_param = 0;
      }
      else
        strcpy(v14->pButtonName, topic);
    }
	else if (v16 == 9)
      strcpy(v14->pButtonName, GetProfessionActionText(pNPC->uProfession));
	else if (v16 == 19)
	{
     // __debugbreak(); // learn conditions of this event Scavenger Hunt
      auto topic = pNPCTopics[pNPC->evt_A - 1].pTopic;//(&dword_721660)[8 * v23];
      if (!topic)
      {
        v14->pButtonName[0] = 0;
        v14->msg_param = 0;
      }
      else strcpy(v14->pButtonName, topic);
	}
	else if (v16 == 20)
	{
      //__debugbreak(); // learn conditions of this event instruments
      auto topic = pNPCTopics[pNPC->evt_B - 1].pTopic;//(&dword_721660)[8 * v23];
      if (!topic)
      {
        v14->pButtonName[0] = 0;
        v14->msg_param = 0;
      }
      else strcpy(v14->pButtonName, topic);
	}
	else if (v16 == 21)
	{
      //__debugbreak(); // learn conditions of this event
      auto topic = pNPCTopics[pNPC->evt_C - 1].pTopic;//(&dword_721660)[8 * v23];
      if (!topic)
      {
        v14->pButtonName[0] = 0;
        v14->msg_param = 0;
      }
      else strcpy(v14->pButtonName, topic);
	}
	else if (v16 == 22)
	{
      //__debugbreak(); // learn conditions of this event
      auto topic = pNPCTopics[pNPC->evt_D - 1].pTopic;//(&dword_721660)[8 * v23];
      if (!topic)
      {
        v14->pButtonName[0] = 0;
        v14->msg_param = 0;
      }
      else strcpy(v14->pButtonName, topic);
	}
	else if (v16 == 23)
	{
      //__debugbreak(); // learn conditions of this event
      auto topic = pNPCTopics[pNPC->evt_E - 1].pTopic;//(&dword_721660)[8 * v23];
      if (!topic)
      {
        v14->pButtonName[0] = 0;
        v14->msg_param = 0;
      }
      else strcpy(v14->pButtonName, topic);
	}
	else if (v16 == 13)
	{
      if (pNPC->Hired())
        sprintf(v14->pButtonName, pGlobalTXT_LocalizationStrings[408], pNPC->pName); // Release %s
      else
        strcpy(v14->pButtonName, pGlobalTXT_LocalizationStrings[122]); // Join
	}
	else
      v14->pButtonName[0] = 0;
	

    if (pParty->field_7B5_in_arena_quest && pParty->field_7B5_in_arena_quest != -1)
    {
      int num_dead_actors = 0;
      pInString = 0;
      for (uint i = 0; i < uNumActors; ++i)
      {
        if (pActors[i].uAIState == Dead || pActors[i].uAIState == Removed ||
            pActors[i].uAIState  == Disabled)
          ++num_dead_actors;
        else
        {
          int sumonner_type = PID_TYPE(pActors[i].uSummonerID);
          if (sumonner_type == OBJECT_Player)
            ++num_dead_actors;
        }
      }
      if (num_dead_actors == uNumActors)
        strcpy(v14->pButtonName, pGlobalTXT_LocalizationStrings[658]); // Collect Prize
    }
  }


  v32 = 0;
  //pInString = (char *)GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
  v33 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xE1u, 0xCDu, 0x23u);
  v34 = pDialogueWindow;
  //v54 = v33;
  v35 = pDialogueWindow->pStartingPosActiveItem;
  for ( i = v35 + pDialogueWindow->pNumPresenceButton; v35 < i; i = pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem )
  {
    v37 = v34->GetControl(v35);
    if ( !v37 )
    {
      v34 = pDialogueWindow;
      break;
    }
    v38 = pFontArrus->CalcTextHeight(v37->pButtonName, &v52, 0, 0);
    v34 = pDialogueWindow;
    v32 += v38;
    ++v35;
  }
  v39 = v34->pNumPresenceButton;
  if ( v39 )
  {
    pOutString = (GUIFont *)((174 - v32) / v39);
    if ( (174 - v32) / v39 > 32 )
      pOutString = (GUIFont *)32;
    int v55 = 1;
    v40 = 174 - (int)pOutString * v39 - v32;
    v41 = v34->pStartingPosActiveItem;
    v42 = v40 / 2 - (signed int)pOutString / 2 + 138;
    if ( (signed int)v41 < (signed int)(v41 + v39) )
    {
      do
      {
        v43 = v34->GetControl(v41);
        if ( !v43 )
          break;
        v43->uY = (unsigned int)((char *)pOutString + v42);
        Str = v43->pButtonName;
        v44 = pFontArrus->CalcTextHeight(v43->pButtonName, &v52, 0, 0);
        v45 = v43->uY;
        v46 = (unsigned short *)v55;
        v43->uHeight = v44;
        v42 = v45 + v44 - 1;
        v43->uW = v42;
        v47 = v33;
        if ( (unsigned __int16 *)pDialogueWindow->pCurrentPosActiveItem != v46 )
          v47 = GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(0xFFu, 0xFFu, 0xFFu);
        v52.DrawTitleText(pFontArrus, 0, v45, v47, Str, 3u);
        v34 = pDialogueWindow;
        ++v55;
        ++v41;
      }
      while ( (signed int)v41 < pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem );
    }
  }
  pRenderer->DrawTextureIndexed(471, 445, (Texture *)(uExitCancelTextureId != -1 ? &pIcons_LOD->pTextures[uExitCancelTextureId] : 0));
}

//----- (00445C8B) --------------------------------------------------------
int __fastcall GetGreetType(signed int SpeakingNPC_ID)
{
  signed int v1; // ebx@1
  int v3; // edi@6
  int v4; // ecx@6
  int v5; // edx@6
  NPCData *v6; // eax@6
  char *v7; // ebp@11
  NPCData *v8; // esi@11

  v1 = 0;
  if ( SpeakingNPC_ID >= 0 )
  {
    if ( SpeakingNPC_ID < 5000 )
      return 1;//QuestNPC_greet
    return 2;//HiredNPC_greet
  }
  if ( SpeakingNPC_ID >= 5000 )
    return 2;
  v3 = abs((int)sDialogue_SpeakingActorNPC_ID) - 1;
  v4 = 0;
  v5 = 0;
  v6 = pParty->pHirelings;
  do
  {
    if ( v6->pName )
      pTmpBuf[v4++] = v5;
    ++v6;
    ++v5;
  }
  while ( (signed int)v6 < (signed int)&pParty->pPickedItem );
  if ( (signed int)pNPCStats->uNumNewNPCs > 0 )
  {
    v7 = &pTmpBuf[v4];
    v8 = pNPCStats->pNewNPCData;
    do
    {
      if (v8->Hired() && (!pParty->pHirelings[0].pName || strcmp(v8->pName, pParty->pHirelings[0].pName)) )
      {
        if ( !pParty->pHirelings[1].pName || strcmp(v8->pName, pParty->pHirelings[1].pName) )
          *v7++ = v1 + 2;
      }
      ++v1;
      ++v8;
    }
    while ( v1 < (signed int)pNPCStats->uNumNewNPCs );
  }
  return ((unsigned __int8)pTmpBuf[v3] < 2) + 1;
}

//----- (0044603D) --------------------------------------------------------
void __cdecl sub_44603D()
{
  sDialogue_SpeakingActorNPC_ID = 0;
  pDialogueWindow->Release();
  pDialogueWindow = 0;
  pMiscTimer->Resume();
  pEventTimer->Resume();
}

//----- (004465DF) --------------------------------------------------------
int sub_4465DF_check_season(int a1)
{
  unsigned int v1; // eax@1
  unsigned int v2; // edx@1
  int v3; // ecx@2
  int v4; // ecx@3
  char v6; // zf@9

  v1 = pParty->uCurrentMonth + 1;
  v2 = pParty->uDaysPlayed + 1;
  if ( a1 )
  {
    v3 = a1 - 1;
    if ( v3 )
    {
      v4 = v3 - 1;
      if ( v4 )
      {
        if ( v4 != 1 )
          return 0;
        if ( v1 != 12 )
        {
          if ( (signed int)v1 >= 1 && (signed int)v1 <= 2 )
            return 1;
          v6 = v1 == 3;
LABEL_24:
          if ( !v6 || (signed int)v2 >= 21 )
            return 0;
          return 1;
        }
      }
      else
      {
        if ( v1 != 9 )
        {
          if ( (signed int)v1 >= 10 && (signed int)v1 <= 11 )
            return 1;
          v6 = v1 == 12;
          goto LABEL_24;
        }
      }
    }
    else
    {
      if ( v1 != 6 )
      {
        if ( (signed int)v1 >= 7 && (signed int)v1 <= 8 )
          return 1;
        v6 = v1 == 9;
        goto LABEL_24;
      }
    }
  }
  else
  {
    if ( v1 != 3 )
    {
      if ( (signed int)v1 >= 4 && (signed int)v1 <= 5 )
        return 1;
      v6 = v1 == 6;
      goto LABEL_24;
    }
  }
  if ( (signed int)v2 >= 21 )
    return 1;
  return 0;
}

//----- (0044665D) --------------------------------------------------------
// uType:     0 -> any monster
//            1 -> uParam is GroupID
//            2 -> uParam is MonsterID
//            3 -> uParam is ActorID
// uNumAlive: 0 -> all must be alive
int __fastcall IsActorAlive(unsigned int uType, unsigned int uParam, unsigned int uNumAlive)
{
  unsigned int uAliveActors; // eax@6
  int v5; // ecx@10
  unsigned int uTotalActors; // [sp+0h] [bp-4h]@1

  uTotalActors = 0;
  if ( uType )
  {
    if ( uType == 1 )
    {
      uAliveActors = SearchActorByGroup(&uTotalActors, uParam);
    }
    else
    {
      if ( uType == 2 )
      {
        uAliveActors = SearchActorByMonsterID(&uTotalActors, uParam);
      }
      else
      {
        if ( uType != 3 )
          return 0;
        uAliveActors = SearchActorByID(&uTotalActors, uParam);
      }
    }
  }
  else
  {
    uAliveActors = SearchAliveActors(&uTotalActors);
  }
  v5 = 0;
  if ( uNumAlive )
    LOBYTE(v5) = (signed int)uAliveActors >= (signed int)uNumAlive;
  else
    LOBYTE(v5) = uTotalActors == uAliveActors;
  return v5;
}

//----- (004466C4) --------------------------------------------------------
int NPC_EventProcessor( int npc_event_id )
	{
  signed int event_index; // ebp@1
  int evt_seq_num; // esi@3
  bool ready_to_exit; // [sp+Ch] [bp-Ch]@3
  signed int npc_activity; // [sp+10h] [bp-8h]@3
  int result;

  event_index = 0;
  if ( !npc_event_id )
    return 0;
  evt_seq_num = start_event_seq_number;
  pSomeOtherEVT = pGlobalEVT;
  uSomeOtherEVT_NumEvents = uGlobalEVT_NumEvents;
  memcpy(pSomeOtherEVT_Events, pGlobalEVT_Index, sizeof(EventIndex)*4400);
  npc_activity = 1;
  ready_to_exit = false;
  if ( uSomeOtherEVT_NumEvents <= 0 )
    return 2;
  do
  {
    if ( (pSomeOtherEVT_Events[event_index].uEventID == npc_event_id) && (pSomeOtherEVT_Events[event_index].event_sequence_num == evt_seq_num) )
    {
	  _evt_raw *_evt = (_evt_raw *)&pSomeOtherEVT[pSomeOtherEVT_Events[event_index].uEventOffsetInEVT];
	  switch(_evt->_e_type)
		  {
	  case EVENT_Exit:
		   //exit
		  if ( ready_to_exit )
			  result = npc_activity != 0;
		  else
			   result = 2;
		  return result;
		  break;
	  case EVENT_OnCanShowDialogItemCmp:
		  ready_to_exit = true;
		  //v8 = (unsigned __int8)v7[7] + (((unsigned __int8)v7[8] + (((unsigned __int8)v7[9] + ((unsigned __int8)v7[10] << 8)) << 8)) << 8);
		  for(int i=0; i<4; ++i)
			  {  
			//  if (pParty->pPlayers[i].CompareVariable((enum VariableType)((unsigned __int8)pSomeOtherEVT[v6 + 5] + ((unsigned __int8)pSomeOtherEVT[v6 + 6] << 8)),
				//  v8))
			  if (pParty->pPlayers[i].CompareVariable((enum VariableType)EVT_WORD(_evt->v5), EVT_DWORD(_evt->v7)))
				  {
				  event_index = -1;
				  evt_seq_num = EVT_BYTE(_evt->v11)-1;//(unsigned __int8)pSomeOtherEVT[v6 + 11] - 1;
				  break;
				  }
			}
		  break;
	  case EVENT_EndCanShowDialogItem :
		  if ( ready_to_exit )
			  result = npc_activity != 0;
		  else
			  result = 2;
		  return result;
		  break;
	  case EVENT_SetCanShowDialogItem :
		  ready_to_exit = true;
		  npc_activity = EVT_BYTE(_evt->v5); //(unsigned __int8)v7[5];
		  break;
	  case EVENT_IsActorAssasinated :
		//  if (IsActorAlive( (unsigned __int8)v7[5], 
		//	  (unsigned __int8)v7[6] + (((unsigned __int8)v7[7] + (((unsigned __int8)v7[8] + ((unsigned __int8)v7[9] << 8)) << 8)) << 8),
			//  (unsigned __int8)v7[10]) )
			if (IsActorAlive( EVT_BYTE(_evt->v5),  EVT_DWORD(_evt->v6), EVT_BYTE(_evt->v10)))
			  {  // drop linear sequense, going to new seq
				event_index = -1;
				evt_seq_num = EVT_BYTE(_evt->v11)-1;//(unsigned __int8)pSomeOtherEVT[v6 + 11] - 1;
			  }
		  break;	  
		  }
		++evt_seq_num;
    }
    ++event_index;
  }
  while ( event_index < uSomeOtherEVT_NumEvents );
  if ( ready_to_exit )
    result = npc_activity != 0;
  else
    result = 2;
  return result;
}

//----- (0044861E) --------------------------------------------------------
void __fastcall sub_44861E_set_texture(unsigned int uFaceCog, const char *pFilename)
{
  unsigned int v2; // eax@2
  unsigned __int16 v3; // di@2
  signed int v4; // esi@5
  BLVFace *v5; // eax@7
  unsigned int *v6; // eax@8
  char *v7; // eax@9
  int v8; // edi@16
  char *v9; // esi@16
  ODMFace *v10; // eax@17
  unsigned int *v11; // eax@19
  unsigned __int16 v12; // [sp+Ch] [bp-18h]@2
  const char *Str2; // [sp+10h] [bp-14h]@1
  unsigned int v14; // [sp+14h] [bp-10h]@1
  signed int v15; // [sp+18h] [bp-Ch]@14
  int v16; // [sp+1Ch] [bp-8h]@15
  signed int v17; // [sp+20h] [bp-4h]@4
  signed int v18; // [sp+20h] [bp-4h]@16

  Str2 = pFilename;
  v14 = uFaceCog;
  if ( uFaceCog )
  {
    v2 = pBitmaps_LOD->LoadTexture(pFilename);
    v3 = v2;
    v12 = v2;
    if ( v2 != -1 ? (int)&pBitmaps_LOD->pTextures[v2] : 0 )
    {
      pBitmaps_LOD->pTextures[v2].palette_id2 = pPaletteManager->LoadPalette(pBitmaps_LOD->pTextures[v2].palette_id1);

      if ( uCurrentlyLoadedLevelType == 1 )
      {
        v17 = 1;
        if ( (signed int)pIndoor->uNumFaceExtras > 1 )
        {
          v4 = 1;
          do
          {
            if ( pIndoor->pFaceExtras[v4].sCogNumber == v14 )
            {
              v5 = &pIndoor->pFaces[pIndoor->pFaceExtras[v4].field_C];
              if ( BYTE1(v5->uAttributes) & 0x40 )
              {
                pIndoor->pFaces[pIndoor->pFaceExtras[v4].field_C].uBitmapID = pTextureFrameTable->FindTextureByName(
                                                                              Str2);
                v6 = (unsigned int *)&pIndoor->pFaces[pIndoor->pFaceExtras[v4].field_C].uBitmapID;
                if ( *(_WORD *)v6 )
                {
                  pTextureFrameTable->LoadAnimationSequenceAndPalettes(*(_WORD *)v6);
                }
                else
                {
                  *(_WORD *)v6 = v3;
                  v7 = (char *)&pIndoor->pFaces[pIndoor->pFaceExtras[v4].field_C].uAttributes;
                  v7[1] &= 0xBFu;
                }
              }
              else
              {
                v5->uBitmapID = v3;
              }
            }
            ++v17;
            ++v4;
          }
          while ( v17 < (signed int)pIndoor->uNumFaceExtras );
        }
        pParty->uFlags |= 2u;
      }
      else
      {
        v15 = 0;
        if ( (signed int)pOutdoor->uNumBModels > 0 )
        {
          v16 = 0;
          do
          {
            v8 = 0;
            v9 = (char *)&pOutdoor->pBModels[v16].pVertices;
            v18 = 0;
            if ( (signed int)pOutdoor->pBModels[v16].uNumFaces > 0 )
            {
              do
              {
                v10 = (ODMFace *)(v8 + *((_DWORD *)v9 + 4));
                if ( v10->sCogNumber == v14 )
                {
                  if ( BYTE1(v10->uAttributes) & 0x40 )
                  {
                    *(_WORD *)(*((_DWORD *)v9 + 4) + v8 + 272) = pTextureFrameTable->FindTextureByName(
                                                                   Str2);
                    v11 = (unsigned int *)(*((_DWORD *)v9 + 4) + v8 + 272);
                    if ( *(_WORD *)v11 )
                    {
                      pTextureFrameTable->LoadAnimationSequenceAndPalettes(*(_WORD *)v11);
                    }
                    else
                    {
                      *(_WORD *)v11 = v12;
                      *(_BYTE *)(*((_DWORD *)v9 + 4) + v8 + 29) &= 0xBFu;
                    }
                  }
                  else
                  {
                    v10->uTextureID = v12;
                  }
                }
                ++v18;
                v8 += 308;
              }
              while ( v18 < *((_DWORD *)v9 + 2) );
            }
            ++v15;
            ++v16;
          }
          while ( v15 < (signed int)pOutdoor->uNumBModels );
        }
      }
      pParty->uFlags |= 2u;
    }
  }
}

//----- (0044882F) --------------------------------------------------------
void __fastcall SetDecorationSprite(unsigned int uCog, int a2, const char *pFileName)
{
  signed int v3; // ebp@1
  char *v4; // esi@2
  unsigned __int16 v5; // ax@6
  unsigned int v6; // [sp+4h] [bp-8h]@1
  int v7; // [sp+8h] [bp-4h]@1

  v3 = 0;
  v7 = a2;
  v6 = uCog;
  if ( (signed int)uNumLevelDecorations > 0 )
  {
    v4 = (char *)&pLevelDecorations[0].field_2;
    do
    {
      if ( *((_WORD *)v4 + 9) == v6 )
      {
        if ( pFileName && _strcmpi(pFileName, "0") )
        {
          v5 = pDecorationList->GetDecorIdByName(pFileName);
          *((_WORD *)v4 - 1) = v5;
          pDecorationList->InitializeDecorationSprite((signed __int16)v5);
        }
        if ( v7 )
          *v4 &= 0xDFu;
        else
          *v4 |= 0x20u;
        pParty->uFlags |= 2u;
      }
      ++v3;
      v4 += 32;
    }
    while ( v3 < (signed int)uNumLevelDecorations );
  }
}

//----- (004488B6) --------------------------------------------------------
unsigned __int16 DecorationList::GetDecorIdByName(const char *pName)
{
  DecorationList *v2; // esi@1
  signed int uID; // edi@2
  signed int v4; // ebx@3
  unsigned __int16 result; // ax@6

  v2 = this;
  if ( pName && (uID = 1, (signed int)this->uNumDecorations > 1) )
  {
    v4 = 1;
    while ( _strcmpi(pName, v2->pDecorations[v4].pName) )
    {
      ++uID;
      ++v4;
      if ( uID >= (signed int)v2->uNumDecorations )
        goto LABEL_6;
    }
    result = uID;
  }
  else
  {
LABEL_6:
    result = 0;
  }
  return result;
}

//----- (0044892E) --------------------------------------------------------
void __fastcall sub_44892E_set_faces_bit(int sCogNumber, int bit, int on)
{
  signed int v3; // esi@2
  signed int v4; // ecx@4
  char *v5; // eax@6
  int v6; // edi@13
  char *v7; // esi@13
  signed int v8; // ecx@13
  ODMFace *v9; // eax@14
  int v10; // [sp+0h] [bp-Ch]@1
  signed int v11; // [sp+4h] [bp-8h]@11
  int v12; // [sp+8h] [bp-4h]@12

  v10 = sCogNumber;
  if ( sCogNumber )
  {
    v3 = 1;
    if ( uCurrentlyLoadedLevelType == 1 )
    {
      if ( (signed int)pIndoor->uNumFaceExtras > 1 )
      {
        v4 = 1;
        do
        {
          if ( pIndoor->pFaceExtras[v4].sCogNumber == v10 )
          {
            v5 = (char *)&pIndoor->pFaces[pIndoor->pFaceExtras[v4].field_C].uAttributes;
            if ( on )
              *(_DWORD *)v5 |= bit;
            else
              *(_DWORD *)v5 &= ~bit;
          }
          ++v3;
          ++v4;
        }
        while ( v3 < (signed int)pIndoor->uNumFaceExtras );
      }
      pParty->uFlags |= 2u;
    }
    else
    {
      v11 = 0;
      if ( (signed int)pOutdoor->uNumBModels > 0 )
      {
        v12 = 0;
        do
        {
          v6 = 0;
          v7 = (char *)&pOutdoor->pBModels[v12].pVertices;
          v8 = 0;
          if ( (signed int)pOutdoor->pBModels[v12].uNumFaces > 0 )
          {
            do
            {
              v9 = (ODMFace *)(v6 + *((_DWORD *)v7 + 4));
              if ( v9->sCogNumber == v10 )
              {
                if ( on )
                  v9->uAttributes |= bit;
                else
                  v9->uAttributes &= ~bit;
              }
              ++v8;
              v6 += 308;
            }
            while ( v8 < *((_DWORD *)v7 + 2) );
          }
          ++v11;
          ++v12;
        }
        while ( v11 < (signed int)pOutdoor->uNumBModels );
      }
    }
    pParty->uFlags |= 2u;
  }
}

//----- (00448A98) --------------------------------------------------------
void __fastcall ToggleActorGroupFlag(unsigned int uGroupID, unsigned int uFlag, unsigned int bToggle)
{
  unsigned int v3; // ebx@1
  unsigned int v4; // ebp@1
  signed int v5; // edi@1
  Actor *v6; // esi@4
  size_t v7; // ecx@10
  Actor *v8; // eax@11
  unsigned __int16 v9; // dx@14

  v4 = uGroupID;
  v5 = Standing;
  v3 = uFlag;
  if ( uGroupID )
  {
    if ( bToggle )
    {
      if ( (signed int)uNumActors > Standing )
      {
        v6 = pActors;//[0].uAttributes;
        do
        {
          if ( v6->uGroup == v4 )
          {
            v6->uAttributes |= v3;
            if ( v3 == 0x10000 )
            {
              v6->uAIState = Disabled;
              v6->UpdateAnimation();
            }
          }
          ++v5;
          ++v6;
        }
        while ( v5 < (signed int)uNumActors );
      }
    }
    else
    {
      v7 = uNumActors;
      if ( (signed int)uNumActors > Standing )
      {
        v8 = pActors;//[0].uAIState;
        do
        {
          if ( v8->uGroup == v4 )
          {
            if ( v3 == 0x10000 )
            {
              v9 = v8->uAIState;
              if ( v8->uAIState != Dead )
              {
                if ( v9 != 4 && v9 != 11 )
                  v8->uAIState = Standing;
              }
            }
			LODWORD(v8->uAttributes) &= ~v3;
          }
          ++v8;
          --v7;
        }
        while ( v7 );
      }
    }
  }
}

//----- (00448B45) --------------------------------------------------------
void __thiscall GameUI_StatusBar_UpdateTimedString(unsigned int bForceHide)
{
  if ( bForceHide || GameUI_Footer_TimeLeft && GetTickCount() >= GameUI_Footer_TimeLeft )
    GameUI_Footer_TimeLeft = 0;
}

//----- (00448B67) --------------------------------------------------------
void OnTimer(int __unused)
{
  if (pEventTimer->bPaused)
    return;
  
  if (__unused)
    _5773C0_unused = 0;
  
  auto v13 = (signed __int64)(pParty->uTimePlayed - _5773B8_event_timer) / 128;
  if (!v13)
    return;

  //uint _v2v3 = pParty->uTimePlayed;
  //v3 = HIDWORD(pParty->uTimePlayed);
  //v2 = LODWORD(pParty->uTimePlayed);

  _5773B8_event_timer = pParty->uTimePlayed;

  for (uint i = 0; i < dword_5B65C8_timers_count; ++i)
  {
        //v4 = (char *)&array_5B5928_timers[0].field_C;
    auto timer = array_5B5928_timers + i;
        //while ( 1 )
        //{
          //v5 = *(short *)v4;
    if (timer->time_left_to_fire)
    {
      if (v13 < timer->time_left_to_fire)
        timer->time_left_to_fire -= v13;
      else
      {
        timer->time_left_to_fire = timer->fire_interval;

        start_event_seq_number = timer->timer_evt_seq_num;
        EventProcessor(timer->timer_evt_ID, 0, 1);

        start_event_seq_number = 0;
      }
    }
    else
    {
      if (timer->next_fire_time < pParty->uTimePlayed)
      {
        uint next_trigger_time = 1 * 60 * 60 * 24; // 1 day
        if (timer->field_10)
          next_trigger_time = 336 * 60 * 60 * 24; // 1 year
        else if (timer->field_12)
          next_trigger_time = 28 * 60 * 60 * 24; // 1 month
        else if (timer->field_14)
          next_trigger_time = 7 * 60 * 60 * 24; // 1 week

        timer->next_fire_time += (next_trigger_time * 128) / 3.0f;
        if (timer->next_fire_time < pParty->uTimePlayed) // make sure in wont fire several times in a row is big time interval has lapsed
          timer->next_fire_time = pParty->uTimePlayed;

        start_event_seq_number = timer->timer_evt_seq_num;
        EventProcessor(timer->timer_evt_ID, 0, 1);

        start_event_seq_number = 0;
      }
    }
  }
}

//----- (00481D77) --------------------------------------------------------
void _outdoor_project(RenderVertexSoft *v)
{
  double v1; // st7@1
  double v2; // st7@1

  v1 = 1.0 / (v->vWorldViewPosition.x + 0.0000001);
  v->_rhw = v1;
  v2 = v1 * (double)pOutdoorCamera->int_fov_rad;
  v->vWorldViewProjX = (double)pViewport->uScreenCenterX - v2 * v->vWorldViewPosition.y;
  v->vWorldViewProjY = (double)pViewport->uScreenCenterY - v2 * v->vWorldViewPosition.z;
}

//----- (00448CF4) --------------------------------------------------------
void __fastcall sub_448CF4_spawn_monsters(__int16 typeindex, __int16 level, int count, int x, int y, int z, int group, unsigned int uUniqueName)
{
  __int16 v8; // di@1
  __int16 v9; // si@1
  unsigned int v10; // eax@1
  size_t v11; // ebx@2
  signed int v12; // esi@2
  Actor *pActor;//Actor_uYawAngle_cr *v13; // ebx@3
  AIDirection a3; // [sp+Ch] [bp-50h]@2
  AIDirection v15; // [sp+28h] [bp-34h]@2
  //SpawnPointMM7 v16; // [sp+44h] [bp-18h]@1

  v8 = typeindex;
  v9 = level;

  SpawnPointMM7 v16; // [sp+44h] [bp-18h]@1
  //SpawnPointMM7::SpawnPointMM7(&v16);

  v16.vPosition.x = x;
  v16.vPosition.y = y;
  v16.vPosition.z = z;
  v16.uGroup = group;
  v16.uRadius = 32;
  v16.uKind = 3;
  v16.uIndex = v8 + 2 * v9 + v9;
  v10 = pMapStats->GetMapInfo(pCurrentMapName);
  if ( v10 )
  {
    v11 = uNumActors;
    SpawnEncounter((MapInfo *)&pMapStats->pInfos[v10], &v16, 0, count, 0);
    memcpy(&v15, Actor::GetDirectionInfo(PID(OBJECT_Actor, v11), 4u, &a3, 1), sizeof(v15));
    v12 = v11;
    if ( (signed int)v11 < (signed int)uNumActors )
    {
      for ( pActor = &pActors[v11]; v12 < (signed int)uNumActors; ++pActor )
      {
        pActor->PrepareSprites(0);
        ++v12;
        pActor->uYawAngle = v15.uYawAngle;
        pActor->dword_000334_unique_name = uUniqueName;
      }
    }
  }
}

//----- (00448DF8) --------------------------------------------------------
void __fastcall EventCastSpell(int spellnum, int uSkillLevel, int uSkill, int fromx, int fromy, int fromz, int tox, int toy, int toz)//sub_448DF8
{
  int v9; // esi@1
  double v10; // st7@4
  double v11; // st6@4
  double v12; // st5@4
  double v13; // st7@6
  int v14; // ST44_4@7
  signed int v15; // ebx@9
  signed int v16; // edx@15
  char *v17; // ecx@16
  unsigned __int16 v18; // ax@20
  char *v19; // ecx@31
  int v20; // edx@35
  signed int v21; // edx@37
  char *v22; // ecx@38
  unsigned __int16 v23; // ax@41
  int i; // esi@42
  signed int v25; // edx@55
  char *v26; // ecx@56
  unsigned __int16 v27; // ax@59
  int j; // esi@60
  signed int v29; // edx@66
  char *v30; // ecx@67
  unsigned __int16 v31; // ax@70
  //Player *v32; // eax@80
  //unsigned __int16 v33; // si@85
  int v34; // eax@96
  int v35; // eax@97
  unsigned __int64 v36; // qax@99
  SpellBuff *v37; // ecx@99
  int v38; // esi@103
  signed __int64 v39; // qax@105
  int v40; // ebx@108
  int v41; // ebx@109
  int v42; // esi@111
  int v43; // ebx@111
  int v44; // eax@117
  //unsigned __int16 v45; // si@137
  unsigned __int16 v46; // [sp-8h] [bp-BCh]@99
  int v47; // [sp-4h] [bp-B8h]@35
  unsigned __int16 v48; // [sp-4h] [bp-B8h]@99
  int v49; // [sp+0h] [bp-B4h]@35
  int v50; // [sp+0h] [bp-B4h]@99
  int v51; // [sp+4h] [bp-B0h]@35
  unsigned __int8 v52; // [sp+4h] [bp-B0h]@99
  float v53; // [sp+14h] [bp-A0h]@4
  float v54; // [sp+18h] [bp-9Ch]@4
  int v55; // [sp+28h] [bp-8Ch]@7
  unsigned int yaw; // [sp+30h] [bp-84h]@7
  int pitch; // [sp+34h] [bp-80h]@7
  //SpriteObject a1; // [sp+38h] [bp-7Ch]@12
  int v59; // [sp+A8h] [bp-Ch]@1
  int v60; // [sp+ACh] [bp-8h]@1
  //int spellnum_; // [sp+B0h] [bp-4h]@1
  //signed int levela; // [sp+BCh] [bp+8h]@80
  int a6_4; // [sp+C8h] [bp+14h]@117
  float a7a; // [sp+CCh] [bp+18h]@6
  signed int a7b; // [sp+CCh] [bp+18h]@12
  int a7c; // [sp+CCh] [bp+18h]@29
  int a7d; // [sp+CCh] [bp+18h]@55
  float a8a; // [sp+D0h] [bp+1Ch]@6
  int a8b; // [sp+D0h] [bp+1Ch]@37
  int a8c; // [sp+D0h] [bp+1Ch]@55
  float toza; // [sp+D4h] [bp+20h]@6

  v9 = 0;
  v59 = uSkillLevel + 1;
  //spellnum_ = spellnum;
  v60 = 0;
  if ( tox || toy || toz )
  {
    v10 = (double)tox - (double)fromx;
    v53 = v10;
    v11 = (double)toy - (double)fromy;
    v54 = v11;
    v12 = (double)toz;
  }
  else
  {
    v10 = (double)pParty->vPosition.x - (double)fromx;
    v53 = v10;
    v11 = (double)pParty->vPosition.y - (double)fromy;
    v54 = v11;
    v12 = (double)(pParty->vPosition.z + pParty->sEyelevel);
  }
  a7a = v12 - (double)fromz;
  toza = v11 * v11;
  a8a = v10 * v10;
  v13 = sqrt(a7a * a7a + a8a + toza);
  if ( v13 <= 1.0 )
  {
    LOBYTE(v55) = 1;
    yaw = 0;
    pitch = 0;
  }
  else
  {
    v55 = (signed __int64)v13;
    v14 = (signed __int64)sqrt(a8a + toza);
    yaw = stru_5C6E00->Atan2((signed __int64)v53, (signed __int64)v54);
    pitch = stru_5C6E00->Atan2(v14, (signed __int64)a7a);
  }
  v15 = v59;
  if ( v59 <= 0 || v59 > 4 )
    v15 = 1;
  a7b = v15;

  SpriteObject a1; // [sp+38h] [bp-7Ch]@12
  //SpriteObject::SpriteObject(&a1);

  a1.uType = stru_4E3ACC[spellnum].field_0;
  if ( spellnum > 58 )
  {
    if ( spellnum == 69 )
      goto LABEL_117;
    if ( spellnum != 83 )
      return;
    v40 = v15 - 2;
    if ( v40 )
    {
      v41 = v40 - 1;
      if ( !v41 )
      {
        v42 = 14400 * uSkill;
        v43 = 4 * uSkill + 10;
        pGame->pStru6Instance->SetPlayerBuffAnim(0x53u, 0);
        pGame->pStru6Instance->SetPlayerBuffAnim(0x53u, 1u);
        pGame->pStru6Instance->SetPlayerBuffAnim(0x53u, 2u);
        pGame->pStru6Instance->SetPlayerBuffAnim(0x53u, 3u);
        v39 = (signed __int64)((double)(v42 << 7) * 0.033333335);
        v37 = &pParty->pPartyBuffs[2];
        v36 = pParty->uTimePlayed + v39;
        v37->Apply(v36, a7b, v43, 0, 0);
        goto LABEL_139;
      }
      if ( v41 == 1 )
      {
        v42 = 18000 * uSkill;
        v43 = 5 * uSkill + 10;
       pGame->pStru6Instance->SetPlayerBuffAnim(0x53u, 0);
       pGame->pStru6Instance->SetPlayerBuffAnim(0x53u, 1u);
       pGame->pStru6Instance->SetPlayerBuffAnim(0x53u, 2u);
       pGame->pStru6Instance->SetPlayerBuffAnim(0x53u, 3u);
       v39 = (signed __int64)((double)(v42 << 7) * 0.033333335);
       v37 = &pParty->pPartyBuffs[2];
       v36 = pParty->uTimePlayed + v39;
       v37->Apply(v36, a7b, v43, 0, 0);
       goto LABEL_139;
      }
    }
    v42 = 10800 * uSkill;
    v43 = 3 * uSkill + 10;
    pGame->pStru6Instance->SetPlayerBuffAnim(0x53u, 0);
    pGame->pStru6Instance->SetPlayerBuffAnim(0x53u, 1u);
    pGame->pStru6Instance->SetPlayerBuffAnim(0x53u, 2u);
    pGame->pStru6Instance->SetPlayerBuffAnim(0x53u, 3u);
    v39 = (signed __int64)((double)(v42 << 7) * 0.033333335);
    v37 = &pParty->pPartyBuffs[2];
    v36 = pParty->uTimePlayed + v39;
    v37->Apply(v36, a7b, v43, 0, 0);
    goto LABEL_139;
  }
  if ( spellnum != 58 )
  {
    switch ( spellnum )
    {
      case 2:
      case 6:
      case 18:
      case 26:
      case 29:
      case 32:
      case 39:
      case 41:
        a1.stru_24.Reset();
        v16 = 0;
        a1.spell_id = spellnum;
        a1.spell_level = uSkill;
        a1.spell_skill = v15;
        if ( (signed int)pObjectList->uNumObjects <= 0 )
        {
          v18 = 0;
          a1.uObjectDescID = v18;
          *(_QWORD *)&a1.vPosition.y = __PAIR__(fromz, fromy);
          a1.vPosition.x = fromx;
          a1.uAttributes = 16;
          a1.uSectorID = pIndoor->GetSector(fromx, fromy, fromz);
          a1.field_60_distance_related_prolly_lod = v55;
          v20 = yaw;
          a1.uSpriteFrameID = 0;
          a1.spell_caster_pid = 8000 | OBJECT_Item;
          a1.spell_target_pid = 0;
          a1.uFacing = yaw;
          a1.uSoundID = 0;
          v49 = pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed;
          a1.Create(v20, pitch, v49, 0);
          goto LABEL_139;
        }
        v17 = (char *)&pObjectList->pObjects->uObjectID;
        while ( (short)a1.uType != *(short *)v17 )
        {
          ++v16;
          v17 += 56;
          if ( v16 >= (signed int)pObjectList->uNumObjects )
          {
            v18 = 0;
            a1.uObjectDescID = v18;
            *(_QWORD *)&a1.vPosition.y = __PAIR__(fromz, fromy);
            a1.vPosition.x = fromx;
            a1.uAttributes = 16;
            a1.uSectorID = pIndoor->GetSector(fromx, fromy, fromz);
            a1.field_60_distance_related_prolly_lod = v55;
            v20 = yaw;
            a1.uSpriteFrameID = 0;
            a1.spell_caster_pid = 8000 | OBJECT_Item;
            a1.spell_target_pid = 0;
            a1.uFacing = yaw;
            a1.uSoundID = 0;
            v49 = pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed;
            a1.Create(v20, pitch, v49, 0);
            goto LABEL_139;
          }
        }
        v18 = v16;
        a1.uObjectDescID = v18;
        *(_QWORD *)&a1.vPosition.y = __PAIR__(fromz, fromy);
        a1.vPosition.x = fromx;
        a1.uAttributes = 16;
        a1.uSectorID = pIndoor->GetSector(fromx, fromy, fromz);
        a1.field_60_distance_related_prolly_lod = v55;
        v20 = yaw;
        a1.uSpriteFrameID = 0;
        a1.spell_caster_pid = 8000 | OBJECT_Item;
        a1.spell_target_pid = 0;
        a1.uFacing = yaw;
        a1.uSoundID = 0;
        v49 = pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed;
        a1.Create(v20, pitch, v49, 0);
        goto LABEL_139;
      case 24:
        switch ( v15 )
        {
          case 1:
            v60 = 1;
            break;
          case 2:
            v60 = 3;
            break;
          case 3:
            v60 = 5;
            break;
          case 4:
            v60 = 7;
            break;
        }
        a7c = (signed int)(60 * stru_5C6E00->uIntegerDoublePi) / 360;
        if ( v60 != 1 )
        {
          a8b = a7c / (v60 - 1);
          a1.stru_24.Reset();
          v21 = 0;
          a1.spell_id = spellnum;
          a1.spell_level = uSkill;
          a1.spell_skill = v15;
          if ( (signed int)pObjectList->uNumObjects <= 0 )
          {
            v23 = 0;
          }
          else
          {
            v22 = (char *)&pObjectList->pObjects->uObjectID;
            while ( (short)a1.uType != *(short *)v22 )
            {
              ++v21;
              v22 += 56;
              if ( v21 >= (signed int)pObjectList->uNumObjects )
              {
                v23 = 0;
                a1.uObjectDescID = v23;
                *(_QWORD *)&a1.vPosition.y = __PAIR__(fromz, fromy);
                a1.vPosition.x = fromx;
                a1.uAttributes = 16;
                a1.uSectorID = pIndoor->GetSector(fromx, fromy, fromz);
                a1.field_60_distance_related_prolly_lod = v55;
                a1.uSpriteFrameID = 0;
                a1.spell_caster_pid = 8000 | OBJECT_Item;
                a1.spell_target_pid = 4;
                a1.uSoundID = 0;
                for ( i = a7c / -2; i <= a7c / 2; i += a8b )
                {
                  a1.uFacing = i + yaw;
                  a1.Create((signed __int16)(i + (short)yaw), pitch, pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed, 0);
                }
                goto LABEL_139;
              }
            }
            v23 = v21;
          }
          a1.uObjectDescID = v23;
          *(_QWORD *)&a1.vPosition.y = __PAIR__(fromz, fromy);
          a1.vPosition.x = fromx;
          a1.uAttributes = 16;
          a1.uSectorID = pIndoor->GetSector(fromx, fromy, fromz);
          a1.field_60_distance_related_prolly_lod = v55;
          a1.uSpriteFrameID = 0;
          a1.spell_caster_pid = 8000 | OBJECT_Item;
          a1.spell_target_pid = 4;
          a1.uSoundID = 0;
          for ( i = a7c / -2; i <= a7c / 2; i += a8b )
          {
            a1.uFacing = i + yaw;
            a1.Create((signed __int16)(i + (short)yaw), pitch, pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed, 0);
          }
          goto LABEL_139;
        }
        a1.stru_24.Reset();
        v16 = 0;
        a1.spell_id = spellnum;
        a1.spell_level = uSkill;
        a1.spell_skill = v15;
        if ( (signed int)pObjectList->uNumObjects <= 0 )
       {
         v18 = 0;
         a1.uObjectDescID = v18;
         *(_QWORD *)&a1.vPosition.y = __PAIR__(fromz, fromy);
         a1.vPosition.x = fromx;
         a1.uAttributes = 16;
         a1.uSectorID = pIndoor->GetSector(fromx, fromy, fromz);
         a1.field_60_distance_related_prolly_lod = v55;
         v20 = yaw;
         a1.uSpriteFrameID = 0;
         a1.spell_caster_pid = 8000 | OBJECT_Item;
         a1.spell_target_pid = 0;
         a1.uFacing = yaw;
         a1.uSoundID = 0;
         v51 = 0;
         v49 = pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed;
         v47 = pitch;
         a1.Create(v20, v47, v49, v51);
         goto LABEL_139;
       }
        v19 = (char *)&pObjectList->pObjects->uObjectID;
        do
        {
          if ( (short)a1.uType == *(short *)v19 )
          {
            v18 = v16;
            a1.uObjectDescID = v18;
            *(_QWORD *)&a1.vPosition.y = __PAIR__(fromz, fromy);
            a1.vPosition.x = fromx;
            a1.uAttributes = 16;
            a1.uSectorID = pIndoor->GetSector(fromx, fromy, fromz);
            a1.field_60_distance_related_prolly_lod = v55;
            v20 = yaw;
            a1.uSpriteFrameID = 0;
            a1.spell_caster_pid = 8000 | OBJECT_Item;
            a1.spell_target_pid = 0;
            a1.uFacing = yaw;
            a1.uSoundID = 0;
            v51 = 0;
            v49 = pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed;
            v47 = pitch;
            a1.Create(v20, v47, v49, v51);
            goto LABEL_139;
          }
          ++v16;
          v19 += 56;
        }
        while ( v16 < (signed int)pObjectList->uNumObjects );
        v18 = 0;
        a1.uObjectDescID = v18;
        *(_QWORD *)&a1.vPosition.y = __PAIR__(fromz, fromy);
        a1.vPosition.x = fromx;
        a1.uAttributes = 16;
        a1.uSectorID = pIndoor->GetSector(fromx, fromy, fromz);
        a1.field_60_distance_related_prolly_lod = v55;
        v20 = yaw;
        a1.uSpriteFrameID = 0;
        a1.spell_caster_pid = 8000 | OBJECT_Item;
        a1.spell_target_pid = 0;
        a1.uFacing = yaw;
        a1.uSoundID = 0;
        v51 = 0;
        v49 = pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed;
        v47 = pitch;
        a1.Create(v20, v47, v49, v51);
        goto LABEL_139;
      case 15:
        switch ( v15 )
        {
          case 1:
            v60 = 3;
            break;
          case 2:
            v60 = 5;
            break;
          case 3:
            v60 = 7;
            break;
          case 4:
            v60 = 9;
            break;
        }
        a7d = (signed int)(60 * stru_5C6E00->uIntegerDoublePi) / 360;
        a8c = (signed int)(60 * stru_5C6E00->uIntegerDoublePi) / 360 / (v60 - 1);
        a1.stru_24.Reset();
        v25 = 0;
        a1.spell_id = spellnum;
        a1.spell_level = uSkill;
        a1.spell_skill = v15;
        if ( (signed int)pObjectList->uNumObjects <= 0 )
        {
          v27 = 0;
          a1.uObjectDescID = v27;
          *(_QWORD *)&a1.vPosition.y = __PAIR__(fromz, fromy);
          a1.vPosition.x = fromx;
          a1.uAttributes = 16;
          a1.uSectorID = pIndoor->GetSector(fromx, fromy, fromz);
          a1.field_60_distance_related_prolly_lod = v55;
          a1.uSpriteFrameID = 0;
          a1.spell_caster_pid = 8000 | OBJECT_Item;
          a1.spell_target_pid = 4;
          a1.uSoundID = 0;
          for ( j = a7d / -2; j <= a7d / 2; j += a8c )
          {
            a1.uFacing = j + yaw;
            a1.Create((signed __int16)(j + (short)yaw), pitch, pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed, 0);
          }
          goto LABEL_139;
        }
        v26 = (char *)&pObjectList->pObjects->uObjectID;
        while ( (short)a1.uType != *(short *)v26 )
        {
          ++v25;
          v26 += 56;
          if ( v25 >= (signed int)pObjectList->uNumObjects )
          {
            v27 = 0;
            a1.uObjectDescID = v27;
            *(_QWORD *)&a1.vPosition.y = __PAIR__(fromz, fromy);
            a1.vPosition.x = fromx;
            a1.uAttributes = 16;
            a1.uSectorID = pIndoor->GetSector(fromx, fromy, fromz);
            a1.field_60_distance_related_prolly_lod = v55;
            a1.uSpriteFrameID = 0;
            a1.spell_caster_pid = 8000 | OBJECT_Item;
            a1.spell_target_pid = 4;
            a1.uSoundID = 0;
            for ( j = a7d / -2; j <= a7d / 2; j += a8c )
            {
              a1.uFacing = j + yaw;
              a1.Create((signed __int16)(j + (short)yaw), pitch, pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed, 0);
            }
            goto LABEL_139;
          }
        }
        v27 = v25;
        a1.uObjectDescID = v27;
        *(_QWORD *)&a1.vPosition.y = __PAIR__(fromz, fromy);
        a1.vPosition.x = fromx;
        a1.uAttributes = 16;
        a1.uSectorID = pIndoor->GetSector(fromx, fromy, fromz);
        a1.field_60_distance_related_prolly_lod = v55;
        a1.uSpriteFrameID = 0;
        a1.spell_caster_pid = 8000 | OBJECT_Item;
        a1.spell_target_pid = 4;
        a1.uSoundID = 0;
        for ( j = a7d / -2; j <= a7d / 2; j += a8c )
        {
          a1.uFacing = j + yaw;
          a1.Create(
            (signed __int16)(j + (short)yaw),
            pitch,
            pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed,
            0);
        }
        goto LABEL_139;
      case 43:
        if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
          return;
        a1.stru_24.Reset();
        v29 = 0;
        a1.spell_id = spellnum;
        a1.spell_level = uSkill;
        a1.spell_skill = v15;
        if ( (signed int)pObjectList->uNumObjects <= 0 )
        {
          v31 = 0;
          a1.uObjectDescID = v31;
          *(_QWORD *)&a1.vPosition.y = __PAIR__(fromz, fromy);
          a1.vPosition.x = fromx;
          a1.uAttributes = 16;
          a1.uSectorID = pIndoor->GetSector(fromx, fromy, fromz);
          a1.field_60_distance_related_prolly_lod = v55;
          a1.uSpriteFrameID = 0;
          a1.spell_caster_pid = 8000 | OBJECT_Item;
          a1.spell_target_pid = 4;
          a1.uSoundID = 0;
          v51 = 0;
          v49 = pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed;
          v20 = yaw;
          v47 = (signed int)stru_5C6E00->uIntegerHalfPi / 2;
          a1.Create(v20, v47, v49, v51);
          goto LABEL_139;
        }
        v30 = (char *)&pObjectList->pObjects->uObjectID;
        break;

      case SPELL_FIRE_HASTE:
        if ( v15 > 0 )
        {
          if ( v15 <= 2 )
          {
            v9 = 60 * (uSkill + 60);
          }
          else
          {
            if ( v15 == 3 )
            {
              v9 = 180 * (uSkill + 20);
            }
            else
            {
              if ( v15 == 4 )
                v9 = 240 * (uSkill + 15);
            }
          }
        }
        //levela = 1;
        //v32 = pParty->pPlayers;//[0].pConditions[1];
        //do
        for (uint i = 0; i < 4; ++i)
          if (pParty->pPlayers[i].pConditions[Player::Condition_Weak])
            return;
		//while ( v32 <= &pParty->pPlayers[3] );
        //if ( !levela )
        //  return;
        pParty->pPartyBuffs[PARTY_BUFF_HASTE].Apply(pParty->uTimePlayed + (signed int)(signed __int64)((double)(v9 * 128) * 0.033333335),
          v15,
          0,
          0,
          0);
        //v33 = spellnum_;
        pGame->pStru6Instance->SetPlayerBuffAnim(spellnum, 0);
        pGame->pStru6Instance->SetPlayerBuffAnim(spellnum, 1);
        pGame->pStru6Instance->SetPlayerBuffAnim(spellnum, 2);
        pGame->pStru6Instance->SetPlayerBuffAnim(spellnum, 3);
        goto LABEL_138;
      case 17:
      case 38:
      case 51:
        switch ( v15 )
        {
          case 1:
          case 2:
            v9 = 300 * (uSkill + 12);
            break;
          case 3:
            v9 = 900 * (uSkill + 4);
            break;
          case 4:
            v9 = 3600 * (uSkill + 1);
            break;
        }
        switch ( spellnum )
        {
          case 17:
            v60 = 0;
            uSkill = 14;
            break;
          case 38:
            v35 = uSkill + 5;
            uSkill = 15;
            v60 = v35;
            break;
          case 51:
            v34 = uSkill + 5;
            uSkill = 9;
            v60 = v34;
            break;
        }
        pGame->pStru6Instance->SetPlayerBuffAnim(spellnum, 0);
        pGame->pStru6Instance->SetPlayerBuffAnim(spellnum, 1);
        pGame->pStru6Instance->SetPlayerBuffAnim(spellnum, 2);
        pGame->pStru6Instance->SetPlayerBuffAnim(spellnum, 3);
        v52 = 0;
        v50 = 0;
        v48 = v60;
        v46 = v15;
        v36 = pParty->uTimePlayed + (signed int)(signed __int64)((double)(v9 << 7) * 0.033333335);
        v37 = &pParty->pPartyBuffs[uSkill];
        v37->Apply(v36, v46, v48, v50, v52);
        goto LABEL_139;;
      case 8:
        if ( v15 == 2 || v15 == 3 || v15 != 4 )
          v38 = 60 * uSkill;
        else
          v38 = 600 * uSkill;
        pGame->pStru6Instance->SetPlayerBuffAnim(spellnum, 0);
        pGame->pStru6Instance->SetPlayerBuffAnim(spellnum, 1);
        pGame->pStru6Instance->SetPlayerBuffAnim(spellnum, 2);
        pGame->pStru6Instance->SetPlayerBuffAnim(spellnum, 3);
        v52 = 0;
        v50 = 0;
        v48 = uSkill;
        v46 = v15;
        v39 = (signed __int64)((double)(v38 << 7) * 0.033333335);
        v37 = &pParty->pPartyBuffs[10];
        v36 = pParty->uTimePlayed + v39;
        v37->Apply(v36, v46, v48, v50, v52);
        goto LABEL_139;
      case 3:
      case 14:
      case 25:
      case 36:
        goto LABEL_117;
      default:
        return;
    }
    while ( (short)a1.uType != *(short *)v30 )
    {
      ++v29;
      v30 += 56;
      if ( v29 >= (signed int)pObjectList->uNumObjects )
      {
        v31 = 0;
        a1.uObjectDescID = v31;
        *(_QWORD *)&a1.vPosition.y = __PAIR__(fromz, fromy);
        a1.vPosition.x = fromx;
        a1.uAttributes = 16;
        a1.uSectorID = pIndoor->GetSector(fromx, fromy, fromz);
        a1.field_60_distance_related_prolly_lod = v55;
        a1.uSpriteFrameID = 0;
        a1.spell_caster_pid = 8000 | OBJECT_Item;
        a1.spell_target_pid = 4;
        a1.uSoundID = 0;
        v51 = 0;
        v49 = pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed;
        v20 = yaw;
        v47 = (signed int)stru_5C6E00->uIntegerHalfPi / 2;
        a1.Create(v20, v47, v49, v51);
        goto LABEL_139;
      }
    }
    v31 = v29;
    a1.uObjectDescID = v31;
    *(_QWORD *)&a1.vPosition.y = __PAIR__(fromz, fromy);
    a1.vPosition.x = fromx;
    a1.uAttributes = 16;
    a1.uSectorID = pIndoor->GetSector(fromx, fromy, fromz);
    a1.field_60_distance_related_prolly_lod = v55;
    a1.uSpriteFrameID = 0;
    a1.spell_caster_pid = 8000 | OBJECT_Item;
    a1.spell_target_pid = 4;
    a1.uSoundID = 0;
    v51 = 0;
    v49 = pObjectList->pObjects[(signed __int16)a1.uObjectDescID].uSpeed;
    v20 = yaw;
    v47 = (signed int)stru_5C6E00->uIntegerHalfPi / 2;
    a1.Create(v20, v47, v49, v51);
    goto LABEL_139;
  }
LABEL_117:
  v44 = uSkill;
  a6_4 = 3600 * uSkill;
  if ( v15 == 1 )
  {
    v60 = v44;
    goto LABEL_125;
  }
  if ( v15 == 2 )
  {
    v44 = 2 * uSkill;
    v60 = v44;
    goto LABEL_125;
  }
  if ( v15 == 3 )
  {
    v44 = 3 * uSkill;
    v60 = v44;
    goto LABEL_125;
  }
  if ( v15 == 4 )
  {
    v44 = 4 * uSkill;
    v60 = v44;
    goto LABEL_125;
  }
LABEL_125:
  switch ( spellnum )
  {
    case 3:
      uSkill = 6;
      break;
    case 14:
      uSkill = 0;
      break;
    case 25:
      uSkill = 17;
      break;
    case 36:
      uSkill = 4;
      break;
    case 58:
      uSkill = 12;
      break;
    case 69:
      uSkill = 1;
      break;
  }
  //v45 = spellnum_;
  pGame->pStru6Instance->SetPlayerBuffAnim(spellnum, 0);
  pGame->pStru6Instance->SetPlayerBuffAnim(spellnum, 1);
  pGame->pStru6Instance->SetPlayerBuffAnim(spellnum, 2);
  pGame->pStru6Instance->SetPlayerBuffAnim(spellnum, 3);
  pParty->pPartyBuffs[uSkill].Apply(pParty->uTimePlayed + (signed int)(signed __int64)((double)a6_4 * 4.2666669), v15, v60, 0, 0);
  //levela = 1;
LABEL_138:
  //if ( levela )
LABEL_139:
    pAudioPlayer->PlaySound((SoundID)word_4EE088_sound_ids[spellnum], 0, 0, fromx, fromy, 0, 0, 0);
}
// 4EE088: using guessed type __int16 word_4EE088_sound_ids[];

//----- (0044987B) --------------------------------------------------------
void sub_44987B(const char *pMapName, MapStartPoint start_point)
{
  const char *v2; // edi@1

  v2 = pMapName;
  pAudioPlayer->StopChannels(-1, -1);
  pGameLoadingUI_ProgressBar->Initialize(GUIProgressBar::TYPE_None);
  if ( _strcmpi(pCurrentMapName, v2) )
    SaveGame(1, 0);

  uGameState = 2;
  strcpy(pCurrentMapName, v2);
  uLevel_StartingPointType = start_point;
}
// 6BE35C: using guessed type int uLevel_StartingPointType;

//----- (004498D5) --------------------------------------------------------
void TeleportToStartingPoint(MapStartPoint point)
{
  //unsigned int v1; // ecx@2
  //int v2; // ecx@3
  //int v3; // ecx@4
  unsigned __int16 v4; // ax@11
  signed int v5; // ecx@12
  LevelDecoration *v6; // edx@13
  signed int v7; // ecx@17
  int v8; // eax@17
  int v9; // ecx@17
  const char *v10; // [sp-4h] [bp-84h]@6
  char pName[128]; // [sp+8h] [bp-78h]@11

  switch (point)
  {
    case MapStartPoint_Party: v10 = "Party Start"; break;
    case MapStartPoint_North: v10 = "North Start"; break;
    case MapStartPoint_South: v10 = "South Start"; break;
    case MapStartPoint_East: v10 = "East Start";  break;
    case MapStartPoint_West: v10 = "West Start";  break;
  }

  strcpy(pName, v10);
  v4 = pDecorationList->GetDecorIdByName(pName);
  if ( v4 )
  {
    v5 = 0;
    if ( (signed int)uNumLevelDecorations > 0 )
    {
      v6 = pLevelDecorations;
      while ( v6->uDecorationDescID != (signed __int16)v4 )
      {
        ++v5;
        ++v6;
        if ( v5 >= (signed int)uNumLevelDecorations )
          goto LABEL_20;
      }
      v7 = v5;
      pParty->vPosition.x = pLevelDecorations[v7].vPosition.x;
      pParty->vPosition.y = pLevelDecorations[v7].vPosition.y;
      pParty->vPosition.z = pLevelDecorations[v7].vPosition.z;
      pParty->uFallStartY = pParty->vPosition.z;
      v8 = (signed int)(stru_5C6E00->uIntegerHalfPi * pLevelDecorations[v7].field_1A) / 90;
      v9 = pLevelDecorations[v7].field_10_y_rot;
      pParty->sRotationY = v8;
      if ( v9 )
        pParty->sRotationY = v9;
      pParty->sRotationX = 0;
      pParty->uFallSpeed = 0;
    }
LABEL_20:
    if ( dword_5B65C0 )
    {
      if ( _5B65A8_npcdata_uflags_or_other )
        pParty->vPosition.x = _5B65A8_npcdata_uflags_or_other;
      if ( _5B65AC_npcdata_fame_or_other )
        pParty->vPosition.y = _5B65AC_npcdata_fame_or_other;
      if ( _5B65B0_npcdata_rep_or_other )
      {
        pParty->vPosition.z = _5B65B0_npcdata_rep_or_other;
        pParty->uFallStartY = _5B65B0_npcdata_rep_or_other;
      }
      if ( _5B65B4_npcdata_loword_house_or_other )
        pParty->sRotationY = _5B65B4_npcdata_loword_house_or_other;
      if ( _5B65B8_npcdata_hiword_house_or_other )
        pParty->sRotationX = _5B65B8_npcdata_hiword_house_or_other;
      if ( dword_5B65BC )
        pParty->uFallSpeed = dword_5B65BC;
    }
    _5B65B4_npcdata_loword_house_or_other = -1;
    dword_5B65C0 = 0;
    dword_5B65BC = 0;
    _5B65B8_npcdata_hiword_house_or_other = 0;
    _5B65B0_npcdata_rep_or_other = 0;
    _5B65AC_npcdata_fame_or_other = 0;
    _5B65A8_npcdata_uflags_or_other = 0;
  }
}
// 5B65A8: using guessed type int _5B65A8_npcdata_uflags_or_other;
// 5B65AC: using guessed type int _5B65AC_npcdata_fame_or_other;
// 5B65B0: using guessed type int _5B65B0_npcdata_rep_or_other;
// 5B65B4: using guessed type int _5B65B4_npcdata_loword_house_or_other;
// 5B65B8: using guessed type int _5B65B8_npcdata_hiword_house_or_other;
// 5B65BC: using guessed type int dword_5B65BC;
// 5B65C0: using guessed type int dword_5B65C0;

//----- (00449A49) --------------------------------------------------------
__int16 __fastcall sub_449A49_door_switch_animation(unsigned int uDoorID, int a2)
{
  int v2; // eax@1
  int v3; // ebx@1
  signed int v4; // esi@2
  int v5; // edx@2
  BLVDoor *v6; // ecx@8
  unsigned int v7; // edx@18
  signed int v8; // esi@19
  int v9; // eax@19
  char Args; // [sp+Ch] [bp-78h]@6

  LOWORD(v2) = LOWORD(pIndoor->pDoors);
  v3 = a2;
  if ( !pIndoor->pDoors )
    return v2;
  v4 = 0;
  v5 = (int)&pIndoor->pDoors->uDoorID;
  do
  {
    if ( *(int *)v5 == uDoorID )
      break;
    ++v4;
    v5 += 80;
  }
  while ( v4 < 200 );
  if ( v4 >= 200 )
  {
    sprintf(&Args, "Unable to find Door ID: %i!", uDoorID);
    Abortf(&Args);
  }
  v6 = &pIndoor->pDoors[v4];
  if ( v3 == 2 )
  {
    LOWORD(v2) = v6->uState;
    if ( (short)v2 == 3 || (short)v2 == 1 )
      return v2;
    if ( (short)v2 )
      goto LABEL_14;
  }
  else
  {
    if ( !v3 )
    {
LABEL_14:
      LOWORD(v2) = v6->uState;
      if ( (short)v2 && (short)v2 != 3 )
      {
        v6->uState = BLVDoor::Closing;
        if ( (short)v2 == 2 )
        {
LABEL_17:
          v6->uTimeSinceTriggered = 0;
          return v2;
        }
        v7 = v6->uTimeSinceTriggered;
        v2 = 15360;
        if ( v7 != 15360 )
        {
          v8 = v6->uOpenSpeed;
          v9 = v6->uCloseSpeed;
LABEL_26:
          v2 = (v6->uMoveLength << 7) / v8 - ((signed int)(v7 * v9) / 128 << 7) / v8;
          goto LABEL_27;
        }
        goto LABEL_27;
      }
      return v2;
    }
    if ( v3 != 1 )
      return v2;
  }
  LOWORD(v2) = v6->uState;
  if ( (short)v2 != 2 && (short)v2 != 1 )
  {
    v6->uState = BLVDoor::Opening;
    if ( !(short)v2 )
      goto LABEL_17;
    v7 = v6->uTimeSinceTriggered;
    v2 = 15360;
    if ( v7 != 15360 )
    {
      v8 = v6->uCloseSpeed;
      v9 = v6->uOpenSpeed;
      goto LABEL_26;
    }
LABEL_27:
    v6->uTimeSinceTriggered = v2;
  }
  return v2;
}

//----- (00449B57) --------------------------------------------------------
bool _449B57_test_bit( unsigned __int8 *a1, __int16 a2 )
    {
  return a1[(a2 - 1) >> 3] & (0x80u >> (a2 - 1) % 8);
}

//----- (00449B7E) --------------------------------------------------------
void _449B7E_toggle_bit(unsigned char *pArray, __int16 a2, unsigned __int16 bToggle)
{
  signed int v3; // esi@1
  unsigned char set_bit; // edx@1

  v3 = a2 - 1;
  set_bit = 0x80 >> v3 % 8;
  if ( bToggle )
    pArray[v3 / 8] |=  set_bit;
  else
    pArray[v3 / 8] &= ~set_bit;
}

//----- (0044A56A) --------------------------------------------------------
void __cdecl Party__CountHirelings()
{
  pParty->field_70A = 0;

  for (int i = 0; i < pNPCStats->uNumNewNPCs; ++i)
  {
    auto npc = pNPCStats->pNewNPCData + i;
    if (npc->Hired() &&
        (!pParty->pHirelings[0].pName || strcmp(npc->pName, pParty->pHirelings[0].pName)))
    {
      if (!pParty->pHirelings[1].pName || strcmp(npc->pName, pParty->pHirelings[1].pName))
        ++pParty->field_70A;
    }
  }
}

//----- (0044C175) --------------------------------------------------------
void __fastcall ShowStatusBarString(const char *pString, unsigned int uNumSeconds)
{
  unsigned int v2; // esi@1
  int i; // eax@1

  v2 = uNumSeconds;
  strcpy(GameUI_Footer_TimedString, pString);
  GameUI_Footer_TimeLeft = 1000 * v2 + GetTickCount();
  for ( i = pFontLucida->GetLineWidth(GameUI_Footer_TimedString);
        i > 450;
        i = pFontLucida->GetLineWidth(GameUI_Footer_TimedString) )
    byte_5C3427[strlen(GameUI_Footer_TimedString)] = 0;
}

//----- (0044C1D0) --------------------------------------------------------
void __cdecl ShowNothingHereStatus()
{
  if ( !GameUI_Footer_TimeLeft )
    ShowStatusBarString(pGlobalTXT_LocalizationStrings[521], 2u);// Nothing here
}

//----- (0044C28B) --------------------------------------------------------
signed int __cdecl const_2()
{
  return 2;
}

//----- (0044C28F) --------------------------------------------------------
bool __cdecl sub_44C28F_open_nwc_dungeon()
{
  bool result; // eax@1

  result = _strcmpi("nwc.blv", pCurrentMapName);
  if ( result )
  {
    _5B65A8_npcdata_uflags_or_other = 0;
    _5B65AC_npcdata_fame_or_other = 0;
    _5B65B0_npcdata_rep_or_other = 0;
    _5B65B4_npcdata_loword_house_or_other = 0;
    _5B65B8_npcdata_hiword_house_or_other = 0;
    dword_5B65BC = 0;
    dword_5B65C0 = 0;
    pGameLoadingUI_ProgressBar->uType = GUIProgressBar::TYPE_Fullscreen;
    sub_44987B("nwc.blv", MapStartPoint_Party);
    pCurrentScreen = SCREEN_GAME;
    result = 1;
  }
  return result;
}

//----- (0044C2F4) --------------------------------------------------------
int LevelDecoration::IsInteractive()
{
  signed int v1; // eax@1

  v1 = this->uDecorationDescID;
  if ( v1 > 34 )
  {
    if ( v1 == 184 || v1 == 187 || v1 == 190 || v1 > 205 && v1 <= 221 )
      return 1;
  }
  else
  {
    if ( v1 == 34 || v1 >= 4 && (v1 <= 6 || v1 == 11 || v1 > 12 && (v1 <= 14 || v1 == 24)) )
      return 1;
  }
  return 0;
}

//----- (0044C362) --------------------------------------------------------
void Vec3_int_::Normalize_float()
{
  Vec3_int_ *v1; // esi@1
  double v2; // st6@1
  float v3; // ST20_4@1
  double v4; // st5@1
  float v5; // ST18_4@1
  double v6; // st4@1
  float v7; // ST14_4@1
  float v8; // ST24_4@1
  float v9; // ST20_4@1
  double v10; // ST0C_8@1
  float v11; // ST18_4@1
  double v12; // ST0C_8@1
  float v13; // ST14_4@1
  double v14; // ST0C_8@1

  v1 = this;
  v2 = (double)this->x * 0.000015258789;
  v3 = v2;
  v4 = (double)this->y * 0.000015258789;
  v5 = v4;
  v6 = (double)this->z * 0.000015258789;
  v7 = v6;
  v8 = 1.0 / sqrt(v6 * v6 + v4 * v4 + v2 * v2);
  v9 = v8 * v3 * 65536.0;
  v10 = v9 + 6.7553994e15;
  v1->x = LODWORD(v10);
  v11 = v8 * v5 * 65536.0;
  v12 = v11 + 6.7553994e15;
  v1->y = LODWORD(v12);
  v13 = v8 * v7 * 65536.0;
  v14 = v13 + 6.7553994e15;
  v1->z = LODWORD(v14);
}

//----- (00401000) --------------------------------------------------------
void __stdcall mm7__vector_constructor(void *a1, int objSize, int numObjs, int (__thiscall *constructor)(int))
{
  void *v4; // esi@2
  int v5; // edi@2

  if ( numObjs - 1 >= 0 )
  {
    v4 = a1;
    v5 = numObjs;
    do
    {
      constructor((int)v4);
      v4 = (char *)v4 + objSize;
      --v5;
    }
    while ( v5 );
  }
}

//----- (004014E6) --------------------------------------------------------
void MakeActorAIList_ODM()
{
  int v1; // eax@4
  int v2; // ebx@4
  unsigned int v3; // ecx@4
  int v4; // edx@5
  int v5; // edx@7
  unsigned int v6; // edx@9
  unsigned int v7; // ST20_4@10
  int v9; // edi@10
  int v10; // ebx@14
  int v21; // [sp+Ch] [bp-14h]@4
  int v22; // [sp+10h] [bp-10h]@4

  pParty->uFlags &= 0xFFFFFFCFu;

  ai_arrays_size = 0;
  for (uint i = 0; i < uNumActors; ++i)
  {
    auto actor = pActors + i;

    actor->uAttributes &= 0xFFFFFBFF;
    if (!actor->CanAct())
    {
      actor->uAttributes &= 0xFFFFBFFF;
      continue;
    }

    v22 = abs(pParty->vPosition.z - actor->vPosition.z);
    v21 = abs(pParty->vPosition.y - actor->vPosition.y);
    v1 = abs(pParty->vPosition.x - actor->vPosition.x);
      v2 = v21;
      v3 = v22;
      if ( v1 < v21 )
      {
        v4 = v1;
        v1 = v21;
        v2 = v4;
      }
      if ( v1 < v22 )
      {
        v5 = v1;
        v1 = v22;
        v3 = v5;
      }
      if ( v2 < (signed int)v3 )
      {
        v6 = v3;
        v3 = v2;
        v2 = v6;
      }
      v7 = ((unsigned int)(11 * v2) >> 5) + (v3 >> 2) + v1;
	  //v8 = actor->uActorRadius;
      v9 = v7 - actor->uActorRadius;
      //v23 = v7 - v8;
      if ( v9 < 0 )
      {
        v9 = 0;
        //v23 = 0;
      }

      if (v9 < 5632)
      {
        v10 = actor->uAttributes & 0xFEFFFFFF;
        actor->uAttributes = v10;
        if ( v10 & 0x80000 || actor->GetActorsRelation(0) )
        {
          //v11 = (pParty->uFlags & 0x10) == 0;
          actor->uAttributes = v10 | 0x1000000;
          if (v9 < 5120 )
            pParty->SetYellowAlert();
          if (v9 < 307)
            pParty->SetRedAlert();
        }
		actor->uAttributes |= 0x00004000;
        ai_near_actors_distances[ai_arrays_size] = v9;
        ai_near_actors_ids[ai_arrays_size++] = i;
      }
      else
		  actor->uAttributes &= 0xFFFFBFFF;
  }

  /*
  result = v27;
  if ( v27 > 0 )
  {
    v14 = 0;
    v15 = 1;
    v26 = 1;
    do
    {
      while ( 1 )
      {
        v24 = v15;
        if ( v15 >= result )
          break;
        v16 = ai_near_actors_distances[v14];
        if ( v16 > ai_near_actors_distances[v15] )
        {
          v17 = &ai_near_actors_ids[v15];
          v18 = ai_near_actors_ids[v14];
          ai_near_actors_ids[v14] = *v17;
          *v17 = v18;
          v15 = v24;
          ai_near_actors_distances[v14] = ai_near_actors_distances[v24];
          ai_near_actors_distances[v24] = v16;
        }
        result = v27;
        ++v15;
      }
      ++v14;
      v15 = v26 + 1;
      v26 = v15;
    }
    while ( v15 - 1 < result );
  }*/

  for (uint i = 0; i < ai_arrays_size; ++i)
    for (uint j = 0; j < i; ++j)
      if (ai_near_actors_distances[j] > ai_near_actors_distances[i])
      {
        int tmp = ai_near_actors_distances[j];
        ai_near_actors_distances[j] = ai_near_actors_distances[i];
        ai_near_actors_distances[i] = tmp;

        tmp = ai_near_actors_ids[j];
        ai_near_actors_ids[j] = ai_near_actors_ids[i];
        ai_near_actors_ids[i] = tmp;
      }


  if (ai_arrays_size > 30)
    ai_arrays_size = 30;

  for (uint i = 0; i < ai_arrays_size; ++i)
    pActors[ai_near_actors_ids[i]].uAttributes |= 0x0400;
}
// 4F75D8: using guessed type int ai_arrays_size;

//----- (004016FA) --------------------------------------------------------
int __cdecl MakeActorAIList_BLV()
{
  Actor *v0; // esi@2
  int v1; // eax@4
  int v2; // ebx@4
  unsigned int v3; // ecx@4
  int v4; // edx@5
  int v5; // edx@7
  unsigned int v6; // edx@9
  unsigned int v7; // ST24_4@10
  int v8; // eax@10
  int v9; // edi@10
  int v10; // ebx@14
  char v11; // zf@16
  int v12; // eax@22
  int v13; // edx@24
  int v14; // ecx@25
  int v15; // ebx@26
  unsigned int *v16; // ecx@27
  unsigned int v17; // esi@27
  int v18; // ecx@31
  signed int v19; // edi@31
  Actor *v20; // esi@32
  bool v21; // eax@33
  int v22; // eax@34
  signed int v23; // ebx@36
  Actor *v24; // esi@37
  signed int v25; // eax@40
  int v26; // eax@43
  int v27; // ebx@45
  int j; // edi@45
  unsigned int v29; // eax@46
  int v30; // eax@48
  int v31; // ecx@51
  int v32; // eax@51
  signed int v33; // eax@53
  __int64 v34; // qax@55
  char *v35; // ecx@56
  int v37; // [sp+Ch] [bp-18h]@1
  int v38; // [sp+10h] [bp-14h]@4
  int v39; // [sp+14h] [bp-10h]@4
  int v40; // [sp+18h] [bp-Ch]@10
  int v41; // [sp+18h] [bp-Ch]@29
  int i; // [sp+18h] [bp-Ch]@31
  signed int v43; // [sp+1Ch] [bp-8h]@1
  signed int v44; // [sp+1Ch] [bp-8h]@25
  int v45; // [sp+20h] [bp-4h]@1

//  __debugbreak(); // refactor for blv ai
  pParty->uFlags &= 0xFFFFFFCFu;
  v37 = pIndoor->GetSector(pParty->vPosition.x, pParty->vPosition.y, pParty->vPosition.z);
  v45 = 0;
  v43 = 0;
  if ( (signed int)uNumActors > 0 )
  {
    v0 = pActors;//[0].uAttributes;
    do
    {
      BYTE1(v0->uAttributes) &= 0xFBu;
      if ( ! v0->CanAct() )
        goto LABEL_60;
	  v39 = abs(pParty->vPosition.z - v0->vPosition.z);
	  v38 = abs(pParty->vPosition.y - v0->vPosition.y);
	  v1 = abs(pParty->vPosition.x - v0->vPosition.x);
      v2 = v38;
      v3 = v39;
      if ( v1 < v38 )
      {
        v4 = v1;
        v1 = v38;
        v2 = v4;
      }
      if ( v1 < v39 )
      {
        v5 = v1;
        v1 = v39;
        v3 = v5;
      }
      if ( v2 < (signed int)v3 )
      {
        v6 = v3;
        v3 = v2;
        v2 = v6;
      }
      v7 = ((unsigned int)(11 * v2) >> 5) + (v3 >> 2) + v1;
      v8 = v0->uActorRadius;
      v9 = v7 - v8;
      v40 = v7 - v8;
      if ( v40 < 0 )
      {
        v9 = 0;
        v40 = 0;
      }
      if ( v9 < 10240 )
      {
        v10 = v0->uAttributes & 0xFEFFFFFF;
        v0->uAttributes = v10;
        if ( v10 & 0x80000 || v0->GetActorsRelation(0) )
        {
          v11 = (pParty->uFlags & 0x10) == 0;
          v0->uAttributes = v10 | 0x1000000;
          if ( v11 && (double)v40 < 307.2 )
            pParty->uFlags |= 0x10u;
          if ( !(pParty->uFlags & 0x20) && v9 < 5120 )
            pParty->uFlags |= 0x20u;
        }
        v12 = v45++;
        ai_near_actors_distances[v12] = v9;
        ai_near_actors_ids[v12] = v43;
      }
      else
      {
LABEL_60:
        BYTE1(v0->uAttributes) &= 0xBFu;
      }
      ++v43;
      ++v0;
    }
    while ( v43 < (signed int)uNumActors );
  }
  v13 = 0;
  if ( v45 > 0 )
  {
    v14 = 1;
    v44 = 1;
    do
    {
      while ( 1 )
      {
        v41 = v14;
        if ( v14 >= v45 )
          break;
        v15 = ai_near_actors_distances[v13];
        if ( v15 > ai_near_actors_distances[v14] )
        {
          v16 = &ai_near_actors_ids[v14];
          v17 = ai_near_actors_ids[v13];
          ai_near_actors_ids[v13] = *v16;
          *v16 = v17;
          v14 = v41;
          ai_near_actors_distances[v13] = ai_near_actors_distances[v41];
          ai_near_actors_distances[v41] = v15;
        }
        ++v14;
      }
      ++v13;
      v14 = v44 + 1;
      v44 = v14;
    }
    while ( v14 - 1 < v45 );
  }
  v18 = 0;
  v19 = 0;
  for ( i = 0; v18 < v45; i = v18 )
  {
    v20 = &pActors[ai_near_actors_ids[v18]];
    if ( v20->uAttributes & 0x8000
      || (v21 = sub_4070EF_prolly_collide_objects(PID(OBJECT_Actor,ai_near_actors_ids[v18]), 4u), v18 = i, v21) )
    {
      v22 = ai_near_actors_ids[v18];
      v20->uAttributes |= 0x8000u;
      ai_array_4F6638_actor_ids[v19] = v22;
      ai_array_4F5E68[v19++] = ai_near_actors_distances[v18];
      if ( v19 >= 30 )
        break;
    }
    ++v18;
  }
  v23 = 0;
  ai_arrays_size = v19;
  if ( (signed int)uNumActors > 0 )
  {
    v24 = pActors;//[0].uAttributes;
    do
    {
      if ( v24->CanAct() && v24->uSectorID == v37 )
      {
        v25 = 0;
        if ( v19 <= 0 )
        {
LABEL_43:
          v26 = ai_arrays_size;
          BYTE1(v24->uAttributes) |= 0x40u;
          ++ai_arrays_size;
          ai_array_4F6638_actor_ids[v26] = v23;
        }
        else
        {
          while ( ai_array_4F6638_actor_ids[v25] != v23 )
          {
            ++v25;
            if ( v25 >= v19 )
              goto LABEL_43;
          }
        }
      }
      ++v23;
      ++v24;
    }
    while ( v23 < (signed int)uNumActors );
  }
  v27 = ai_arrays_size;
  for ( j = 0; j < v45; ++j )
  {
    v29 = ai_near_actors_ids[j];
    if ( pActors[v29].uAttributes & 0xC000 && pActors[v29].CanAct() )
    {
      v30 = 0;
      if ( v27 <= 0 )
      {
LABEL_51:
        v31 = ai_arrays_size;
        v32 = ai_near_actors_ids[j];
        ++ai_arrays_size;
        ai_array_4F6638_actor_ids[v31] = v32;
      }
      else
      {
        while ( ai_array_4F6638_actor_ids[v30] != ai_near_actors_ids[j] )
        {
          ++v30;
          if ( v30 >= v27 )
            goto LABEL_51;
        }
      }
    }
  }
  v33 = ai_arrays_size;
  if ( ai_arrays_size > 30 )
  {
    v33 = 30;
    ai_arrays_size = 30;
  }
  memcpy(ai_near_actors_ids, ai_array_4F6638_actor_ids, 4 * v33);
  memcpy(ai_near_actors_distances, ai_array_4F5E68, 4 * ai_arrays_size);
  v34 = (unsigned int)ai_arrays_size;
  if ( ai_arrays_size > 0 )
  {
    do
    {
      v35 = (char *)&pActors[ai_near_actors_ids[HIDWORD(v34)]].uAttributes;
      v35[1] |= 4u;
      ++HIDWORD(v34);
    }
    while ( SHIDWORD(v34) < (signed int)v34 );
  }
  return v34;
}
// 4F75D8: using guessed type int ai_arrays_size;

//----- (00401A91) --------------------------------------------------------
void __cdecl UpdateActorAI()
{
	//unsigned int v0; // esi@4
	int v1; // eax@7
	int v2; // ecx@7
	int v3; // eax@7
	signed int v4; // edi@10
	Actor *v5; // esi@12
	signed int v6; // eax@14
	__int16 v7; // cx@14
	Player **v8; // esi@20
	Player *pPlayer; // ecx@21
	//Actor *pActor; // esi@34
	//__int16 v11; // ax@34
	//unsigned int v12; // eax@47
	//signed int v13; // edi@47
	//SpellBuff *v14; // ebx@47
	//unsigned int v15; // edi@67
	//char *v16; // eax@67
	//unsigned int v17; // edx@67
	//unsigned int v18; // ecx@67
	//unsigned __int16 v19; // ax@72
	//int *v20; // esi@80
	Actor *v21; // ebx@80
	unsigned __int16 v22; // ax@86
	//signed int v23; // eax@94
	//unsigned int v24; // eax@102
	//signed int v25; // edi@102
	//SpellBuff *v26; // esi@102
	unsigned int v27; // ecx@123
	unsigned int v28; // eax@123
	//unsigned int v29; // eax@127
	AIDirection *v30; // eax@129
	unsigned __int16 v31; // ax@132
	//unsigned int v32; // esi@142
	int v33; // eax@144
	int v34; // eax@147
	char v35; // al@150
	unsigned int v36; // edi@152
	signed int v37; // eax@154
	//unsigned __int8 v38; // sf@158
	//unsigned __int8 v39; // of@158
	//signed int v40; // edx@166
	//unsigned int v41; // ecx@166
	double v42; // st7@176
	double v43; // st6@176
	//bool v44; // eax@189
	bool v45; // eax@192
	unsigned __int8 v46; // cl@197
	double v47; // st7@206
	//double v48; // st7@207
	//char v49; // zf@208
	//char v50; // zf@214
	//signed int v51; // edx@219
	//unsigned int v52; // ecx@219
	__int16 v53; // fps@224
	//unsigned __int8 v54; // c0@224
	//unsigned __int8 v55; // c3@224
	//double v56; // st7@226
	AIDirection *v57; // eax@246
	double v58; // st7@246
	//signed int v59; // [sp-18h] [bp-C8h]@213
	//int v60; // [sp-14h] [bp-C4h]@144
	//int v61; // [sp-14h] [bp-C4h]@168
	//AIDirection *v62; // [sp-14h] [bp-C4h]@213
	//signed int v63; // [sp-14h] [bp-C4h]@216
	unsigned int v64; // [sp-14h] [bp-C4h]@219
	unsigned int v65; // [sp-10h] [bp-C0h]@144
	char v66; // [sp-10h] [bp-C0h]@147
	//AIDirection *v67; // [sp-10h] [bp-C0h]@167
	//int v68; // [sp-10h] [bp-C0h]@168
	//AIDirection *v69; // [sp-10h] [bp-C0h]@206
	int v70; // [sp-10h] [bp-C0h]@213
	//AIDirection *v71; // [sp-10h] [bp-C0h]@216
	AIDirection v72; // [sp+0h] [bp-B0h]@246
	AIDirection a3; // [sp+1Ch] [bp-94h]@129
	AIDirection v74; // [sp+38h] [bp-78h]@246
	AIDirection v75; // [sp+54h] [bp-5Ch]@129
	int target_pid_type; // [sp+70h] [bp-40h]@83
	signed int a1; // [sp+74h] [bp-3Ch]@129
	int v78; // [sp+78h] [bp-38h]@79
	AIDirection pDir; // [sp+7Ch] [bp-34h]@129
	float v80; // [sp+98h] [bp-18h]@33
	int v81; // [sp+9Ch] [bp-14h]@100
	//int v82; // [sp+A0h] [bp-10h]@45
	//unsigned int uActorID; // [sp+A4h] [bp-Ch]@32
	unsigned int v84; // [sp+A8h] [bp-8h]@11
	signed int target_pid; // [sp+ACh] [bp-4h]@83
	AIState uAIState;
	int v38;
	
	if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor)
		MakeActorAIList_ODM();
	else
		MakeActorAIList_BLV();
	
	//v0 = 0;
	if ( uCurrentlyLoadedLevelType != LEVEL_Indoor && pParty->armageddon_timer > 0 )
	{
		if ( pParty->armageddon_timer > 417 )
		{
			pParty->armageddon_timer = 0;
		}
		else
		{
			pParty->sRotationY = (stru_5C6E00->uIntegerDoublePi - 1) & (pParty->sRotationY + rand() % 16 - 8);
			v1 = rand();
			v2 = 128;
			v3 = pParty->sRotationX + v1 % 16 - 8;
			pParty->sRotationX = v3;
			if ( v3 > 128 || (v2 = -128, v3 < -128) )
				pParty->sRotationX = v2;
			pParty->uFlags |= 2u;
			pParty->armageddon_timer -= pMiscTimer->uTimeElapsed;
			v4 = pParty->field_16140 + 50;
			if ( pParty->armageddon_timer <= 0 )
			{
				pParty->armageddon_timer = 0;
				v84 = 0;
				if ( (signed int)uNumActors > 0 )
				{
					v5 = pActors;//[0].sCurrentHP;
					do
					{
						if ( v5->CanAct() )
						{
							v6 = stru_50C198.CalcMagicalDamageToActor(v5, 5, v4);
							v7 = v5->sCurrentHP - v6;
							v5->sCurrentHP = v7;
							if ( v6 )
							{
								if ( v7 >= 0 )
								{
									Actor::Stun(v84, 4, 0);
								}
								else
								{
									Actor::Die(v84);
									if ( v5->pMonsterInfo.uExp )
										GivePartyExp(pMonsterStats->pInfos[v5->pMonsterInfo.uID].uExp);
								}
							}
						}
						++v84;
						++v5;
					}
					while ( (signed int)v84 < (signed int)uNumActors );
				}
				v8 = &pPlayers[1];
				do
				{
					pPlayer = *v8;
					if ( !(*v8)->pConditions[14] && !pPlayer->pConditions[15] && !pPlayer->pConditions[16] )
						pPlayer->ReceiveDamage(v4, 5);
					++v8;
				}
				while ( (signed int)v8 <= (signed int)&pPlayers[4] );
				//v0 = 0;
			}
			if (pTurnEngine->field_1C)
				--pTurnEngine->field_1C;
		}
	}
	
	if (pParty->bTurnBasedModeOn)
	{
		pTurnEngine->_405E14();
		return;
	}
	
	
	//uActorID = v0;
	for (uint i = 0; i < uNumActors; ++i)
	{
		auto actor = pActors + i;
		//LODWORD(v80) = (int)(char *)pActors + 176; // uAIState
		//do
		//{
			//pActor = (Actor *)(LODWORD(v80) - 176);
			//v11 = *(unsigned int *)LODWORD(v80);
			//v49 = *(unsigned int *)LODWORD(v80) == 5;
			ai_near_actors_targets_pid[i] = OBJECT_Player;
			if (actor->uAIState == Dead || actor->uAIState == Removed || actor->uAIState == Disabled || actor->uAttributes & 0x0400)
				continue;
			
			if (!actor->sCurrentHP && actor->uAIState != Dying)
				Actor::Die(i);
			
			//v84 = *(_QWORD *)(LODWORD(v80) + 84) <= 0i64 ? 0 : 1;
			//v82 = *(_QWORD *)(LODWORD(v80) + 52) <= 0i64 ? 0 : 1;
			//v12 = 0;
			//v13 = 0;
			//v14 = (SpellBuff *)(LODWORD(v80) + 36);
			for (uint j = 0; j < 22; ++j)
			{
				if (j != 10)
				actor->pActorBuffs[j]._4585CA(pParty->uTimePlayed);
			}
			/*do
			{
				if ( v13 != 10 )
				{
					v14->_4585CA(pParty->uTimePlayed);
					v12 = 0;
				}
				++v13;
				++v14;
			}
			while ( v13 < 22 );*/
			if ( (signed __int64)actor->pActorBuffs[ACTOR_BUFF_SHRINK].uExpireTime < 0 )
			//&& SHIDWORD(pActor->pActorBuffs[3].uExpireTime) <= (signed int)v12 && (SHIDWORD(pActor->pActorBuffs[3].uExpireTime) < (signed int)v12
			// || LODWORD(pActor->pActorBuffs[3].uExpireTime) <= v12) )
				actor->uActorHeight = pMonsterList->pMonsters[actor->pMonsterInfo.uID - 1].uMonsterHeight;
			if ( (signed __int64)actor->pActorBuffs[ACTOR_BUFF_CHARM].uExpireTime > 0 )
				actor->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Friendly;
			// not sure
			else  if ( (signed __int64)actor->pActorBuffs[ACTOR_BUFF_CHARM].uExpireTime < 0 )
				actor->pMonsterInfo.uHostilityType = pMonsterStats->pInfos[actor->pMonsterInfo.uID].uHostilityType;
			
			if ((signed __int64)actor->pActorBuffs[ACTOR_BUFF_PARALYZED].uExpireTime > 0 
				|| (signed __int64)actor->pActorBuffs[ACTOR_BUFF_STONED].uExpireTime > 0)
				continue;
			
			//v15 = pMiscTimer->uTimeElapsed;
			//v16 = (char *)&pActor->pMonsterInfo.uRecoveryTime;
			//v17 = pActor->uCurrentActionTime;
			//v18 = pActor->pMonsterInfo.uRecoveryTime;
			if (actor->pMonsterInfo.uRecoveryTime)
			{
				if (actor->pMonsterInfo.uRecoveryTime < pMiscTimer->uTimeElapsed)
					actor->pMonsterInfo.uRecoveryTime = 0;
				else 
					actor->pMonsterInfo.uRecoveryTime -= pMiscTimer->uTimeElapsed;
			}
			
			actor->uCurrentActionTime += pMiscTimer->uTimeElapsed;
			if (actor->uCurrentActionTime < actor->uCurrentActionLength)
				continue;
			
			//v19 = actor->uAIState;
			if (actor->uAIState == Dying)
				actor->uAIState = Dead;
			else
			{
				if (actor->uAIState != Summoned)
				{
					Actor::AI_StandOrBored(i, OBJECT_Player, 256, nullptr);
					continue;
				}
				actor->uAIState = Standing;
			}
			
			actor->uCurrentActionTime = 0;
			actor->uCurrentActionLength = 0;
			actor->UpdateAnimation();
			//LABEL_78:
			//++uActorID;
			//LODWORD(v80) += 836;
		//}
		//while ( (signed int)uActorID < (signed int)uNumActors );
	}
	
	
	v78 = 0;
	int actor_id = -1;
	if ( ai_arrays_size > 0 )
	{
		//while ( 1 )
		for(v78 = 0; v78 < ai_arrays_size; ++v78)
		{
			actor_id = ai_near_actors_ids[v78];
			assert(actor_id < uNumActors);
			
			//v20 = &ai_near_actors_targets_pid[actor_id];
			v21 = &pActors[actor_id];
			Actor::_SelectTarget(actor_id, &ai_near_actors_targets_pid[actor_id], true);
			if (v21->pMonsterInfo.uHostilityType && !ai_near_actors_targets_pid[actor_id])
				v21->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Friendly;
			target_pid = ai_near_actors_targets_pid[actor_id];
			target_pid_type = PID_TYPE(target_pid);
			if ( target_pid_type == OBJECT_Actor)
				v80 = 0.5;
			else
				v80 = 1.0;
			v22 = v21->uAIState;
			if ( v22 == Dying || v22 == Dead || v22 == Removed || v22 == Disabled || v22 == Summoned)
			{
				continue;
			}
			if ( !v21->sCurrentHP )
				Actor::Die(actor_id);
			for(int i=0;i<22;i++)
			{
				if ( i != 10 )
				{
					v21->pActorBuffs[i]._4585CA(pParty->uTimePlayed);
				}
			}
			if ( (signed __int64)v21->pActorBuffs[ACTOR_BUFF_SHRINK].uExpireTime < 0 )
				v21->uActorHeight = pMonsterList->pMonsters[v21->pMonsterInfo.uID - 1].uMonsterHeight;
			if ( (signed __int64)v21->pActorBuffs[ACTOR_BUFF_CHARM].uExpireTime > 0 )
				v21->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Friendly;
			// not sure
			else if ( (signed __int64)v21->pActorBuffs[ACTOR_BUFF_CHARM].uExpireTime < 0 )
				v21->pMonsterInfo.uHostilityType = pMonsterStats->pInfos[v21->pMonsterInfo.uID].uHostilityType;
			if ( (signed __int64)v21->pActorBuffs[2].uExpireTime < 0 )
			{
				v21->uAIState = Removed;
				continue;
			}
			if ( (signed __int64)v21->pActorBuffs[5].uExpireTime > 0
				|| (signed __int64)v21->pActorBuffs[6].uExpireTime > 0)
			{
				continue;
			}
			v27 = pMiscTimer->uTimeElapsed;
			v28 = v21->pMonsterInfo.uRecoveryTime;
			v21->uCurrentActionTime += pMiscTimer->uTimeElapsed;
			if ( (signed int)v28 > 0 )
				v21->pMonsterInfo.uRecoveryTime = v28 - v27;
			if ( v21->pMonsterInfo.uRecoveryTime < 0 )
				v21->pMonsterInfo.uRecoveryTime = 0;
			if ( !(v21->uAttributes & 0x8000) )
				v21->uAttributes |= 0x8000;
			a1 = PID(OBJECT_Actor,actor_id);
			v30 = Actor::GetDirectionInfo(PID(OBJECT_Actor,actor_id), target_pid, &a3, 0);
			memcpy(&v75, v30, sizeof(v75));
			memcpy(&pDir, &v75, sizeof(pDir));
			uAIState = v21->uAIState; 
			/*if ( v21->pMonsterInfo.uHostilityType != MonsterInfo::Hostility_Friendly
				&& (signed int)v21->pMonsterInfo.uRecoveryTime <= 0
				&& v80 * 307.2 >= (double)(signed int)v75.uDistance
				&& (uAIState == Pursuing || uAIState == Standing || uAIState == Tethered || uAIState == Fidgeting)
				|| ( v21->pMonsterInfo.uMissleAttack1Type && uAIState == Stunned ) )
			{
				v32 = actor_id;
			}
			else
			*/
			if ( v21->pMonsterInfo.uHostilityType == MonsterInfo::Hostility_Friendly
				|| (signed int)v21->pMonsterInfo.uRecoveryTime > 0
				|| v80 * 307.2 < (double)(signed int)v75.uDistance
				|| uAIState != Pursuing && uAIState != Standing && uAIState != Tethered && uAIState != Fidgeting
				&&  !v21->pMonsterInfo.uMissleAttack1Type || uAIState != Stunned )
			{
				if ( (signed int)v21->uCurrentActionTime < v21->uCurrentActionLength )
				{
					continue;
				}
				else if ( v21->uAIState == AttackingMelee )
				{
					v35 = stru_50C198.special_ability_use_check(v21, actor_id);
					stru_50FE08.Add(
						a1,
						5120,
						v21->vPosition.x,
						v21->vPosition.y,
						v21->vPosition.z + ((signed int)v21->uActorHeight >> 1),
						v35,
						1
					);
				}
				else if ( v21->uAIState == AttackingRanged1 )
				{
					v34 = v21->pMonsterInfo.uMissleAttack1Type;
					Actor::RangedAttack(actor_id, &pDir, v34, 0);
				}
				else if ( v21->uAIState == AttackingRanged2 )
				{
					v34 = v21->pMonsterInfo.uMissleAttack2Type;
					Actor::RangedAttack(actor_id, &pDir, v34, 1);
				}
				else if ( v21->uAIState == AttackingRanged3 )
				{
					v65 = v21->pMonsterInfo.uSpellSkillAndMastery1;
					v33 = v21->pMonsterInfo.uSpell1ID;
					Actor::SpellAttack(actor_id, &pDir, v33, 2, v65);
				}
				else if ( v21->uAIState == AttackingRanged4 )
				{
					v65 = v21->pMonsterInfo.uSpellSkillAndMastery2;
					v33 = v21->pMonsterInfo.uSpell2ID;
					Actor::SpellAttack(actor_id, &pDir, v33, 3, v65);
				}
			}

			v36 = v75.uDistance;
			if ( v21->pMonsterInfo.uHostilityType == MonsterInfo::Hostility_Friendly)
			{
				if ( target_pid_type == OBJECT_Actor )
				{
					v36 = v75.uDistance;
					v37 = (unsigned __int8)*(&byte_5C8D1A[89 * (v21->pMonsterInfo.uID - 1) / 3]
						+ (pActors[PID_ID(target_pid)].pMonsterInfo.uID - 1) / 3);
				}
				else
				{
					v37 = 4;
				}
				v38=0;
				if ( v37 == 2 )
				{
					//v39 = __OFSUB__(v36, 1024);
					//v38 = ((v36 - 1024) & 0x80000000u) != 0;
					v38 = 1024;
				}
				else if ( v37 == 3 )
				{
					//v39 = __OFSUB__(v36, 2560);
					//v38 = ((v36 - 2560) & 0x80000000u) != 0;
					v38 = 2560;
				}
				else if ( v37 == 4 )
				{
					//v39 = __OFSUB__(v36, 5120);
					//v38 = ((v36 - 5120) & 0x80000000u) != 0;
					v38 = 5120;
				}
				if ( v37 >= 1 && v37 <= 4 && v36 < v38  || v37 == 1 )
					v21->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Long;
			}

			if ( (signed __int64)v21->pActorBuffs[4].uExpireTime > 0 )
			{
				if ( (signed int)v36 >= 10240 )
				{
					Actor::_4032B2(actor_id, target_pid, 1024, 0);
				}
				else
				{
					//peasents after attacked
					//guard after attacked
					Actor::Flee(actor_id, target_pid, 0, &pDir);
				}
				continue;
			}

			if ( v21->pMonsterInfo.uHostilityType == MonsterInfo::Hostility_Long && target_pid )
			{

				if ( v21->pMonsterInfo.uAIType == 1 )
				{
					if ( v21->pMonsterInfo.uMovementType == 5 )
					{
						Actor::AI_Stand(actor_id, target_pid, (signed __int64)((double)(signed int)v21->pMonsterInfo.uRecoveryTime * 2.133333333333333),	&pDir);
					}
					else
					{
						Actor::Flee(actor_id, target_pid, 0, &pDir);
						continue;
					}
						
				}
				if ( !(v21->uAttributes & 0x020000) )
				{
					if ( v21->pMonsterInfo.uAIType == 2 || v21->pMonsterInfo.uAIType == 3)
					{
						if ( v21->pMonsterInfo.uAIType == 2 )
							v43 = (double)(signed int)v21->pMonsterInfo.uHP * 0.2;
						if ( v21->pMonsterInfo.uAIType == 3 )
							v43 = (double)(signed int)v21->pMonsterInfo.uHP * 0.1;
						v84 = v21->sCurrentHP;
						v42 = (double)(signed int)v84;
						if ( v43 > v42 && (signed int)v36 < 10240 )
						{
							Actor::Flee(actor_id, target_pid, 0, &pDir);
							continue;
						}
					}
				}
				
				v81 = v36 - v21->uActorRadius;
				if ( target_pid_type == OBJECT_Actor )
					v81 -= pActors[PID_ID(target_pid)].uActorRadius;
				if ( v81 < 0 )
					v81 = 0;
				rand();
				v21->uAttributes &= 0xFBFFFF;
				if ( v81 < 5120 )
				{
					v45 = stru_50C198.special_ability_use_check(v21, actor_id);
					if ( v45 == 0 )
					{
						if ( v21->pMonsterInfo.uMissleAttack1Type )
						{
							if ( (signed int)v21->pMonsterInfo.uRecoveryTime <= 0 )
							{
								Actor::MissileAttack1(actor_id, target_pid, &pDir);
							}
							else if ( v21->pMonsterInfo.uMovementType == 5 )
							{
								v47 = (double)(signed int)v21->pMonsterInfo.uRecoveryTime * 2.133333333333333;
								v64 = (signed __int64)v47;
								Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
							}
							else
							{
								v47 = (double)(signed int)v21->pMonsterInfo.uRecoveryTime * 2.133333333333333;
								if ( v80 * 307.2 > (double)v81 )
								{
									v64 = (signed __int64)v47;
									Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
								}
								else
								{
									Actor::Pursue1(actor_id, target_pid, actor_id, (signed __int64)v47, &pDir);
								}
							}
						}
						else
						{
							if ( (double)v81 >= v80 * 307.2 )
							{
								if ( v81 >= 1024 )
								{
									if ( v21->pMonsterInfo.uMovementType == 5 )
									{
										v47 = (double)(signed int)v21->pMonsterInfo.uRecoveryTime * 2.133333333333333;
										v64 = (signed __int64)v47;
										Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
									}
									else
									{
										//monsters
										Actor::Pursue3(actor_id, target_pid, 0, &pDir);
									}
								}
								else if ( v21->pMonsterInfo.uMovementType == 5 )
								{
									v47 = (double)(signed int)v21->pMonsterInfo.uRecoveryTime * 2.133333333333333;
									v64 = (signed __int64)v47;
									Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
								}
								else
								{
									v70 = (signed __int64)v80 * 307.2;
									//monsters
									//guard after player runs away
									// follow player
									Actor::Pursue2(actor_id, target_pid, 0, &pDir, v70);
								}
							}
							else if ( (signed int)v21->pMonsterInfo.uRecoveryTime > 0 )
							{
								v47 = (double)(signed int)v21->pMonsterInfo.uRecoveryTime * 2.133333333333333;
								v64 = (signed __int64)v47;
								Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
							}
							else
							{
								//monsters
								Actor::MeleeAttack(actor_id, target_pid, &pDir);
							}
						}
						continue;
					}
					else if ( v45 == 2 || v45 == 3 )
					{
						if ( v45 == 2 )
							v46 = v21->pMonsterInfo.uSpell1ID;
						else
							v46 = v21->pMonsterInfo.uSpell2ID;
						if ( v46 )
						{
							if ( (signed int)v21->pMonsterInfo.uRecoveryTime <= 0 )
							{
								if ( v45 == 2 )
									Actor::SpellAttack1(actor_id, target_pid, &pDir);
								else
									Actor::SpellAttack2(actor_id, target_pid, &pDir);
							}
							else if ( v80 * 307.2 > (double)v81 || v21->pMonsterInfo.uMovementType == 5 )
							{
								v47 = (double)(signed int)v21->pMonsterInfo.uRecoveryTime * 2.133333333333333;
								v64 = (signed __int64)v47;
								Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
							}
							else
							{
								v47 = (double)(signed int)v21->pMonsterInfo.uRecoveryTime * 2.133333333333333;
								Actor::Pursue1(actor_id, target_pid, actor_id, (signed __int64)v47, &pDir);
							}
						}
						else
						{
							if ( (double)v81 >= v80 * 307.2 )
							{
								if ( v81 >= 1024 )
								{
									if ( v21->pMonsterInfo.uMovementType == 5 )
									{
										v47 = (double)(signed int)v21->pMonsterInfo.uRecoveryTime * 2.133333333333333;
										v64 = (signed __int64)v47;
										Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
									}
									else
									{
										Actor::Pursue3(actor_id, target_pid, 256, &pDir);
									}
								}
								else if ( v21->pMonsterInfo.uMovementType == 5 )
								{
									v47 = (double)(signed int)v21->pMonsterInfo.uRecoveryTime * 2.133333333333333;
									v64 = (signed __int64)v47;
									Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
								}
								else
								{
									v70 = (signed __int64)v80 * 307.2;
									Actor::Pursue2(actor_id, target_pid, 0, &pDir, v70);
								}
							}
							else if ( (signed int)v21->pMonsterInfo.uRecoveryTime > 0 )
							{
								v47 = (double)(signed int)v21->pMonsterInfo.uRecoveryTime * 2.133333333333333;
								v64 = (signed __int64)v47;
								Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
							}
							else
							{
								Actor::MeleeAttack(actor_id, target_pid, &pDir);
							}
						}
						continue;
					}
				}
			}

			if ( v21->pMonsterInfo.uHostilityType != MonsterInfo::Hostility_Long || !target_pid || v81 >= 5120 || v45 != 1 )
			{
				if ( !v21->pMonsterInfo.uMovementType )
				{
					Actor::_4032B2(actor_id, 4, 1024, 0);
				}
				else if ( v21->pMonsterInfo.uMovementType == 1 )
				{
					Actor::_4032B2(actor_id, 4, 2560, 0);
				}
				else if ( v21->pMonsterInfo.uMovementType == 2 )
				{
					Actor::_4032B2(actor_id, 4, 5120, 0);
				}
				else if ( v21->pMonsterInfo.uMovementType == 4 )
				{
					Actor::_4032B2(actor_id, 4, 10240, 0);
				}
				else if ( v21->pMonsterInfo.uMovementType == 5 )
				{
					v57 = Actor::GetDirectionInfo(a1, 4u, &v72, 0);
					v58 = (double)(signed int)v21->pMonsterInfo.uRecoveryTime * 2.133333333333333;
					memcpy(&v74, v57, sizeof(v74));
					memcpy(&pDir, &v74, sizeof(pDir));
					v64 = (signed __int64)v58;
					Actor::AI_Stand(actor_id, 4, v64, &pDir);
				}				
			}
			else if ( !v21->pMonsterInfo.uMissleAttack2Type )
			{
				if ( (double)v81 >= v80 * 307.2 )
				{
					if ( v81 >= 1024 )
					{
						if ( v21->pMonsterInfo.uMovementType == 5 )
						{
							v47 = (double)(signed int)v21->pMonsterInfo.uRecoveryTime * 2.133333333333333;
							v64 = (signed __int64)v47;
							Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
						}
						else
						{
							Actor::Pursue3(actor_id, target_pid, 256, &pDir);
						}
					}
					else if ( v21->pMonsterInfo.uMovementType == 5 )
					{
						v47 = (double)(signed int)v21->pMonsterInfo.uRecoveryTime * 2.133333333333333;
						v64 = (signed __int64)v47;
						Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
					}
					else
					{
						v70 = (signed __int64)v80 * 307.2;
						Actor::Pursue2(actor_id, target_pid, 0, &pDir, v70);
					}
				}
				else if ( (signed int)v21->pMonsterInfo.uRecoveryTime > 0 )
				{
					v47 = (double)(signed int)v21->pMonsterInfo.uRecoveryTime * 2.133333333333333;
					v64 = (signed __int64)v47;
					Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
				}
				else
				{
					Actor::MeleeAttack(actor_id, target_pid, &pDir);
				}
			}
			else if ( (signed int)v21->pMonsterInfo.uRecoveryTime > 0 )
			{
				v47 = (double)(signed int)v21->pMonsterInfo.uRecoveryTime * 2.133333333333333;
				if ( v80 * 307.2 > (double)v81 || v21->pMonsterInfo.uMovementType == 5 )
				{
					v64 = (signed __int64)v47;
					Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
				}
				else
				{
					Actor::Pursue1(actor_id, target_pid, actor_id, (signed __int64)v47, &pDir);
				}
			}
			else
			{
				Actor::MissileAttack2(actor_id, target_pid, &pDir);
			}
		}
	}
}

//----- (0040261D) --------------------------------------------------------
int stru298::Add(__int16 uID, __int16 a3, __int16 x, __int16 y, __int16 z, char a7, char a8)
{
  int result; // eax@1

  result = this->count;
  if ( this->count < 100 )
  {
    this->pIDs[result] = uID;
    this->pXs[this->count] = x;
    this->pYs[this->count] = y;
    this->pZs[this->count] = z;
    this->field_324[this->count] = a3;
    this->field_3EC[this->count] = a8;
    result = this->count;
    this->field_450[this->count++] = a7;
  }
  return result;
}

//----- (00402CAE) --------------------------------------------------------
int stru193_math::Cos(int angle)
{
  int v2; // eax@1

  //a2: (angle - uIntegerHalfPi)    for  sin(angle)
  //    (angle)                     for  cos(angle)

  v2 = uDoublePiMask & angle;
  
  if ( v2 > uIntegerPi )
    v2 = uIntegerDoublePi - v2;
  if ( v2 >= uIntegerHalfPi )
    return -pCosTable[uIntegerPi - v2];
  else
    return pCosTable[v2];
}

//----- (00404544) --------------------------------------------------------
signed int stru262_TurnBased::_404544()
{
  stru262_TurnBased *v1; // ebx@1
  TurnBased_QueueElem *v2; // esi@2
  Actor *v3; // edi@4
  Actor *v4; // ecx@4
  Player *v5; // eax@7
  int v6; // ecx@15
  TurnBased_QueueElem *v7; // eax@16
  TurnBased_QueueElem *v8; // ecx@18
  int v9; // edx@19
  int v10; // esi@19
  int v11; // esi@21
  int v12; // ST0C_4@25
  int v13; // ST10_4@25
  int v14; // ST14_4@25
  int v15; // ST18_4@25
  signed int result; // eax@28
  TurnBased_QueueElem *v17; // edi@32
  int v18; // [sp+20h] [bp-Ch]@17
  int v19; // [sp+24h] [bp-8h]@1
  int v20; // [sp+28h] [bp-4h]@1
  signed int v21; // [sp+28h] [bp-4h]@16
  int v22; // [sp+28h] [bp-4h]@31

  v20 = 0;
  v1 = this;
  v19 = this->uActorQueueSize;
  if ( this->uActorQueueSize > 0 )
  {
    v2 = this->pQueue;
    do
    {
      if ( PID_TYPE(v2->uPackedID) == OBJECT_Actor )
      {
        v3 = &pActors[PID_ID(v2->uPackedID)];
        v4 = &pActors[PID_ID(v2->uPackedID)];
        LOBYTE(v4->uAttributes) |= 0x80u;
        if ( !v4->CanAct() )
        {
          --v19;
          v2->field_4 = 1001;
          LOBYTE(v3->uAttributes) &= 0x7Fu;
        }
      }
      if ( PID_TYPE(v2->uPackedID) == OBJECT_Player)
      {
        v5 = &pParty->pPlayers[v2->uPackedID >> 3];
        if ( v5->pConditions[14]
          || v5->pConditions[16]
          || v5->pConditions[15]
          || v5->pConditions[13]
          || v5->pConditions[12]
          || v5->pConditions[2] )
        {
          --v19;
          v2->field_4 = 1001;
        }
      }
      ++v20;
      ++v2;
    }
    while ( v20 < v1->uActorQueueSize );
  }
  v6 = v1->uActorQueueSize;
  if ( v6 > 0 )
  {
    v21 = 1;
    v7 = v1->pQueue;
    do
    {
      v18 = v21;
      if ( v21 < v6 )
      {
        v8 = v7 + 1;
        do
        {
          v9 = v8->field_4;
          v10 = v7->field_4;
          if ( v9 < v10
            || v9 == v10
            && ((v11 = PID_TYPE(v8->uPackedID), v11 == OBJECT_Player) && PID_TYPE(v7->uPackedID) == OBJECT_Actor
             || v11 == PID_TYPE(v7->uPackedID) && (v8->uPackedID & 0xFFFFFFF8) < (v7->uPackedID & 0xFFFFFFF8)) )
          {
            v12 = v7->uPackedID;
            v13 = v7->field_4;
            v14 = v7->uActionLength;
            v15 = v7->field_C;
            v7->uPackedID = v8->uPackedID;
            v7->field_4 = v8->field_4;
            v7->uActionLength = v8->uActionLength;
            v7->field_C = v8->field_C;
            v8->uPackedID = v12;
            v8->field_4 = v13;
            v8->uActionLength = v14;
            v8->field_C = v15;
          }
          ++v18;
          ++v8;
        }
        while ( v18 < v1->uActorQueueSize );
      }
      ++v21;
      v6 = v1->uActorQueueSize;
      ++v7;
    }
    while ( v21 - 1 < v6 );
  }
  v1->uActorQueueSize = v19;
  result = v1->pQueue[0].uPackedID;
  if ( PID_TYPE(v1->pQueue[0].uPackedID) == OBJECT_Player)
  {
    result = PID_ID(result) + 1;
    uActiveCharacter = result;
    v1->field_18 |= 4u;
  }
  else
  {
    uActiveCharacter = 0;
    v1->field_18 &= 0xFFFFFFFBu;
  }
  v22 = 0;
  if ( v1->uActorQueueSize > 0 )
  {
    v17 = v1->pQueue;
    do
    {
      if ( PID_TYPE(v17->uPackedID) == OBJECT_Player)
        pParty->pPlayers[PID_ID(v17->uPackedID)].uTimeToRecovery = (signed __int64)((double)v17->field_4 * 0.46875);
      ++v22;
      ++v17;
      result = v22;
    }
    while ( v22 < v1->uActorQueueSize );
  }
  return result;
}

//----- (0040471C) --------------------------------------------------------
void stru262_TurnBased::_40471C()
{
  if ( pParty->bTurnBasedModeOn == 1 )
  {
    if ( pTurnEngine->field_4 == 2 )
      _406457(0);
  }
}

//----- (004059DB) --------------------------------------------------------
signed int stru262_TurnBased::Start()
{
  stru262_TurnBased *v1; // ebx@1
  unsigned int v2; // edi@1
  int v3; // esi@1
  int v4; // eax@5
  unsigned int v5; // esi@7
  Actor *v6; // edi@7
  unsigned int v7; // eax@9
  unsigned int v8; // edx@10
  unsigned __int8 v9; // zf@14
  unsigned __int8 v10; // sf@14
  unsigned __int8 v11; // of@14
  char *v12; // esi@15
  int v13; // ecx@16
  unsigned __int16 v14; // ax@17
  int v15; // ecx@18
  signed __int64 v16; // qax@19
  int v17; // edx@22
  unsigned int v18; // esi@27
  char *v19; // esi@32
  int v20; // edx@33
  char *v21; // eax@33
  int v22; // ecx@33
  int v23; // eax@34
  char *v24; // eax@34
  char *v25; // ecx@34
  int v26; // edx@34
  int v27; // eax@38
  int v28; // ecx@38
  AIDirection v30; // [sp+Ch] [bp-68h]@10
  AIDirection v31; // [sp+28h] [bp-4Ch]@10
  AIDirection a3; // [sp+44h] [bp-30h]@10
  int v33; // [sp+60h] [bp-14h]@10
  int *v34; // [sp+64h] [bp-10h]@6
  int v35; // [sp+68h] [bp-Ch]@5
  Player *v40; // [sp+6Ch] [bp-8h]@1
  int v40b;
  unsigned int v37; // [sp+70h] [bp-4h]@7

  pTurnEngine->field_18 &= 0xFFFFFFFDu;
  v1 = this;
  pEventTimer->TrackGameTime();
  pAudioPlayer->StopChannels(-1, -1);
  v2 = 0;
  pAudioPlayer->PlaySound((SoundID)(SOUND_GoldReceived|SOUND_EnteringAHouse|0x1), 0, 0, -1, 0, 0, 0, 0);
  v40 = pParty->pPlayers;
  dword_50C998_turnbased_icon_1A = 8 * pIconsFrameTable->pIcons[uIconID_TurnStart].uAnimLength;
  dword_50C994 = 0;
  v1->field_10 = 100;
  v1->field_0 = 0;
  v1->field_8 = 64;
  v1->field_4 = 1;
  v1->uActorQueueSize = 0;
  v3 = 0;
  do
  {
    if ( v40->CanAct() )
    {
      *(&v1->field_0 + 4 * (v1->uActorQueueSize + 2)) = PID(OBJECT_Player,v3);
      v1->pQueue[v1->uActorQueueSize].field_C = 2;
      v1->pQueue[v1->uActorQueueSize].uActionLength = 0;
      pParty->pTurnBasedPlayerRecoveryTimes[v1->uActorQueueSize++] = 0;
    }
    ++v40;
    ++v3;
  }
  while ( v40 <=&pParty->pPlayers[3] );
  v35 = v1->uActorQueueSize;
  v4 = v35;
  v40b = v35;
  if ( v40b < v40b + ai_arrays_size )
  {
    v34 = (int *)ai_near_actors_ids;
    do
    {
      v37 = *v34;
      v5 = v37;
      v6 = &pActors[v37];
      if ( v37 != 10 )
      {
        if ( pActors[v37].CanAct() )
        {
          v7 = v6->uAttributes;
          if ( v7 & 0x8000 < 0 )
          {
            v8 = ai_near_actors_targets_pid[v5];
            LOBYTE(v7) = v7 | 0x80;
            v6->uAttributes = v7;
            v33 = PID(OBJECT_Actor,v5);
            memcpy(&v31, Actor::GetDirectionInfo(PID(OBJECT_Actor,v5), v8, &a3, 0), sizeof(v31));
            memcpy(&v30, &v31, sizeof(v30));
            Actor::AI_StandOrBored(v37, 4, 32, &v30);
            *(&v1->field_0 + 4 * (v1->uActorQueueSize + 2)) = v33;
            v1->pQueue[v1->uActorQueueSize].field_C = 2;
            v1->pQueue[v1->uActorQueueSize++].uActionLength = 0;
          }
        }
        v4 = v35;
      }
      ++v40b;
      ++v34;
    }
    while ( v40b < v4 + ai_arrays_size );
    v2 = 0;
  }
  v11 = __OFSUB__(v1->uActorQueueSize, v2);
  v9 = v1->uActorQueueSize == v2;
  v10 = ((v1->uActorQueueSize - v2) & 0x80000000u) != 0;
  v37 = v2;
  v40b = v2;
  if ( !((unsigned __int8)(v10 ^ v11) | v9) )
  {
    v12 = (char *)&v1->pQueue[0].field_4;
    while ( 1 )
    {
      v13 = PID_TYPE(*((int *)v12 - 1));
      if ( v13 != OBJECT_Player )
        break;
      v14 = pPlayers[(*((int *)v12 - 1) >> 3) + 1]->uTimeToRecovery;
      if ( v14 != (short)v2 )
      {
        v33 = v14;
        v16 = (signed __int64)((double)v14 * 0.46875);
LABEL_20:
        *(int *)v12 = v16;
        goto LABEL_26;
      }
      v15 = v37++;
      *(&a3.uDistance + v15) = v40b;
LABEL_26:
      ++v40b;
      v12 += 16;
      if ( v40b >= v1->uActorQueueSize )
        goto LABEL_27;
    }
    if ( v13 != 3 )
    {
      *(int *)v12 = 666;
      goto LABEL_26;
    }
    v17 = rand() % 99;
    if ( v17 < 33 )
    {
      *(int *)v12 = 1;
      goto LABEL_26;
    }
    LODWORD(v16) = SHIDWORD(v16) < 66;
    LOBYTE(v16) = SHIDWORD(v16) >= 66;
    LODWORD(v16) = 2 * v16 + 3;
    goto LABEL_20;
  }
LABEL_27:
  v18 = 0;
  if ( (signed int)v37 > (signed int)v2 )
  {
    do
    {
      __debugbreak();
      *(&v31.uDistance + v18) = pParty->pPlayers[*(&v1->field_0 + 4 * (*(&a3.uDistance + v18) + 2)) >> 3].GetAttackRecoveryTime(
                                  v2);
      ++v18;
    }
    while ( (signed int)v18 < (signed int)v37 );
    if ( (signed int)v37 > (signed int)v2 )
    {
      v35 = v2;
      v34 = (int *)1;
      do
      {
        v40b = (int)v34;
        if ( (signed int)v34 < (signed int)v37 )
        {
          v19 = (char *)&v31.uDistance + v35;
          do
          {
            v20 = *(int *)v19;
            v33 = 4 * v40b;
            v21 = (char *)(&v31.uDistance + v40b);
            v22 = *(int *)v21;
            if ( *(int *)v21 < v20 )
            {
              *(int *)v21 = v20;
              v23 = v33;
              *(int *)v19 = v22;
              v24 = (char *)&a3.uDistance + v23;
              v25 = (char *)&a3.uDistance + v35;
              v26 = *(int *)v24;
              *(int *)v24 = *(unsigned int *)((char *)&a3.uDistance + v35);
              *(int *)v25 = v26;
              v2 = 0;
            }
            ++v40b;
          }
          while ( v40b < (signed int)v37 );
        }
        v34 = (int *)((char *)v34 + 1);
        v35 += 4;
      }
      while ( (signed int)((char *)v34 - 1) < (signed int)v37 );
      if ( (signed int)v37 > (signed int)v2 )
      {
        do
        {
          v27 = v2 + 2;
          v28 = *(&a3.uDistance + v2++);
          v11 = __OFSUB__(v2, v37);
          v10 = ((v2 - v37) & 0x80000000u) != 0;
          v1->pQueue[v28].field_4 = v27;
        }
        while ( v10 ^ v11 );
      }
    }
  }
  return v1->_404544();
}