view mm7_3.cpp @ 1218:eb687c8529ee

arcomage card animation working
author Gloval
date Sun, 09 Jun 2013 21:40:17 +0400
parents 96a81634669e
children 6c55c6bd67e0
line wrap: on
line source

#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif

#include <assert.h>


#include "VideoPlayer.h"
#include "Sprites.h"
#include "BSPModel.h"
#include "OutdoorCamera.h"
#include "LightmapBuilder.h"
#include "DecalBuilder.h"
#include "ParticleEngine.h"
#include "Mouse.h"
#include "Keyboard.h"
#include "stru6.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 "LOD.h"
#include "Actor.h"
#include "Allocator.h"
#include "Events.h"
#include "Viewport.h"
#include "Math.h"
#include "SpriteObject.h"
#include "ObjectList.h"
#include "PaletteManager.h"
#include "DecorationList.h"
#include "stru123.h"
#include "Time.h"
#include "IconFrameTable.h"
#include "TurnEngine.h"
#include "stru220.h"
#include "Events2D.h"
#include "stru176.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::AI_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::AI_Flee(v75, v38, 0, (AIDirection *)0);
            }
			else
			{
				Actor::AI_FaceObject(v75, v38, 0, (AIDirection *)0);
			}
          }
          break;
        case OBJECT_Player:
          if ( !v0->GetActorsRelation(0) )
          {
            v38 = stru_721530.uFaceID;
            Actor::AI_FaceObject(v75, v38, 0, (AIDirection *)0);
            break;
          }
          //v52 = HIDWORD(pParty->pPartyBuffs[PARTY_BUFF_INVISIBILITY].uExpireTime) == 0;
          //v53 = SHIDWORD(pParty->pPartyBuffs[PARTY_BUFF_INVISIBILITY].uExpireTime) < 0;
          v0->vVelocity.y = 0;
          v0->vVelocity.x = 0;
          //if ( !v53 && (!(v53 | v52) || LODWORD(pParty->pPartyBuffs[PARTY_BUFF_INVISIBILITY].uExpireTime) > 0) )
		  if ( (signed __int64)pParty->pPartyBuffs[PARTY_BUFF_INVISIBILITY].uExpireTime < 0)
            pParty->pPartyBuffs[PARTY_BUFF_INVISIBILITY].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);
		  item->vPosition.x = pActors[v5].vPosition.x;
          item->vPosition.y = pActors[v5].vPosition.y;
          item->vPosition.z = pActors[v5].vPosition.z + pActors[v5].uActorHeight;
		  if ( !item->uObjectDescID || (v6 = LOWORD(pEventTimer->uTimeElapsed) + item->uSpriteFrameID, item->uSpriteFrameID = v6, !(v4->uFlags & 4)) )
            continue;
          if ( v6 >= 0 )
          {
            v7 = v4->uLifetime;
            if (item->uAttributes & 2)
              v7 = item->field_20;
            if ( v6 < v7 )
              continue;
          }
            v10 = i;
            SpriteObject::OnInteraction(v10);
            continue;
      }

        if ( item->uObjectDescID )
        {
          v8 = LOWORD(pEventTimer->uTimeElapsed) + item->uSpriteFrameID;
          item->uSpriteFrameID = v8;
          v9 = v4->uFlags;
          if ( v9 & 4 )
		  {    
			  if ( v8 < 0 )
			  {
				v10 = i;
				SpriteObject::OnInteraction(v10);
				continue;
			  }
			  v11 = v4->uLifetime;
			  if (item->uAttributes & 2)
				v11 = item->field_20;
		  }
		  if ( !(v9 & 4) || v8 < v11 )
          {
            if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
              SpriteObject::UpdateObject_fn0_BLV(i);
            else
              SpriteObject::UpdateObject_fn0_ODM(i);
			if ( pParty->bTurnBasedModeOn != 1 || !(item->uSectorID & 4) )
              continue;
			v12 = abs(pParty->vPosition.x - item->vPosition.x);
			v18 = abs(pParty->vPosition.y - item->vPosition.y);
			v19 = abs(pParty->vPosition.z - item->vPosition.z);
            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 )
              continue;
            v10 = i;
            SpriteObject::OnInteraction(v10);
            continue;
          }
          v10 = i;
          if ( !(v9 & 0x40) )
		  {
            SpriteObject::OnInteraction(v10);
            continue;
		  }
          _46BFFA_check_object_intercept(i, PID(OBJECT_Item,i));
        }
    }
      //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;
    }
  }

  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, EQIUP_ANY) &&  // grants feather fall
        !pParty->pPlayers[1].WearsItem(ITEM_ARTIFACT_LADYS_ESCORT, EQIUP_ANY) &&
        !pParty->pPlayers[2].WearsItem(ITEM_ARTIFACT_LADYS_ESCORT, EQIUP_ANY) &&
        !pParty->pPlayers[3].WearsItem(ITEM_ARTIFACT_LADYS_ESCORT, EQIUP_ANY))
    {
      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, EQUIP_BOOTS))
      {
        player->ReceiveDamage((pParty->uFallStartY - party_z) * (0.1f * player->GetMaxHealth()) / 256, DMGT_PHISYCAL);
        v10 = (double)(20 - player->GetParameterBonus(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, EQUIP_BOOTS) ) //was 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[PARTY_BUFF_INVISIBILITY].uExpireTime) >= 0
        && (SHIDWORD(pParty->pPartyBuffs[PARTY_BUFF_INVISIBILITY].uExpireTime) > 0 || LODWORD(pParty->pPartyBuffs[PARTY_BUFF_INVISIBILITY].uExpireTime)) )
        pParty->pPartyBuffs[PARTY_BUFF_INVISIBILITY].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;
  v128 = 0;
  v129 = 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(ITEM_ARTIFACT_LADYS_ESCORT, EQIUP_ANY))  // 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[PARTY_BUFF_WATER_WALK].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[PARTY_BUFF_WATER_WALK].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(ITEM_ARTIFACT_HERMES_SANDALS, EQUIP_BOOTS) )
      {
        player->ReceiveDamage(
            (signed int)((pParty->uFallStartY - pZ) * (unsigned __int64)(player->GetMaxHealth() / 10)) / 256,
            DMGT_PHISYCAL);
        v105 = 20 - player->GetParameterBonus(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[PARTY_BUFF_FLY].uExpireTime) <= 0
    && (SHIDWORD(pParty->pPartyBuffs[PARTY_BUFF_FLY].uExpireTime) < 0 || LODWORD(pParty->pPartyBuffs[PARTY_BUFF_FLY].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[PARTY_BUFF_FLY].uFlags & 1
            || pParty->pPlayers[pParty->pPartyBuffs[PARTY_BUFF_FLY].uCaster - 1].sMana > 0 )//*(int *)&pParty->pArtifactsFound[6972 * pParty->pPartyBuffs[PARTY_BUFF_FLY].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 || pParty->bFlying)
  {
    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[PARTY_BUFF_FLY].uOverlayID + 119] &= 0xFEu;
      pParty->uFallStartY = pZ;
      //goto LABEL_141;
    }
	else
	{
		if ( v130 && v121 )
		  sub_42F960_create_object(pX, pY, v111);
		v121 = 0;
		pZ = v111;
		pParty->uFallStartY = v111;
	    v113 = pZ;
	    if (pParty->FlyActive())
		  stru_5E4C90._decor_events[20 * pParty->pPartyBuffs[PARTY_BUFF_FLY].uOverlayID + 119] |= 1u;

	}
  }
  else
  {
	  v113 = pZ;
	  if (pParty->FlyActive())
		stru_5E4C90._decor_events[20 * pParty->pPartyBuffs[PARTY_BUFF_FLY].uOverlayID + 119] |= 1u;
  }
//LABEL_141:
  if (bJumping && !pParty->bFlying)
  {
    v33 = -(pEventTimer->uTimeElapsed * GetGravityStrength());
    v34 = v121 + 2 * v33;
    v121 += 2 * v33;
  }
  else if (!partyAtHighSlope)
  {
    v34 = v121;
  }
  else if (!bJumping)
  {
    if ( !v108 )
	{
		// 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;
	}
  }
  else
	  v34 = v121;

//LABEL_164:
  if(bJumping)
  {
	  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(ITEM_ARTIFACT_HERMES_SANDALS, EQUIP_BOOTS) && 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 )
	{
		  pX = _angle_x;
		  if ( v43 )
			  pY = _angle_y;
	}
	else
	{
		if ( v127 && v129 > pZ )
		  v44 = 0;
		if ( v118 && v119 > pZ )
		  v43 = 0;
		if ( v44 )
		{
			  pX = _angle_x;
			  if ( v43 )
				  pY = _angle_y;
		}
		else if ( v43 )
		  pY = _angle_y;
		else
		{
			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;
			  pX = _angle_x;
			  if ( v43 )
				  pY = _angle_y;
			}
		}
	}
    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;
		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;
		continue;
	}
    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;
			}
			if ( pParty->floor_face_pid != v45 && BYTE3(v47->uAttributes) & 4 )
			{
				pParty->floor_face_pid = v45;
				v103 = v47->sCogTriggeredID;
			}
			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;
			continue;
        }
        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;
			if ( pParty->floor_face_pid != v45 && BYTE3(v47->uAttributes) & 4 )
			{
				pParty->floor_face_pid = v45;
				v103 = v47->sCogTriggeredID;
			}
			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;
			continue;
        }
        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 )
		{
			v45 = stru_721530.uFaceID;
			if ( pParty->floor_face_pid != v45 && BYTE3(v47->uAttributes) & 4 )
			{
				pParty->floor_face_pid = v45;
				v103 = v47->sCogTriggeredID;
			}
			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;
			continue;
		}
        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 )
	{
		  pAudioPlayer->_4AA258(804);
		  pParty->walk_sound_timer = 64;
	}
	else
	{
		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;
			pAudioPlayer->PlaySound((SoundID)v87, v88, v89, v90, 0, 0, 0, 0);
		  }
		  else
		  {
			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);
			pAudioPlayer->PlaySound((SoundID)v87, v88, v89, v90, 0, 0, 0, 0);
		  }
		}
		else
		{
			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;
				v63 = WorldPosToGridCellZ(pParty->vPosition.y) - 1;
				v64 = WorldPosToGridCellX(pParty->vPosition.x);
				v87 = pOutdoor->GetSoundIdByPosition(v64, v63, v86);
				pAudioPlayer->PlaySound((SoundID)v87, v88, v89, v90, 0, 0, 0, 0);
			  }
			  else
			  {
				  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,
                DMGT_PHISYCAL);
              v75 = (*v74)->GetActualEndurance();
              v110 = 20 - (*v74)->GetParameterBonus(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;
    }
	else
	{
		v114 = 1;
		v78 = 1;
	}
  }
  else
	v78 = 1;
//LABEL_306:
  if ( v77 )
  {
    pParty->vPosition.x = pX;
  }
  if ( v78 )
  {
    pParty->vPosition.y = pY;
  }
  if ( v78 || v77)
  {
    if ( bWaterWalk )
    {
      pParty->uFlags &= ~PARTY_FLAGS_1_STANDING_ON_WATER;
      //v79 = 20 * pParty->pPartyBuffs[PARTY_BUFF_WATER_WALK].uOverlayID + 6180178;
      //*(short *)&stru_5E4C90._decor_events[20 * pParty->pPartyBuffs[PARTY_BUFF_WATER_WALK].uOverlayID + 119] |= 1u;
      v79 = (int)&stru_5E4C90._decor_events[20 * pParty->pPartyBuffs[PARTY_BUFF_WATER_WALK].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;
        }
      }
    }
  }
  else 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,
              DMGT_PHISYCAL);
            v85 = (*v84)->GetActualEndurance();
            v110 = 20 - (*v84)->GetParameterBonus(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 ( this->field_10 > 0 )
    {
      v3 = (int)&this->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 < this->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 )
	  if(pIndoorCamera->pos.x == 0)
      {
        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 );
  }
  this->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()
{
  double v6; // st7@4
  double v12; // st7@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;

  v16 = 0;
  if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
  {
	for(int i = 0; i < a1->field_10; i++)
    {
		v6 = (double)pBLVRenderParams->field_40 * 0.000015258789 / a1->field_B4[i*4];
		if ( pRenderer->pRenderD3D )
		{
			pGame->pIndoorCameraD3D->Project(
				round(a1->field_B4[i*4]),
				round(a1->field_B4[i*4+1]),
				round(a1->field_B4[i*4+2]),
				&a5,
				&a6);
			a1->field_B4[i*4+16] = (double)a5;
			a1->field_B4[i*4+17] = (double)a6;
			a1->field_B4[i*4+18] = round(a1->field_B4[i*4]);
		}
		else
		{
			a1->field_B4[i*4+16] = (double)pBLVRenderParams->uViewportCenterX - v6 * a1->field_B4[i*4+1];
			a1->field_B4[i*4+17] = (double)pBLVRenderParams->uViewportCenterY - v6 * a1->field_B4[i*4+2];
			a1->field_B4[i*4+18] = a1->field_B4[i*4];
		}
		a1->field_B4[i*4+19] = a1->field_B4[i*4+3];
		if ( (double)(signed int)pViewport->uViewportTL_X <= a1->field_B4[i*4+16]
			&& (double)(signed int)pViewport->uViewportBR_X > a1->field_B4[i*4+16]
			&& (double)(signed int)pViewport->uViewportTL_Y <= a1->field_B4[i*4+17]
			&& (double)(signed int)pViewport->uViewportBR_Y > a1->field_B4[i*4+17] )
			v16 = 1;
    }
  }
  else
  {
	for(int i = 0; i < a1->field_10; i++)
    {
		v12 = (double)pOutdoorCamera->int_fov_rad / a1->field_B4[i*4];
		a1->field_B4[i*4+20] = (double)pViewport->uScreenCenterX - v12 * a1->field_B4[i*4+1];
		a1->field_B4[i*4+21] = (double)pViewport->uScreenCenterY - v12 * a1->field_B4[i*4+2];
		*((int *)&a1->field_B4[i*4+22]) = (int)a1->field_B4[i*4];
		*((int *)&a1->field_B4[i*4+23]) = a1->field_B4[i*4+3];
		if ( (double)(signed int)pViewport->uViewportTL_X <= a1->field_B4[i*4+20]
			&& (double)(signed int)pViewport->uViewportBR_X > a1->field_B4[i*4+20]
			&& (double)(signed int)pViewport->uViewportTL_Y <= a1->field_B4[i*4+21]
			&& (double)(signed int)pViewport->uViewportBR_Y > a1->field_B4[i*4+21] )
			v16 = 1;
    }
  }
  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 = pBitmaps_LOD->GetTexture(v9);
      v7->pTexture = pFaceTexture;
      v12 = pFaceTexture->uTextureWidth;
      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 = 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 = v3;
        v12->uNumVertices = v7;
        v12->field_59 = 5;
        v84 = v3->pFacePlane.vNormal.x;
        v83 = (unsigned __int64)(v84 * (signed __int64)-pOutdoor->vSunlight.x) >> 16;
        v82 = -pOutdoor->vSunlight.y;
        v84 = v3->pFacePlane.vNormal.y;
        v82 = (unsigned __int64)(v84 * (signed __int64)-pOutdoor->vSunlight.y) >> 16;
        v81 = (unsigned __int16 *)-pOutdoor->vSunlight.z;
        v84 = v3->pFacePlane.vNormal.z;
        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 = v3->uTextureID;
        if ( BYTE1(v3->uAttributes) & 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(v3, array_73D150, v12) )
        {
LABEL_71:
          --pOutdoorCamera->numStru148s;
          --pOutdoorCamera->field_44;
          goto LABEL_72;
        }
        LOBYTE(v20) = v79;
        v21 = a1;
        v3->bVisible = 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 ( v3->uAttributes & 0x10 )
          *(int *)&v12->flags |= 2u;
        if ( BYTE2(v3->uAttributes) & 0x40 )
          HIBYTE(v12->flags) |= 4u;
        v23 = v3->uAttributes;
        if ( v23 & 4 )
        {
          HIBYTE(v12->flags) |= 4u;
        }
        else
        {
          if ( v23 & 0x20 )
            HIBYTE(v12->flags) |= 8u;
        }
        v24 = v3->uAttributes;
        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[v3->uGradientVertex1],
              &array_73D150[v3->uGradientVertex2],
              &array_73D150[v3->uGradientVertex3],
              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.data(), dword_50B570.data(), v12);
      }
LABEL_72:
      ++v79;
      v1 = v78;
      ++v3;
      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.data() )
  {
    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, wcslen(L"%s_xn.tga"), L"%s_xn.tga", skybox_name); swprintf(xp_filename, wcslen(L"%s_xp.tga"), L"%s_xp.tga", skybox_name);
  swprintf(yn_filename, wcslen(L"%s_yn.tga"), L"%s_yn.tga", skybox_name); swprintf(yp_filename, wcslen(L"%s_yp.tga"), L"%s_yp.tga", skybox_name);
  swprintf(zn_filename, wcslen(L"%s_zn.tga"), L"%s_zn.tga", skybox_name); swprintf(zp_filename, wcslen(L"%s_zp.tga"), 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.data());
  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[PARTY_BUFF_TORCHLIGHT].uExpireTime > 0 )
      v8 = pParty->pPartyBuffs[PARTY_BUFF_TORCHLIGHT].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[PARTY_BUFF_TORCHLIGHT].uExpireTime > 0 )
      {
        if ( (signed __int64)pParty->pPartyBuffs[PARTY_BUFF_TORCHLIGHT].uExpireTime <= 0 )
          v11 = 0;
        else
          v11 = pParty->pPartyBuffs[PARTY_BUFF_TORCHLIGHT].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.data(), dword_50B570.data(), 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 )
  {
    this->v_18.x = 0;
    this->v_18.y = 0;
    this->v_18.z = 65536;
  }
  else
  {
    v8 = 1.0 / v7;
    v9 = v8 * v15 * 65536.0;
    v10 = v9 + 6.7553994e15;
    this->v_18.x = LODWORD(v10);
    v4 = v3;
    v11 = v8 * v4 * 65536.0;
    v12 = v11 + 6.7553994e15;
    this->v_18.y = LODWORD(v12);
    v6 = v5;
    v13 = v8 * v6 * 65536.0;
    v14 = v13 + 6.7553994e15;
    this->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 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)//for blessing
{
  __int16 result; // ax@1
  int v2; // ebx@1
  char *v3; // esi@1
  int v4; // edi@4
  bool 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
  for ( uint i = 0; i < 50; ++i )
  {
    if ( pOtherOverlayList->pOverlays[i].field_6 > 0 )
    {
      result = pOtherOverlayList->pOverlays[i].field_0;
      if ( pOtherOverlayList->pOverlays[i].field_0 >= 300 )
      {
        //v4 = result;
        v5 = pOtherOverlayList->pOverlays[i].field_0 == v2 + 320 
           || pOtherOverlayList->pOverlays[i].field_0 == v2 + 330 
           || pOtherOverlayList->pOverlays[i].field_0 == v2 + 340 
           || pOtherOverlayList->pOverlays[i].field_0 == v2 + 350;
        pOtherOverlayList->pOverlays[i].field_0 = v2 + 310;
        if ( pOtherOverlayList->pOverlays[i].field_0 == v2 + 310 || v5 )
        {
          if ( !pOtherOverlayList->pOverlays[i].field_0 )
          {
            v6 = pSpriteFrameTable->GetFrame(pOverlayList->pOverlays[pOtherOverlayList->pOverlays[i].field_2].uSpriteFramesetID,
                   pOtherOverlayList->pOverlays[i].field_4);
            v7 = v6;
            v11 = pOtherOverlayList->pOverlays[i].field_E;
            v13 = v6->scale;
            v13 = (unsigned __int64)(v11 * (signed __int64)v13) >> 16;
            v10.uScreenSpaceX = pOtherOverlayList->pOverlays[i].field_8;
            v10.uScreenSpaceY = pOtherOverlayList->pOverlays[i].field_A;
            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 = pOtherOverlayList->pOverlays[i].field_2;
            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.data(), 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 )
      {
        EventProcessor(pLevelEVT_Index[i].uEventID, 0, 1, pLevelEVT_Index[i].event_sequence_num);
      }
    }
  }
}

//----- (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)
		{
			EventProcessor(pEvent.uEventID, 0, 0, pEvent.event_sequence_num);
		}
		else if (_evt->_e_type == EVENT_OnTimer || _evt->_e_type == EVENT_Initialize)
		{
			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_Initialize && !(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.data(), 0x2400u);

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

//----- (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 ( _stricmp(v13, "") )
                    v17 = v14;
                }
              }
            }
          }
        }
        result = v17;
      }
    }
  }
  return result;
}

//----- (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;

//----- (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();
    pAudioPlayer->StopChannels(-1, -1);
    pMiscTimer->Pause();
    pEventTimer->Pause();
    dword_5C3418 = v4;
    dword_5C341C = v3;
    _591094_decoration = activeLevelDecoration;
    pGUIWindow2 = GUIWindow::Create(0, 0, 640, 480, WINDOW_GreetingNPC, a4, 0);
    pGUIWindow2->CreateButton( 61, 424, 31, 40, 2, 94, UIMSG_SelectCharacter, 1, '1', "", 0);
    pGUIWindow2->CreateButton(177, 424, 31, 40, 2, 94, UIMSG_SelectCharacter, 2, '2', "", 0);
    pGUIWindow2->CreateButton(292, 424, 31, 40, 2, 94, UIMSG_SelectCharacter, 3, '3', "", 0);
    pGUIWindow2->CreateButton(407, 424, 31, 40, 2, 94, UIMSG_SelectCharacter, 4, '4', "", 0);
  }
}

//----- (004452BB) --------------------------------------------------------
void __cdecl sub_4452BB()
{
  pGUIWindow2->Release();
  pGUIWindow2 = 0;
  activeLevelDecoration = _591094_decoration;
  EventProcessor(dword_5C3418, 0, 1, dword_5C341C);
  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;
}


//----- (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 DialogueEnding()
{
  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, int entry_line)
	{
  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 = entry_line;
  pSomeOtherEVT = pGlobalEVT.data();
  uSomeOtherEVT_NumEvents = uGlobalEVT_NumEvents;
  memcpy(pSomeOtherEVT_Events.data(), pGlobalEVT_Index.data(), 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 && _stricmp(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 ( _stricmp(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.data();//[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.data();//[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;
        EventProcessor(timer->timer_evt_ID, 0, 1, timer->timer_evt_seq_num);
      }
    }
    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 if big time interval has lapsed
          timer->next_fire_time = pParty->uTimePlayed;

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

//----- (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.data());
  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].uType;
  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[PARTY_BUFF_DAY_OF_GODS];
        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[PARTY_BUFF_DAY_OF_GODS];
       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[PARTY_BUFF_DAY_OF_GODS];
    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[PARTY_BUFF_IMMOLATION];
        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 ( _stricmp(pCurrentMapName.data(), v2) )
    SaveGame(1, 0);

  uGameState = GAME_STATE_2;
  strcpy(pCurrentMapName.data(), 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.data();
      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;
  }
}



//----- (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)) != 0;
}

//----- (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;
}

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

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

//----- (0044C1D0) --------------------------------------------------------
void 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 = _stricmp("nwc.blv", pCurrentMapName.data());
  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) --------------------------------------------------------
bool LevelDecoration::IsInteractive()
{
  switch (uDecorationDescID)
  {
    case 4:    // trash pile
    case 5:    // campfire
    case 6:    // cauldron
    case 11:   // fruit plate
    case 13:   // trash pile
    case 14:   // dirt
    case 24:   // keg
    case 184:  // fire
    case 187:  // fire
    case 190:  // fire
      return true;
  }

  if (uDecorationDescID >= 206 && uDecorationDescID <= 209) // lighthouse fire
    return true;
  if (uDecorationDescID >= 210 && uDecorationDescID <= 221) // magic pedistal
    return true;

  return false;
}

//----- (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

  assert(false);
  //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;
  this->x = LODWORD(v10);
  v11 = v8 * v5 * 65536.0;
  v12 = v11 + 6.7553994e15;
  this->y = LODWORD(v12);
  v13 = v8 * v7 * 65536.0;
  v14 = v13 + 6.7553994e15;
  this->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.data();//[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.data();//[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.data(), ai_array_4F6638_actor_ids.data(), 4 * v33);
  memcpy(ai_near_actors_distances.data(), ai_array_4F5E68.data(), 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 sDmg; // 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);
			pParty->sRotationX = pParty->sRotationX + rand() % 16 - 8;
			if ( pParty->sRotationX > 128) 
				pParty->sRotationX = 128;
			else if ( pParty->sRotationX < -128 )
				pParty->sRotationX = -128;
				
			pParty->uFlags |= 2u;
			pParty->armageddon_timer -= pMiscTimer->uTimeElapsed;
			v4 = pParty->field_16140 + 50;
			if ( pParty->armageddon_timer <= 0 )
			{
				pParty->armageddon_timer = 0;
				for(int i = 0; i < uNumActors; i++)
				{
					pActor=&pActors[i];
					if ( pActor->CanAct() )
					{
						sDmg = stru_50C198.CalcMagicalDamageToActor(pActor, 5, v4);
						pActor->sCurrentHP -= stru_50C198.CalcMagicalDamageToActor(pActor, 5, v4);
						if ( sDmg )
						{
							if ( pActor->sCurrentHP >= 0 )
							{
								Actor::AI_Stun(i, 4, 0);
							}
							else
							{
								Actor::Die(i);
								if ( pActor->pMonsterInfo.uExp )
									GivePartyExp(pMonsterStats->pInfos[pActor->pMonsterInfo.uID].uExp);
							}
						}
					}
				}
				for(int i = 1; i <= 4; i++)
				{
					pPlayer = pPlayers[i];
					if ( !pPlayer->pConditions[14] && !pPlayer->pConditions[15] && !pPlayer->pConditions[16] )
						pPlayer->ReceiveDamage(v4, DMGT_5);
				}
			}
			if (pTurnEngine->field_1C)
				--pTurnEngine->field_1C;
		}
	}
	
	if (pParty->bTurnBasedModeOn)
	{
		pTurnEngine->_405E14();
		return;
	}
	
	
	//uActorID = v0;
	for (uint i = 0; i < uNumActors; ++i)
	{
		pActor = &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 (pActor->uAIState == Dead || pActor->uAIState == Removed || pActor->uAIState == Disabled || pActor->uAttributes & 0x0400)
				continue;
			
			if (!pActor->sCurrentHP && pActor->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)
				pActor->pActorBuffs[j]._4585CA(pParty->uTimePlayed);
			}
			/*do
			{
				if ( v13 != 10 )
				{
					v14->_4585CA(pParty->uTimePlayed);
					v12 = 0;
				}
				++v13;
				++v14;
			}
			while ( v13 < 22 );*/
			if ( (signed __int64)pActor->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) )
				pActor->uActorHeight = pMonsterList->pMonsters[pActor->pMonsterInfo.uID - 1].uMonsterHeight;
			if ( (signed __int64)pActor->pActorBuffs[ACTOR_BUFF_CHARM].uExpireTime > 0 )
				pActor->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Friendly;
			// not sure
			else  if ( (signed __int64)pActor->pActorBuffs[ACTOR_BUFF_CHARM].uExpireTime < 0 )
				pActor->pMonsterInfo.uHostilityType = pMonsterStats->pInfos[pActor->pMonsterInfo.uID].uHostilityType;
			
			if ((signed __int64)pActor->pActorBuffs[ACTOR_BUFF_PARALYZED].uExpireTime > 0 
				|| (signed __int64)pActor->pActorBuffs[ACTOR_BUFF_STONED].uExpireTime > 0)
				continue;
			
			//v15 = pMiscTimer->uTimeElapsed;
			//v16 = (char *)&pActor->pMonsterInfo.uRecoveryTime;
			//v17 = pActor->uCurrentActionTime;
			//v18 = pActor->pMonsterInfo.uRecoveryTime;
			if (pActor->pMonsterInfo.uRecoveryTime)
			{
				if (pActor->pMonsterInfo.uRecoveryTime < pMiscTimer->uTimeElapsed)
					pActor->pMonsterInfo.uRecoveryTime = 0;
				else 
					pActor->pMonsterInfo.uRecoveryTime -= pMiscTimer->uTimeElapsed;
			}
			
			pActor->uCurrentActionTime += pMiscTimer->uTimeElapsed;
			if (pActor->uCurrentActionTime < pActor->uCurrentActionLength)
				continue;
			
			//v19 = actor->uAIState;
			if (pActor->uAIState == Dying)
				pActor->uAIState = Dead;
			else
			{
				if (pActor->uAIState != Summoned)
				{
					Actor::AI_StandOrBored(i, OBJECT_Player, 256, nullptr);
					continue;
				}
				pActor->uAIState = Standing;
			}
			
			pActor->uCurrentActionTime = 0;
			pActor->uCurrentActionLength = 0;
			pActor->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];
			pActor = &pActors[actor_id];
			Actor::_SelectTarget(actor_id, &ai_near_actors_targets_pid[actor_id], true);
			if (pActor->pMonsterInfo.uHostilityType && !ai_near_actors_targets_pid[actor_id])
				pActor->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 = pActor->uAIState;
			if ( v22 == Dying || v22 == Dead || v22 == Removed || v22 == Disabled || v22 == Summoned)
			{
				continue;
			}
			if ( !pActor->sCurrentHP )
				Actor::Die(actor_id);
			for(int i=0;i<22;i++)
			{
				if ( i != 10 )
				{
					pActor->pActorBuffs[i]._4585CA(pParty->uTimePlayed);
				}
			}
			if ( (signed __int64)pActor->pActorBuffs[ACTOR_BUFF_SHRINK].uExpireTime < 0 )
				pActor->uActorHeight = pMonsterList->pMonsters[pActor->pMonsterInfo.uID - 1].uMonsterHeight;
			if ( (signed __int64)pActor->pActorBuffs[ACTOR_BUFF_CHARM].uExpireTime > 0 )
				pActor->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Friendly;
			// not sure
			else if ( (signed __int64)pActor->pActorBuffs[ACTOR_BUFF_CHARM].uExpireTime < 0 )
				pActor->pMonsterInfo.uHostilityType = pMonsterStats->pInfos[pActor->pMonsterInfo.uID].uHostilityType;
			if ( (signed __int64)pActor->pActorBuffs[2].uExpireTime < 0 )
			{
				pActor->uAIState = Removed;
				continue;
			}
			if ( (signed __int64)pActor->pActorBuffs[5].uExpireTime > 0
				|| (signed __int64)pActor->pActorBuffs[6].uExpireTime > 0)
			{
				continue;
			}
			v27 = pMiscTimer->uTimeElapsed;
			v28 = pActor->pMonsterInfo.uRecoveryTime;
			pActor->uCurrentActionTime += pMiscTimer->uTimeElapsed;
			if ( (signed int)v28 > 0 )
				pActor->pMonsterInfo.uRecoveryTime = v28 - v27;
			if ( pActor->pMonsterInfo.uRecoveryTime < 0 )
				pActor->pMonsterInfo.uRecoveryTime = 0;
			if ( !(pActor->uAttributes & 0x8000) )
				pActor->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 = pActor->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 ( pActor->pMonsterInfo.uHostilityType == MonsterInfo::Hostility_Friendly
				|| (signed int)pActor->pMonsterInfo.uRecoveryTime > 0
				|| v80 * 307.2 < (double)(signed int)v75.uDistance
				|| uAIState != Pursuing && uAIState != Standing && uAIState != Tethered && uAIState != Fidgeting
				&&  !pActor->pMonsterInfo.uMissleAttack1Type || uAIState != Stunned )
			{
				if ( (signed int)pActor->uCurrentActionTime < pActor->uCurrentActionLength )
				{
					continue;
				}
				else if ( pActor->uAIState == AttackingMelee )
				{
					v35 = stru_50C198.special_ability_use_check(pActor, actor_id);
					stru_50FE08.Add(
						a1,
						5120,
						pActor->vPosition.x,
						pActor->vPosition.y,
						pActor->vPosition.z + ((signed int)pActor->uActorHeight >> 1),
						v35,
						1
					);
				}
				else if ( pActor->uAIState == AttackingRanged1 )
				{
					v34 = pActor->pMonsterInfo.uMissleAttack1Type;
					Actor::AI_RangedAttack(actor_id, &pDir, v34, 0);
				}
				else if ( pActor->uAIState == AttackingRanged2 )
				{
					v34 = pActor->pMonsterInfo.uMissleAttack2Type;
					Actor::AI_RangedAttack(actor_id, &pDir, v34, 1);
				}
				else if ( pActor->uAIState == AttackingRanged3 )
				{
					v65 = pActor->pMonsterInfo.uSpellSkillAndMastery1;
					v33 = pActor->pMonsterInfo.uSpell1ID;
					Actor::AI_SpellAttack(actor_id, &pDir, v33, 2, v65);
				}
				else if ( pActor->uAIState == AttackingRanged4 )
				{
					v65 = pActor->pMonsterInfo.uSpellSkillAndMastery2;
					v33 = pActor->pMonsterInfo.uSpell2ID;
					Actor::AI_SpellAttack(actor_id, &pDir, v33, 3, v65);
				}
			}

			v36 = v75.uDistance;
			if ( pActor->pMonsterInfo.uHostilityType == MonsterInfo::Hostility_Friendly)
			{
				if ( target_pid_type == OBJECT_Actor )
				{
					v36 = v75.uDistance;
					v37 = (unsigned __int8)*(&byte_5C8D1A[89 * (pActor->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 )
					pActor->pMonsterInfo.uHostilityType = MonsterInfo::Hostility_Long;
			}

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

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

				if ( pActor->pMonsterInfo.uAIType == 1 )
				{
					if ( pActor->pMonsterInfo.uMovementType == 5 )
					{
						Actor::AI_Stand(actor_id, target_pid, (signed __int64)((double)(signed int)pActor->pMonsterInfo.uRecoveryTime * 2.133333333333333),	&pDir);
					}
					else
					{
						Actor::AI_Flee(actor_id, target_pid, 0, &pDir);
						continue;
					}
						
				}
				if ( !(pActor->uAttributes & 0x020000) )
				{
					if ( pActor->pMonsterInfo.uAIType == 2 || pActor->pMonsterInfo.uAIType == 3)
					{
						if ( pActor->pMonsterInfo.uAIType == 2 )
							v43 = (double)(signed int)pActor->pMonsterInfo.uHP * 0.2;
						if ( pActor->pMonsterInfo.uAIType == 3 )
							v43 = (double)(signed int)pActor->pMonsterInfo.uHP * 0.1;
						v84 = pActor->sCurrentHP;
						v42 = (double)(signed int)v84;
						if ( v43 > v42 && (signed int)v36 < 10240 )
						{
							Actor::AI_Flee(actor_id, target_pid, 0, &pDir);
							continue;
						}
					}
				}
				
				v81 = v36 - pActor->uActorRadius;
				if ( target_pid_type == OBJECT_Actor )
					v81 -= pActors[PID_ID(target_pid)].uActorRadius;
				if ( v81 < 0 )
					v81 = 0;
				rand();
				pActor->uAttributes &= 0xFFFBFFFF;
				if ( v81 < 5120 )
				{
					v45 = stru_50C198.special_ability_use_check(pActor, actor_id);
					if ( v45 == 0 )
					{
						if ( pActor->pMonsterInfo.uMissleAttack1Type )
						{
							if ( (signed int)pActor->pMonsterInfo.uRecoveryTime <= 0 )
							{
								Actor::AI_MissileAttack1(actor_id, target_pid, &pDir);
							}
							else if ( pActor->pMonsterInfo.uMovementType == 5 )
							{
								v47 = (double)(signed int)pActor->pMonsterInfo.uRecoveryTime * 2.133333333333333;
								v64 = (signed __int64)v47;
								Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
							}
							else
							{
								v47 = (double)(signed int)pActor->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::AI_Pursue1(actor_id, target_pid, actor_id, (signed __int64)v47, &pDir);
								}
							}
						}
						else
						{
							if ( (double)v81 >= v80 * 307.2 )
							{
								if ( v81 >= 1024 )
								{
									if ( pActor->pMonsterInfo.uMovementType == 5 )
									{
										v47 = (double)(signed int)pActor->pMonsterInfo.uRecoveryTime * 2.133333333333333;
										v64 = (signed __int64)v47;
										Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
									}
									else
									{
										//monsters
										Actor::AI_Pursue3(actor_id, target_pid, 0, &pDir);
									}
								}
								else if ( pActor->pMonsterInfo.uMovementType == 5 )
								{
									v47 = (double)(signed int)pActor->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::AI_Pursue2(actor_id, target_pid, 0, &pDir, v70);
								}
							}
							else if ( (signed int)pActor->pMonsterInfo.uRecoveryTime > 0 )
							{
								v47 = (double)(signed int)pActor->pMonsterInfo.uRecoveryTime * 2.133333333333333;
								v64 = (signed __int64)v47;
								Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
							}
							else
							{
								//monsters
								Actor::AI_MeleeAttack(actor_id, target_pid, &pDir);
							}
						}
						continue;
					}
					else if ( v45 == 2 || v45 == 3 )
					{
						if ( v45 == 2 )
							v46 = pActor->pMonsterInfo.uSpell1ID;
						else
							v46 = pActor->pMonsterInfo.uSpell2ID;
						if ( v46 )
						{
							if ( (signed int)pActor->pMonsterInfo.uRecoveryTime <= 0 )
							{
								if ( v45 == 2 )
									Actor::AI_SpellAttack1(actor_id, target_pid, &pDir);
								else
									Actor::AI_SpellAttack2(actor_id, target_pid, &pDir);
							}
							else if ( v80 * 307.2 > (double)v81 || pActor->pMonsterInfo.uMovementType == 5 )
							{
								v47 = (double)(signed int)pActor->pMonsterInfo.uRecoveryTime * 2.133333333333333;
								v64 = (signed __int64)v47;
								Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
							}
							else
							{
								v47 = (double)(signed int)pActor->pMonsterInfo.uRecoveryTime * 2.133333333333333;
								Actor::AI_Pursue1(actor_id, target_pid, actor_id, (signed __int64)v47, &pDir);
							}
						}
						else
						{
							if ( (double)v81 >= v80 * 307.2 )
							{
								if ( v81 >= 1024 )
								{
									if ( pActor->pMonsterInfo.uMovementType == 5 )
									{
										v47 = (double)(signed int)pActor->pMonsterInfo.uRecoveryTime * 2.133333333333333;
										v64 = (signed __int64)v47;
										Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
									}
									else
									{
										Actor::AI_Pursue3(actor_id, target_pid, 256, &pDir);
									}
								}
								else if ( pActor->pMonsterInfo.uMovementType == 5 )
								{
									v47 = (double)(signed int)pActor->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::AI_Pursue2(actor_id, target_pid, 0, &pDir, v70);
								}
							}
							else if ( (signed int)pActor->pMonsterInfo.uRecoveryTime > 0 )
							{
								v47 = (double)(signed int)pActor->pMonsterInfo.uRecoveryTime * 2.133333333333333;
								v64 = (signed __int64)v47;
								Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
							}
							else
							{
								Actor::AI_MeleeAttack(actor_id, target_pid, &pDir);
							}
						}
						continue;
					}
				}
			}
			
			if ( pActor->pMonsterInfo.uHostilityType != MonsterInfo::Hostility_Long || !target_pid || v81 >= 5120 || v45 != 1 )
			{
				if ( !pActor->pMonsterInfo.uMovementType )
				{
					Actor::AI_4032B2(actor_id, 4, 1024, 0);
				}
				else if ( pActor->pMonsterInfo.uMovementType == 1 )
				{
					Actor::AI_4032B2(actor_id, 4, 2560, 0);
				}
				else if ( pActor->pMonsterInfo.uMovementType == 2 )
				{
					Actor::AI_4032B2(actor_id, 4, 5120, 0);
				}
				else if ( pActor->pMonsterInfo.uMovementType == 4 )
				{
					Actor::AI_4032B2(actor_id, 4, 10240, 0);
				}
				else if ( pActor->pMonsterInfo.uMovementType == 5 )
				{
					v57 = Actor::GetDirectionInfo(a1, 4u, &v72, 0);
					v58 = (double)(signed int)pActor->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 ( !pActor->pMonsterInfo.uMissleAttack2Type )
			{
				if ( (double)v81 >= v80 * 307.2 )
				{
					if ( v81 >= 1024 )
					{
						if ( pActor->pMonsterInfo.uMovementType == 5 )
						{
							v47 = (double)(signed int)pActor->pMonsterInfo.uRecoveryTime * 2.133333333333333;
							v64 = (signed __int64)v47;
							Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
						}
						else
						{
							Actor::AI_Pursue3(actor_id, target_pid, 256, &pDir);
						}
					}
					else if ( pActor->pMonsterInfo.uMovementType == 5 )
					{
						v47 = (double)(signed int)pActor->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::AI_Pursue2(actor_id, target_pid, 0, &pDir, v70);
					}
				}
				else if ( (signed int)pActor->pMonsterInfo.uRecoveryTime > 0 )
				{
					v47 = (double)(signed int)pActor->pMonsterInfo.uRecoveryTime * 2.133333333333333;
					v64 = (signed __int64)v47;
					Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
				}
				else
				{
					Actor::AI_MeleeAttack(actor_id, target_pid, &pDir);
				}
			}
			else if ( (signed int)pActor->pMonsterInfo.uRecoveryTime > 0 )
			{
				v47 = (double)(signed int)pActor->pMonsterInfo.uRecoveryTime * 2.133333333333333;
				if ( v80 * 307.2 > (double)v81 || pActor->pMonsterInfo.uMovementType == 5 )
				{
					v64 = (signed __int64)v47;
					Actor::AI_Stand(actor_id, target_pid, v64, &pDir);
				}
				else
				{
					Actor::AI_Pursue1(actor_id, target_pid, actor_id, (signed __int64)v47, &pDir);
				}
			}
			else
			{
				Actor::AI_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 *pActor; // 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 *pPlayer; // [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);
  pPlayer = pParty->pPlayers;
  dword_50C998_turnbased_icon_1A = 8 * pIconsFrameTable->pIcons[uIconID_TurnStart].uAnimLength;
  dword_50C994 = 0;
  this->field_10 = 100;
  this->field_0 = 0;
  this->field_8 = 64;
  this->field_4 = 1;
  this->uActorQueueSize = 0;
  v3 = 0;
  do
  {
    if ( pPlayer->CanAct() )
    {
      *(&this->field_0 + 4 * (this->uActorQueueSize + 2)) = PID(OBJECT_Player,v3);
      this->pQueue[this->uActorQueueSize].field_C = 2;
      this->pQueue[this->uActorQueueSize].uActionLength = 0;
      pParty->pTurnBasedPlayerRecoveryTimes[this->uActorQueueSize++] = 0;
    }
    ++pPlayer;
    ++v3;
  }
  while ( pPlayer <= &pParty->pPlayers[3] );
  v35 = this->uActorQueueSize;
  v4 = v35;
  v40b = v35;
  if ( v40b < v40b + ai_arrays_size )
  {
    v34 = (int *)ai_near_actors_ids.data();
    do
    {
      v37 = *v34;
      v5 = v37;
      pActor = &pActors[v37];
      if ( v37 != 10 )
      {
        if ( pActors[v37].CanAct() )
        {
          v7 = pActor->uAttributes;
          if ( v7 & 0x8000 )
          {
            v8 = ai_near_actors_targets_pid[v5];
            LOBYTE(v7) = v7 | 0x80;
            pActor->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);
            *(&this->field_0 + 4 * (this->uActorQueueSize + 2)) = v33;
            this->pQueue[this->uActorQueueSize].field_C = 2;
            this->pQueue[this->uActorQueueSize++].uActionLength = 0;
          }
        }
        v4 = v35;
      }
      ++v40b;
      ++v34;
    }
    while ( v40b < v4 + ai_arrays_size );
    v2 = 0;
  }
  v11 = __OFSUB__(this->uActorQueueSize, v2);
  v9 = this->uActorQueueSize == v2;
  v10 = ((this->uActorQueueSize - v2) & 0x80000000u) != 0;
  v37 = v2;
  v40b = v2;
  if ( !((unsigned __int8)(v10 ^ v11) | v9) )
  {
    v12 = (char *)&this->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);
        *(int *)v12 = v16;
        goto LABEL_26;
      }
      v15 = v37++;
      *(&a3.uDistance + v15) = v40b;
LABEL_26:
      ++v40b;
      v12 += 16;
      if ( v40b >= this->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;
    *(int *)v12 = v16;
    goto LABEL_26;
  }
LABEL_27:
  v18 = 0;
  if ( (signed int)v37 > (signed int)v2 )
  {
    do
    {
      __debugbreak();
      *(&v31.uDistance + v18) = pParty->pPlayers[*(&this->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;
          this->pQueue[v28].field_4 = v27;
        }
        while ( v10 ^ v11 );
      }
    }
  }
  return this->_404544();
}