changeset 1650:b0a2b8525483

Merge
author Grumpy7
date Wed, 18 Sep 2013 06:32:15 +0200
parents d25389b91029 (current diff) bac69d9157b6 (diff)
children d11b5669f089 56847118d50c
files IndoorCamera.cpp IndoorCamera.h OutdoorCamera.cpp OutdoorCamera.h UI/UICharacter.cpp mm7_data.h
diffstat 46 files changed, 2565 insertions(+), 2944 deletions(-) [+]
line wrap: on
line diff
--- a/Actor.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/Actor.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -17,7 +17,6 @@
 #include "ObjectList.h"
 #include "Overlays.h"
 #include "Events.h"
-#include "IndoorCamera.h"
 #include "FactionTable.h"
 #include "TurnEngine.h"
 #include "MapInfo.h"
@@ -26,6 +25,7 @@
 #include "LOD.h"
 #include "Party.h"
 #include "GUIWindow.h"
+#include "Outdoor_stuff.h"
 
 #include "MM7.h"
 #include "SpriteObject.h"
@@ -2927,7 +2927,7 @@
 
   actor->uCurrentActionLength = 8 * pSpriteFrameTable->pSpriteSFrames[actor->pSpriteIDs[ANIM_Bored]].uAnimLength;
 
-  v7 = stru_5C6E00->Atan2(actor->vPosition.x - pIndoorCamera->pos.x, actor->vPosition.y - pIndoorCamera->pos.y);
+  v7 = stru_5C6E00->Atan2(actor->vPosition.x - pGame->pIndoorCameraD3D->vPartyPos.x, actor->vPosition.y - pGame->pIndoorCameraD3D->vPartyPos.y);
   v9 = stru_5C6E00->uIntegerPi + actor->uYawAngle + ((signed int)stru_5C6E00->uIntegerPi >> 3) - v7;
 
   if ( BYTE1(v9) & 7 )      // turned away - just stand
@@ -3144,8 +3144,8 @@
     v18 = -16;
 
   v7->uYawAngle = stru_5C6E00->Atan2(
-                    pParty->vPosition.x + fixpoint_sub0(stru_5C6E00->Cos(v18 + stru_5C6E00->uIntegerPi + v10->uYawAngle), v10->uDistanceXZ) - v7->vPosition.x,
-                    pParty->vPosition.y + fixpoint_sub0(stru_5C6E00->Sin(v18 + stru_5C6E00->uIntegerPi + v10->uYawAngle), v10->uDistanceXZ) - v7->vPosition.y);
+                    pParty->vPosition.x + fixpoint_mul(stru_5C6E00->Cos(v18 + stru_5C6E00->uIntegerPi + v10->uYawAngle), v10->uDistanceXZ) - v7->vPosition.x,
+                    pParty->vPosition.y + fixpoint_mul(stru_5C6E00->Sin(v18 + stru_5C6E00->uIntegerPi + v10->uYawAngle), v10->uDistanceXZ) - v7->vPosition.y);
   if ( uActionLength )
     v7->uCurrentActionLength = uActionLength;
   else
--- a/AudioPlayer.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/AudioPlayer.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -1494,11 +1494,11 @@
       a1.vWorldPosition.z = v11;
       if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
       {
-        v16 = pBLVRenderParams->fCosineNegX;
-        v17 = pBLVRenderParams->fSineNegX;
-        v55 = pBLVRenderParams->fCosineY;
-        v56 = pBLVRenderParams->fSineY;
-        if ( pBLVRenderParams->sPartyRotX )
+        v16 = pGame->pIndoorCameraD3D->fRotationXCosine;
+        v17 = pGame->pIndoorCameraD3D->fRotationXSine;
+        v55 = pGame->pIndoorCameraD3D->fRotationYCosine;
+        v56 = pGame->pIndoorCameraD3D->fRotationYSine;
+        if (pGame->pIndoorCameraD3D->sRotationX)
         {
           v58 = a1.vWorldPosition.x - (double)pParty->vPosition.x;
           *(float *)&uNumRepeats = a1.vWorldPosition.y - (double)pParty->vPosition.y;
--- a/CastSpellInfo.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/CastSpellInfo.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -1349,9 +1349,9 @@
 			else
 			{
 				v155 = stru_5C6E00->Cos(pParty->sRotationY);
-				uRequiredMana = pParty->vPosition.x + fixpoint_sub0(2048, v155);
+				uRequiredMana = pParty->vPosition.x + fixpoint_mul(2048, v155);
 				v156 = stru_5C6E00->Sin(pParty->sRotationY);
-				LODWORD(v727) = pParty->vPosition.y + fixpoint_sub0(2048, v156);
+				LODWORD(v727) = pParty->vPosition.y + fixpoint_mul(2048, v156);
 				v154 = pParty->vPosition.z;
 			}
 			unsigned __int64 k = 0;
@@ -1656,9 +1656,9 @@
 			else
 			{
 				v212 = stru_5C6E00->Cos(pParty->sRotationY);
-				LODWORD(v718) = pParty->vPosition.x + fixpoint_sub0(2048, v212);
+				LODWORD(v718) = pParty->vPosition.x + fixpoint_mul(2048, v212);
 				v213 = stru_5C6E00->Sin(pParty->sRotationY);
-				v214 = fixpoint_sub0(2048, v213);
+				v214 = fixpoint_mul(2048, v213);
 				v211 = pParty->vPosition.z;
 				v713 = pParty->vPosition.y + v214;
 				v208 = LODWORD(v725);
--- a/DecalBuilder.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/DecalBuilder.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -686,10 +686,10 @@
 
     float v15;
     if (fabs(z_bias) < 1e-5)
-      v15 = 1.0 - 1.0 / ((1.0f / get_shading_dist_mist()) * pDecal->pVertices[i].vWorldViewPosition.x * 1000.0);
+      v15 = 1.0 - 1.0 / ((1.0f / pGame->pIndoorCameraD3D->GetShadingDistMist()) * pDecal->pVertices[i].vWorldViewPosition.x * 1000.0);
      else
      {
-      v15 = 1.0 - 1.0 / ((1.0f / get_shading_dist_mist()) * pDecal->pVertices[i].vWorldViewPosition.x * 1000.0) - z_bias;
+      v15 = 1.0 - 1.0 / ((1.0f / pGame->pIndoorCameraD3D->GetShadingDistMist()) * pDecal->pVertices[i].vWorldViewPosition.x * 1000.0) - z_bias;
       if (v15 < 0.000099999997)
         v15 = 0.000099999997;
      }
--- a/Events2D.h	Wed Sep 18 06:30:53 2013 +0200
+++ b/Events2D.h	Wed Sep 18 06:32:15 2013 +0200
@@ -16,8 +16,8 @@
   BuildingType_BodyGuild = 11,
   BuildingType_LightGuild = 12,
   BuildingType_DarkGuild = 13,
-  BuildingType_14 = 14,
-  BuildingType_15 = 15,
+  BuildingType_ElementalGuild = 14,
+  BuildingType_SelfGuild = 15,
   BuildingType_16 = 16,
   BuildingType_TownHall = 17,
   BuildingType_18 = 18,
--- a/GUIWindow.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/GUIWindow.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -7,7 +7,6 @@
 #include "Party.h"
 #include "LOD.h"
 #include "Keyboard.h"
-#include "IndoorCamera.h"
 #include "Math.h"
 #include "VideoPlayer.h"
 #include "MapInfo.h"
@@ -26,6 +25,8 @@
 #include "Autonotes.h"
 #include "Awards.h"
 #include "Chest.h"
+#include "Outdoor.h"
+#include "Game.h"
 
 
 #include "mm7_data.h"
@@ -296,9 +297,8 @@
 		dword_5C35D4 = 0;
 		if ( bFlipOnExit )
 		{
-			pIndoorCamera->sRotationY = (stru_5C6E00->uIntegerDoublePi - 1) & (stru_5C6E00->uIntegerPi
-																			+ pIndoorCamera->sRotationY);
-			pParty->sRotationY = pIndoorCamera->sRotationY;
+          pParty->sRotationY = (stru_5C6E00->uIntegerDoublePi - 1) & (stru_5C6E00->uIntegerPi + pParty->sRotationY);
+          pGame->pIndoorCameraD3D->sRotationY = pParty->sRotationY;
 		}
 		pParty->uFlags |= 2u;
 		break;
@@ -985,9 +985,9 @@
     }
     return;
   }
-  if ( v4 || !dword_591080 )
+  if ( v4 || !dword_591080 )//на изумрудном острове заходит на корабле пока не выполнены квесты
   {
-    SimpleHouseAndBoatsDialog();
+    SimpleHouseDialog();
   }
   else
   {
--- a/Game.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/Game.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -17,7 +17,6 @@
 
 #include "Game.h"
 #include "Party.h"
-#include "IndoorCamera.h"
 #include "Viewport.h"
 #include "Time.h"
 #include "Outdoor.h"
@@ -74,14 +73,15 @@
   uFlags2 &= ~0x02;
   if ( pParty->_497FC5_check_party_perception_against_level() )
     uFlags2 |= 2u;
-  pIndoorCamera->sRotationX = pParty->sRotationX;
-  pIndoorCamera->sRotationY = pParty->sRotationY;
-  //pIndoorCamera->pos.x = pParty->vPosition.x - ((__int64)pParty->y_rotation_granularity * stru_5C6E00->SinCos(pIndoorCamera->sRotationY)) / 2048.0;//12552
-  //pIndoorCamera->pos.y = pParty->vPosition.y - ((__int64)pParty->y_rotation_granularity * stru_5C6E00->SinCos(pIndoorCamera->sRotationY)) / 2048.0;//800
-  pIndoorCamera->pos.x = pParty->vPosition.x - pParty->y_rotation_granularity * cosf(2 * 3.141592653589 * pIndoorCamera->sRotationY / 2048.0);
-  pIndoorCamera->pos.y = pParty->vPosition.y - pParty->y_rotation_granularity * sinf(2 * 3.141592653589 * pIndoorCamera->sRotationY / 2048.0);
-  pIndoorCamera->pos.z = pParty->vPosition.z + pParty->sEyelevel;//193, but real 353
-  pIndoorCamera->Initialize2();
+
+  pGame->pIndoorCameraD3D->sRotationX = pParty->sRotationX;
+  pGame->pIndoorCameraD3D->sRotationY = pParty->sRotationY;
+  pGame->pIndoorCameraD3D->vPartyPos.x = pParty->vPosition.x - pParty->y_rotation_granularity * cosf(2 * 3.141592653589 * pParty->sRotationY / 2048.0);
+  pGame->pIndoorCameraD3D->vPartyPos.y = pParty->vPosition.y - pParty->y_rotation_granularity * sinf(2 * 3.141592653589 * pParty->sRotationY / 2048.0);
+  pGame->pIndoorCameraD3D->vPartyPos.z = pParty->vPosition.z + pParty->sEyelevel;//193, but real 353
+
+  //pIndoorCamera->Initialize2();
+  pIndoorCameraD3D->CalculateRotations(pParty->sRotationX, pParty->sRotationY);
   pIndoorCameraD3D->CreateWorldMatrixAndSomeStuff();
   pIndoorCameraD3D->_4374E8_ProllyBuildFrustrum();
 
--- a/Indoor.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/Indoor.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -29,7 +29,6 @@
 #include "TurnEngine.h"
 #include "PaletteManager.h"
 #include "MapInfo.h"
-#include "IndoorCamera.h"
 #include "Lights.h"
 
 #include "mm7_data.h"
@@ -94,7 +93,7 @@
 
 
 //----- (0043F39E) --------------------------------------------------------
-void __fastcall PrepareDrawLists_BLV(IndoorLocation_drawstru *_this)
+void __fastcall PrepareDrawLists_BLV()
 {
   //int *v1; // ecx@1
   //double v2; // ST30_8@3
@@ -109,11 +108,10 @@
   //unsigned __int8 v11; // [sp+1Ch] [bp-4h]@3
   //signed int v12; // [sp+1Ch] [bp-4h]@8
 
-  pBLVRenderParams->Reset(_this);
+  pBLVRenderParams->Reset();
   pMobileLightsStack->uNumLightsActive = 0;
   //uNumMobileLightsApplied = 0;
   uNumDecorationsDrawnThisFrame = 0;
-  _unused000 = 0;
   uNumSpritesDrawnThisFrame = 0;
   uNumBillboardsToDraw = 0;
 
@@ -127,9 +125,9 @@
     //LOBYTE(v1) = byte_4E94D0;
     //v4 = pParty->flt_TorchlightColorR + 6.7553994e15;
     //v3 = pParty->flt_TorchlightColorG + 6.7553994e15;
-    pMobileLightsStack->AddLight(pBLVRenderParams->vPartyPos.x,
-                                 pBLVRenderParams->vPartyPos.y,
-                                 pBLVRenderParams->vPartyPos.z,
+    pMobileLightsStack->AddLight(pGame->pIndoorCameraD3D->vPartyPos.x,
+                                 pGame->pIndoorCameraD3D->vPartyPos.y,
+                                 pGame->pIndoorCameraD3D->vPartyPos.z,
                                  pBLVRenderParams->uPartySectorID,
                                  v5,
                                  floorf(pParty->flt_TorchlightColorR + 0.5f),
@@ -165,22 +163,22 @@
 
 
 //----- (004407D9) --------------------------------------------------------
-int BLVRenderParams::Reset(IndoorLocation_drawstru *a2)
+void BLVRenderParams::Reset()
 {
-  IndoorLocation_drawstru *v2; // ebx@1
-  int v4; // ST08_4@1
-  int v5; // ST04_4@1
-  int v6; // ST00_4@1
+  //IndoorLocation_drawstru *v2; // ebx@1
+  //int v4; // ST08_4@1
+  //int v5; // ST04_4@1
+  //int v6; // ST00_4@1
   int v7; // eax@1
   int v8; // ST08_4@2
   int v9; // ST04_4@2
   int v10; // ST00_4@2
-  unsigned int v11; // edi@4
-  unsigned int v12; // ecx@4
-  int v13; // edx@4
-  signed int v14; // ecx@4
-  unsigned int v15; // edx@4
-  unsigned int v16; // eax@4
+  //unsigned int v11; // edi@4
+  //unsigned int v12; // ecx@4
+  //int v13; // edx@4
+  //signed int v14; // ecx@4
+  //unsigned int v15; // edx@4
+  //unsigned int v16; // eax@4
   double v17; // st7@5
   int v18; // eax@5
   double v19; // st7@5
@@ -192,56 +190,68 @@
   int v25; // eax@5
   int v26; // eax@5
   signed int v27; // eax@6
-  int result; // eax@6
+  //int result; // eax@6
   int v29; // [sp+24h] [bp+8h]@5
 
-  v2 = a2;
-  this->field_0_timer_ = a2->field_0_timer;
-  this->uFlags = a2->uFlags;
-  this->vPartyPos.x = a2->vPosition.x;
-  this->vPartyPos.y = a2->vPosition.y;
-  this->vPartyPos.z = a2->vPosition.z;
-  v4 = this->vPartyPos.z;
-  v5 = this->vPartyPos.y;
-  this->sPartyRotY = a2->sRotationY;
-  v6 = this->vPartyPos.x;
-  this->sPartyRotX = a2->sRotationX;
-  v7 = pIndoor->GetSector(v6, v5, v4);
+  this->field_0_timer_ = pEventTimer->uTotalGameTimeElapsed;
+
+  pGame->pIndoorCameraD3D->debug_flags = 0;
+  if (viewparams->draw_sw_outlines)
+    pGame->pIndoorCameraD3D->debug_flags |= BLV_RENDER_DRAW_SW_OUTLINES;
+  if (viewparams->draw_d3d_outlines)
+    pGame->pIndoorCameraD3D->debug_flags |= BLV_RENDER_DRAW_D3D_OUTLINES;
+
+  //v2 = a2;
+  //this->field_0_timer_ = a2->field_0_timer;
+  //this->uFlags = a2->uFlags;
+  //this->vPartyPos.x = a2->vPosition.x;
+  //this->vPartyPos.y = a2->vPosition.y;
+  //this->vPartyPos.z = a2->vPosition.z;
+  //v4 = this->vPartyPos.z;
+  //v5 = this->vPartyPos.y;
+  //this->sPartyRotY = a2->sRotationY;
+  //v6 = this->vPartyPos.x;
+  //this->sPartyRotX = a2->sRotationX;
+  v7 = pIndoor->GetSector(pGame->pIndoorCameraD3D->vPartyPos.x,
+                          pGame->pIndoorCameraD3D->vPartyPos.y,
+                          pGame->pIndoorCameraD3D->vPartyPos.z);
   this->uPartySectorID = v7;
   if ( !v7 )
   {
-    v8 = this->vPartyPos.z;
+    __debugbreak(); // shouldnt happen, please provide savegame
+    /*v8 = this->vPartyPos.z;
     this->vPartyPos.x = pParty->vPosition.x;
     v9 = pParty->vPosition.y;
     v10 = this->vPartyPos.x;
-    this->vPartyPos.y = pParty->vPosition.y;
+    this->vPartyPos.y = pParty->vPosition.y;*/
     this->uPartySectorID = pIndoor->GetSector(v10, v9, v8);
   }
   if ( pRenderer->pRenderD3D )
   {
-    this->sCosineY = stru_5C6E00->Cos(this->sPartyRotY);
-    this->sSineY = stru_5C6E00->Sin(this->sPartyRotY);
-    this->sCosineNegX = stru_5C6E00->Cos(-this->sPartyRotX);
-    this->sSineNegX = stru_5C6E00->Sin(-this->sPartyRotX);
-    this->fCosineY = cos((3.141592653589793 + 3.141592653589793) * (double)this->sPartyRotY * 0.00048828125);
-    this->fSineY = sin((3.141592653589793 + 3.141592653589793) * (double)this->sPartyRotY * 0.00048828125);
-    this->fCosineNegX = cos((3.141592653589793 + 3.141592653589793) * (double)-this->sPartyRotX * 0.00048828125);
-    this->fSineNegX = sin((3.141592653589793 + 3.141592653589793) * (double)-this->sPartyRotX * 0.00048828125);
-    this->field_64 = a2->field_3C;
-    v11 = this->uViewportW;
-    v12 = this->uViewportX;
-    v13 = this->uViewportZ - v12;
-    v14 = this->uViewportZ + v12;
-    this->field_70 = v13 + 1;
-    v15 = this->uViewportY;
-    this->uViewportHeight = v11 - v15 + 1;
-    v16 = this->uViewportW;
-    this->uViewportCenterX = v14 >> 1;
-    this->uViewportCenterY = (signed int)(v16 + v15) >> 1;
+    //this->sCosineY = stru_5C6E00->Cos(pGame->pIndoorCameraD3D->sRotationY);
+    //this->sSineY = stru_5C6E00->Sin(pGame->pIndoorCameraD3D->sRotationY);
+    //this->sCosineNegX = stru_5C6E00->Cos(-pGame->pIndoorCameraD3D->sRotationX);
+    //this->sSineNegX = stru_5C6E00->Sin(-pGame->pIndoorCameraD3D->sRotationX);
+    //this->fCosineY = cos((3.141592653589793 + 3.141592653589793) * (double)pGame->pIndoorCameraD3D->sRotationY * 0.00048828125);
+    //this->fSineY = sin((3.141592653589793 + 3.141592653589793) * (double)pGame->pIndoorCameraD3D->sRotationY * 0.00048828125);
+    //this->fCosineNegX = cos((3.141592653589793 + 3.141592653589793) * (double)-pGame->pIndoorCameraD3D->sRotationX * 0.00048828125);
+    //this->fSineNegX = sin((3.141592653589793 + 3.141592653589793) * (double)-pGame->pIndoorCameraD3D->sRotationX * 0.00048828125);
+    this->field_64 = pViewport->field_30;
+    
+    this->uViewportX = pViewport->uScreen_TL_X;
+    this->uViewportY = pViewport->uScreen_TL_Y;
+    this->uViewportZ = pViewport->uScreen_BR_X;
+    this->uViewportW = pViewport->uScreen_BR_Y;
+
+    this->uViewportWidth = uViewportZ - uViewportX + 1;
+    this->uViewportHeight = uViewportW - uViewportY + 1;
+    this->uViewportCenterX = (uViewportZ + uViewportX) / 2;
+    this->uViewportCenterY = (uViewportY + uViewportW) / 2;
   }
   else
   {
-    this->sCosineY = stru_5C6E00->Cos(-this->sPartyRotY);
+    __debugbreak(); // no sw
+    /*this->sCosineY = stru_5C6E00->Cos(-this->sPartyRotY);
     this->sSineY = stru_5C6E00->Sin(-this->sPartyRotY);
     this->sCosineNegX = stru_5C6E00->Cos(-this->sPartyRotX);
     this->sSineNegX = stru_5C6E00->Sin(-this->sPartyRotX);
@@ -264,28 +274,24 @@
     v29 = v25;
     v26 = this->field_64;
     this->uViewportCenterX = (signed int)(v24 + v23) >> 1;
-    this->uViewportCenterY = this->uViewportW - ((unsigned __int64)(v26 * (signed __int64)v29) >> 16);
+    this->uViewportCenterY = this->uViewportW - ((unsigned __int64)(v26 * (signed __int64)v29) >> 16);*/
   }
-  v27 = (unsigned int)(signed __int64)((double)this->field_70 * 0.5 / tan((double)(v2->field_1C_mb_fov >> 1) * 0.01745329)
-                                     + 0.5) << 16;
-  this->field_40 = v27;
-  this->field_44 = 0x100000000i64 / v27;
-  this->pRenderTarget = v2->pRenderTarget;
-  this->uTargetWidth = v2->uTargetWidth;
-  this->uTargetHeight = v2->uTargetHeight;
-  this->uViewportX = v2->uViewportX;
-  this->uViewportY = v2->uViewportY;
-  this->uViewportZ = v2->uViewportZ;
-  this->uViewportW = v2->uViewportW;
-  this->pTargetZBuffer = v2->pTargetZ;
-  result = 0;
+  //v27 = (unsigned int)(signed __int64)((double)this->uViewportWidth * 0.5
+  //                                             / tan((double)(v2->fov_deg >> 1) * 0.01745329)
+  //                                             + 0.5) << 16;
+  extern float _calc_fov(int viewport_width, int angle_degree);
+  this->fov_rad_fixpoint = fixpoint_from_int(_calc_fov(uViewportWidth, 65), 0);
+  this->fov_rad_inv_fixpoint = 0x100000000i64 / this->fov_rad_fixpoint;
+  this->pRenderTarget = pRenderer->pTargetSurface;
+  this->uTargetWidth = 640;
+  this->uTargetHeight = 480;
+  this->pTargetZBuffer = pRenderer->pActiveZBuffer;
   this->field_8C = 0;
   this->field_84 = 0;
   this->uNumFacesRenderedThisFrame = 0;
   this->field_88 = 0;
   pBLVRenderParams->field_90 = 64;
   pBLVRenderParams->field_94 = 6;
-  return result;
 }
 
 //----- (00440B44) --------------------------------------------------------
@@ -316,6 +322,8 @@
   }
 }
 
+
+/*
 //----- (00440BED) --------------------------------------------------------
 void __fastcall sub_440BED(IndoorLocation_drawstru *_this)
 {
@@ -365,7 +373,7 @@
     }
   }
 }
-
+*/
 
 
 
@@ -374,27 +382,26 @@
 void IndoorLocation::Draw()
 {
   //int v0; // eax@1
-  IndoorLocation_drawstru _this; // [sp+0h] [bp-4Ch]@5
+  //IndoorLocation_drawstru _this; // [sp+0h] [bp-4Ch]@5
   int v2; // [sp+44h] [bp-8h]@5
   int v3; // [sp+48h] [bp-4h]@5
 
-  _this.uFlags = 0;
+  /*_this.uFlags = 0;
   if (viewparams->draw_sw_outlines)
-    _this.uFlags |= INDOOR_CAMERA_DRAW_SW_OUTLINES;
+    _this.uFlags |= BLV_RENDER_DRAW_SW_OUTLINES;
   if (viewparams->draw_d3d_outlines)
-    _this.uFlags |= INDOOR_CAMERA_DRAW_D3D_OUTLINES;
-
-  _this.uFlags |= INDOOR_CAMERA_DRAW_D3D_OUTLINES;
-  _this.uFlags |= INDOOR_CAMERA_DRAW_SW_OUTLINES;
-  //INDOOR_CAMERA_DRAW_TERRAIN_OUTLINES
+    _this.uFlags |= BLV_RENDER_DRAW_D3D_OUTLINES;
+  
+  _this.uFlags |= BLV_RENDER_DRAW_SW_OUTLINES;
+  _this.uFlags |= BLV_RENDER_DRAW_D3D_OUTLINES;
 
   _this.field_0_timer = pEventTimer->uTotalGameTimeElapsed;
-  _this.field_1C_mb_fov = 65;
-  _this.vPosition.x = pParty->vPosition.x - fixpoint_sub0(stru_5C6E00->Cos(pParty->sRotationY), pParty->y_rotation_granularity);
-  _this.vPosition.y = pParty->vPosition.y - fixpoint_sub0(stru_5C6E00->Sin(pParty->sRotationY), pParty->y_rotation_granularity);
-  _this.vPosition.z = pParty->vPosition.z + pParty->sEyelevel;
-  _this.sRotationX = pParty->sRotationX;
-  _this.sRotationY = pParty->sRotationY;
+  //_this.fov_deg = 65;
+  //_this.vPosition.x = pParty->vPosition.x - fixpoint_mul(stru_5C6E00->Cos(pParty->sRotationY), pParty->y_rotation_granularity);
+  //_this.vPosition.y = pParty->vPosition.y - fixpoint_mul(stru_5C6E00->Sin(pParty->sRotationY), pParty->y_rotation_granularity);
+  //_this.vPosition.z = pParty->vPosition.z + pParty->sEyelevel;
+  //_this.sRotationX = pParty->sRotationX;
+  //_this.sRotationY = pParty->sRotationY;
   _this.pRenderTarget = pRenderer->pTargetSurface;
   _this.uViewportX = pViewport->uScreen_TL_X;
   _this.uViewportY = pViewport->uScreen_TL_Y;
@@ -404,8 +411,16 @@
 
   _this.uTargetWidth = 640;
   _this.uTargetHeight = 480;
-  _this.pTargetZ = pRenderer->pActiveZBuffer;
-  sub_440BED(&_this);
+  _this.pTargetZ = pRenderer->pActiveZBuffer;*/
+
+  //sub_440BED(&_this); -- inlined
+  {
+    PrepareDrawLists_BLV();
+    if (pBLVRenderParams->uPartySectorID)
+      IndoorLocation::ExecDraw(pRenderer->pRenderD3D != 0);
+    pRenderer->DrawBillboardList_BLV();
+  }
+
   pParty->uFlags &= ~2;
   pGame->DrawParticles();
   trail_particle_generator.UpdateParticles();
@@ -701,16 +716,16 @@
   if (nodes[node_id].uFaceID == uFaceID)
     return;
   if (!node_id &&
-      pBLVRenderParams->vPartyPos.x >= pFace->pBounding.x1 - 16 &&  // we are probably standing at the portal plane
-      pBLVRenderParams->vPartyPos.x <= pFace->pBounding.x2 + 16 &&
-      pBLVRenderParams->vPartyPos.y >= pFace->pBounding.y1 - 16 &&
-      pBLVRenderParams->vPartyPos.y <= pFace->pBounding.y2 + 16 &&
-      pBLVRenderParams->vPartyPos.z >= pFace->pBounding.z1 - 16 &&
-      pBLVRenderParams->vPartyPos.z <= pFace->pBounding.z2 + 16 )
+      pGame->pIndoorCameraD3D->vPartyPos.x >= pFace->pBounding.x1 - 16 &&  // we are probably standing at the portal plane
+      pGame->pIndoorCameraD3D->vPartyPos.x <= pFace->pBounding.x2 + 16 &&
+      pGame->pIndoorCameraD3D->vPartyPos.y >= pFace->pBounding.y1 - 16 &&
+      pGame->pIndoorCameraD3D->vPartyPos.y <= pFace->pBounding.y2 + 16 &&
+      pGame->pIndoorCameraD3D->vPartyPos.z >= pFace->pBounding.z1 - 16 &&
+      pGame->pIndoorCameraD3D->vPartyPos.z <= pFace->pBounding.z2 + 16 )
   {
-    if ( abs(pFace->pFacePlane_old.dist + pBLVRenderParams->vPartyPos.x * pFace->pFacePlane_old.vNormal.x
-                                        + pBLVRenderParams->vPartyPos.y * pFace->pFacePlane_old.vNormal.y
-                                        + pBLVRenderParams->vPartyPos.z * pFace->pFacePlane_old.vNormal.z) <= 589824 ) // we sure are standing at the portal plane
+    if ( abs(pFace->pFacePlane_old.dist + pGame->pIndoorCameraD3D->vPartyPos.x * pFace->pFacePlane_old.vNormal.x
+                                        + pGame->pIndoorCameraD3D->vPartyPos.y * pFace->pFacePlane_old.vNormal.y
+                                        + pGame->pIndoorCameraD3D->vPartyPos.z * pFace->pFacePlane_old.vNormal.z) <= 589824 ) // we sure are standing at the portal plane
     {
       pTransitionSector = pFace->uSectorID;
       if ( nodes[0].uSectorID == pTransitionSector )  // draw back sector
@@ -728,9 +743,9 @@
     }
   }
 
-  v9 = pFace->pFacePlane_old.vNormal.x * (pIndoor->pVertices[pFace->pVertexIDs[0]].x - pBLVRenderParams->vPartyPos.x)
-     + pFace->pFacePlane_old.vNormal.y * (pIndoor->pVertices[pFace->pVertexIDs[0]].y - pBLVRenderParams->vPartyPos.y)
-     + pFace->pFacePlane_old.vNormal.z * (pIndoor->pVertices[pFace->pVertexIDs[0]].z - pBLVRenderParams->vPartyPos.z);
+  v9 = pFace->pFacePlane_old.vNormal.x * (pIndoor->pVertices[pFace->pVertexIDs[0]].x - pGame->pIndoorCameraD3D->vPartyPos.x)
+     + pFace->pFacePlane_old.vNormal.y * (pIndoor->pVertices[pFace->pVertexIDs[0]].y - pGame->pIndoorCameraD3D->vPartyPos.y)
+     + pFace->pFacePlane_old.vNormal.z * (pIndoor->pVertices[pFace->pVertexIDs[0]].z - pGame->pIndoorCameraD3D->vPartyPos.z);
   if (nodes[node_id].uSectorID != pFace->uSectorID)
     v9 = -v9;
   if (v9 >= 0)
@@ -803,7 +818,7 @@
       nodes[num_nodes].viewing_portal_id = uFaceID;
       AddBspNodeToRenderList(++num_nodes - 1);
     }
-    if (pBLVRenderParams->uFlags & INDOOR_CAMERA_DRAW_SW_OUTLINES)
+    if (pGame->pIndoorCameraD3D->debug_flags & BLV_RENDER_DRAW_SW_OUTLINES)
       pGame->pIndoorCameraD3D->PrepareAndDrawDebugOutline(pFace, 0x1E1EFF);
     //pGame->pIndoorCameraD3D->DebugDrawPortal(pFace);
   }
@@ -845,16 +860,16 @@
     if ( uFaceID == *((short *)v5 + 2982) )
       return;
     if (!node_id
-      && pBLVRenderParams->vPartyPos.x >= v4->pBounding.x1 - 16
-      && pBLVRenderParams->vPartyPos.x <= v4->pBounding.x2 + 16
-      && pBLVRenderParams->vPartyPos.y >= v4->pBounding.y1 - 16
-      && pBLVRenderParams->vPartyPos.y <= v4->pBounding.y2 + 16
-      && pBLVRenderParams->vPartyPos.z >= v4->pBounding.z1 - 16
-      && pBLVRenderParams->vPartyPos.z <= v4->pBounding.z2 + 16 )
+      && pGame->pIndoorCameraD3D->vPartyPos.x >= v4->pBounding.x1 - 16
+      && pGame->pIndoorCameraD3D->vPartyPos.x <= v4->pBounding.x2 + 16
+      && pGame->pIndoorCameraD3D->vPartyPos.y >= v4->pBounding.y1 - 16
+      && pGame->pIndoorCameraD3D->vPartyPos.y <= v4->pBounding.y2 + 16
+      && pGame->pIndoorCameraD3D->vPartyPos.z >= v4->pBounding.z1 - 16
+      && pGame->pIndoorCameraD3D->vPartyPos.z <= v4->pBounding.z2 + 16 )
     {
-      if ( abs(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) <= 589824 )
+      if ( abs(v4->pFacePlane_old.dist + pGame->pIndoorCameraD3D->vPartyPos.x * v4->pFacePlane_old.vNormal.x
+                                       + pGame->pIndoorCameraD3D->vPartyPos.y * v4->pFacePlane_old.vNormal.y
+                                       + pGame->pIndoorCameraD3D->vPartyPos.z * v4->pFacePlane_old.vNormal.z) <= 589824 )
       {
         v6 = v21->uSectorID;
         if ( v3->nodes[0].uSectorID == v6 )
@@ -877,9 +892,9 @@
       v5 = v20;
     }
     v8 = &pIndoor->pVertices[*v4->pVertexIDs];
-    v9 = v4->pFacePlane_old.vNormal.x * ((signed __int16)*(int *)&v8->x - pBLVRenderParams->vPartyPos.x)
-       + v4->pFacePlane_old.vNormal.y * ((signed __int16)(*(int *)&v8->x >> 16) - pBLVRenderParams->vPartyPos.y)
-       + v4->pFacePlane_old.vNormal.z * (v8->z - pBLVRenderParams->vPartyPos.z);
+    v9 = v4->pFacePlane_old.vNormal.x * (v8->x - pGame->pIndoorCameraD3D->vPartyPos.x)
+       + v4->pFacePlane_old.vNormal.y * (v8->y - pGame->pIndoorCameraD3D->vPartyPos.y)
+       + v4->pFacePlane_old.vNormal.z * (v8->z - pGame->pIndoorCameraD3D->vPartyPos.z);
     if ( *((short *)v5 + 2004) != v4->uSectorID )
       v9 = -v9;
     if ( v9 < 0 )
@@ -2558,16 +2573,16 @@
                         HIDWORD(v33) = v32 >> 16;*/
                         //fixpoint_div(v1->x - v2->x, v1->y - v2->y);
                         //_a58 = v33 / (v1->y - v2->y);
-                        //_a59 = fixpoint_sub0(_a58, sY - v2->y);
+                        //_a59 = fixpoint_mul(_a58, sY - v2->y);
             auto x_div_y = fixpoint_div(v1->x - v2->x, v1->y - v2->y);
-            auto res = fixpoint_sub0(x_div_y, sY - v2->y);  // a / b * c  - looks like projection 
+            auto res = fixpoint_mul(x_div_y, sY - v2->y);  // a / b * c  - looks like projection 
             if (res + v2->x > sX)
               ++v54;
           }
           else
           {
             auto x_div_y = fixpoint_div(v2->x - v1->x, v2->y - v1->y);
-            auto res = fixpoint_sub0(x_div_y, sY - v1->y);
+            auto res = fixpoint_mul(x_div_y, sY - v1->y);
 
             if (res + v1->x > sX)
               ++v54;
@@ -2578,7 +2593,7 @@
                         LODWORD(v33) = v32 << 16;
                         HIDWORD(v33) = v32 >> 16;
                         _a58 = v33 / (v2->y - v1->y);
-                        _a59 = fixpoint_sub0(_a58, sY - v1->y);
+                        _a59 = fixpoint_mul(_a58, sY - v1->y);
 
                         if (_a59 + pVertices[k].x > sX)
                           ++v54;*/
@@ -3430,9 +3445,9 @@
         }
         else
         {
-          v30 = v0->vPosition.x + fixpoint_sub0(stru_721530.field_7C, stru_721530.direction.x);
-          v31 = v0->vPosition.y + fixpoint_sub0(stru_721530.field_7C, stru_721530.direction.y);
-          v32 = v0->vPosition.z + fixpoint_sub0(stru_721530.field_7C, stru_721530.direction.z);
+          v30 = v0->vPosition.x + fixpoint_mul(stru_721530.field_7C, stru_721530.direction.x);
+          v31 = v0->vPosition.y + fixpoint_mul(stru_721530.field_7C, stru_721530.direction.y);
+          v32 = v0->vPosition.z + fixpoint_mul(stru_721530.field_7C, stru_721530.direction.z);
         }
         v33 = collide_against_floor(v30, v31, v32, &stru_721530.uSectorID, &uFaceID);
         v34 = pIndoor->pFaces[uFaceID].uAttributes;
@@ -3457,12 +3472,12 @@
               goto LABEL_123;
             }
             //v58 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.direction.x) >> 16;
-            v0->vPosition.x += fixpoint_sub0(stru_721530.field_7C, stru_721530.direction.x);
+            v0->vPosition.x += fixpoint_mul(stru_721530.field_7C, stru_721530.direction.x);
             //v58 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.direction.y) >> 16;
-            v0->vPosition.y += fixpoint_sub0(stru_721530.field_7C, stru_721530.direction.y);
+            v0->vPosition.y += fixpoint_mul(stru_721530.field_7C, stru_721530.direction.y);
             //v58 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.direction.z) >> 16;
             v36 = stru_721530.uFaceID;
-            v0->vPosition.z += fixpoint_sub0(stru_721530.field_7C, stru_721530.direction.z);
+            v0->vPosition.z += fixpoint_mul(stru_721530.field_7C, stru_721530.direction.z);
             v0->uSectorID = LOWORD(stru_721530.uSectorID);
             stru_721530.field_70 += stru_721530.field_7C;
             v37 = PID_ID(v36);
@@ -3476,8 +3491,8 @@
                   v45 = stru_5C6E00->Atan2(
                           v0->vPosition.x - pLevelDecorations[v37].vPosition.x,
                           v0->vPosition.y - pLevelDecorations[v37].vPosition.y);
-                  v0->vVelocity.x = fixpoint_sub0(stru_5C6E00->Cos(v45), _this);
-                  v0->vVelocity.y = fixpoint_sub0(stru_5C6E00->Sin(v45), _this);
+                  v0->vVelocity.x = fixpoint_mul(stru_5C6E00->Cos(v45), _this);
+                  v0->vVelocity.y = fixpoint_mul(stru_5C6E00->Sin(v45), _this);
                   goto LABEL_119;
                 }
                 if ( PID_TYPE(v36) == OBJECT_BModel)
@@ -3506,9 +3521,9 @@
                     if ( (stru_721530.speed >> 3) > v61 )
                       v61 = stru_721530.speed >> 3;
 
-                    v0->vVelocity.x += fixpoint_sub0(v61, v38->pFacePlane_old.vNormal.x);
-                    v0->vVelocity.y += fixpoint_sub0(v61, v38->pFacePlane_old.vNormal.y);
-                    v0->vVelocity.z += fixpoint_sub0(v61, v38->pFacePlane_old.vNormal.z);
+                    v0->vVelocity.x += fixpoint_mul(v61, v38->pFacePlane_old.vNormal.x);
+                    v0->vVelocity.y += fixpoint_mul(v61, v38->pFacePlane_old.vNormal.y);
+                    v0->vVelocity.z += fixpoint_mul(v61, v38->pFacePlane_old.vNormal.z);
                     v41 = v38->uPolygonType;
                     if ( v41 != 4 && v41 != 3 )
                     {
@@ -3532,9 +3547,9 @@
                     EventProcessor(pIndoor->pFaceExtras[v38->uFaceExtraID].uEventID, 0, 1);
                 }
 LABEL_119:
-                v0->vVelocity.x = fixpoint_sub0(58500, v0->vVelocity.x);
-                v0->vVelocity.y = fixpoint_sub0(58500, v0->vVelocity.y);
-                v0->vVelocity.z = fixpoint_sub0(58500, v0->vVelocity.z);
+                v0->vVelocity.x = fixpoint_mul(58500, v0->vVelocity.x);
+                v0->vVelocity.y = fixpoint_mul(58500, v0->vVelocity.y);
+                v0->vVelocity.z = fixpoint_mul(58500, v0->vVelocity.z);
                 v22 = 0;
                 goto LABEL_120;
               }
@@ -4055,7 +4070,7 @@
           else
           {
             auto a_div_b = fixpoint_div(y - word_721390_ys[j], word_721390_ys[j + 1] - word_721390_ys[j]);
-            auto res = fixpoint_sub0((signed int)word_721460_xs[j + 1] - (signed int)word_721460_xs[j], a_div_b);
+            auto res = fixpoint_mul((signed int)word_721460_xs[j + 1] - (signed int)word_721460_xs[j], a_div_b);
 
             if (res + word_721460_xs[j] >= x)
                 ++v53;
@@ -4073,7 +4088,7 @@
           }
           else
           {
-            v21 = fixpoint_sub0(pFloor->zCalc1, x) + fixpoint_sub0(pFloor->zCalc2, y) + (short)(pFloor->zCalc3 >> 16);
+            v21 = fixpoint_mul(pFloor->zCalc1, x) + fixpoint_mul(pFloor->zCalc2, y) + (short)(pFloor->zCalc3 >> 16);
           }
           blv_floor_level[v55] = v21;
           blv_floor_id[v55] = pSector->pFloors[i];
@@ -4126,7 +4141,7 @@
                 else
                 {
                   auto a_div_b = fixpoint_div(y - word_721390_ys[j], word_721390_ys[j + 1] - word_721390_ys[j]);
-                  auto res = fixpoint_sub0(word_721460_xs[j + 1] - word_721460_xs[j], a_div_b);
+                  auto res = fixpoint_mul(word_721460_xs[j + 1] - word_721460_xs[j], a_div_b);
                   if (res + word_721460_xs[j] >= x)
                     ++v54;
                 }
@@ -4500,7 +4515,7 @@
     a2 = p->vPosition.y;
     a1a = p->vPosition.x;
     a3 = p->vPosition.z;
-    v4 = stru_5C6E00->Atan2(a1a - pBLVRenderParams->vPartyPos.x, a2 - pBLVRenderParams->vPartyPos.y);
+    v4 = stru_5C6E00->Atan2(a1a - pGame->pIndoorCameraD3D->vPartyPos.x, a2 - pGame->pIndoorCameraD3D->vPartyPos.y);
     LOWORD(v0) = p->uYawAngle;
     v5 = p->uCurrentActionAnimation;
     v6 = ((signed int)((char *)v0 + ((signed int)stru_5C6E00->uIntegerPi >> 3) - v4 + stru_5C6E00->uIntegerPi) >> 8) & 7;
@@ -4567,7 +4582,7 @@
       if ( v12 >= pBspRenderer->uNumVisibleNotEmptySectors )
         goto _continue;
     }
-    if ( !pGame->pIndoorCameraD3D->ApplyViewTransform_TrueIfStillVisible(a1a, a2, a3, &x, &y, &z, 1)
+    if ( !pGame->pIndoorCameraD3D->ApplyViewTransform_TrueIfStillVisible_BLV(a1a, a2, a3, &x, &y, &z, 1)
       || (v0 = (RenderBillboard *)abs(x), (signed int)v0 < abs(y)) )
       continue;
     pGame->pIndoorCameraD3D->Project(x, y, z, &v43, &a6);
@@ -4583,8 +4598,8 @@
     v0->uIndoorSectorID = a5;
     if ( v29 )
     {
-      LODWORD(v20) = pBLVRenderParams->field_40 << 16;
-      HIDWORD(v20) = pBLVRenderParams->field_40 >> 16;
+      LODWORD(v20) = pBLVRenderParams->fov_rad_fixpoint << 16;
+      HIDWORD(v20) = pBLVRenderParams->fov_rad_fixpoint >> 16;
       v21 = v20 / x;
       v0->_screenspace_x_scaler_packedfloat = (unsigned __int64)(v10->scale * v20 / x) >> 16;
       a5a = (unsigned __int64)(v10->scale * (signed __int64)v21) >> 16;
@@ -4714,8 +4729,8 @@
             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);
+            v6 = stru_5C6E00->Atan2(p->vPosition.x - pGame->pIndoorCameraD3D->vPartyPos.x,
+                                    p->vPosition.y - pGame->pIndoorCameraD3D->vPartyPos.y);
             LOWORD(v7) = p->uFacing;
             v8 = v30;
             v9 = ((signed int)(stru_5C6E00->uIntegerPi + ((signed int)stru_5C6E00->uIntegerPi >> 3) + v7 - v6) >> 8) & 7;
@@ -4750,7 +4765,7 @@
                 v1->uParticleTrailColorB,
                 byte_4E94D3);
             }
-            if ( pGame->pIndoorCameraD3D->ApplyViewTransform_TrueIfStillVisible(
+            if ( pGame->pIndoorCameraD3D->ApplyViewTransform_TrueIfStillVisible_BLV(
                    a1,
                    a2,
                    a3,
@@ -4864,8 +4879,10 @@
     pSector = &pIndoor->pSectors[node->uSectorID];
     pNode = &pIndoor->pNodes[uFirstNode];
     pFace = &pIndoor->pFaces[pSector->pFaceIDs[pNode->uCoplanarOffset]];
-    v5 = pFace->pFacePlane_old.dist + pBLVRenderParams->vPartyPos.x * pFace->pFacePlane_old.vNormal.x
-       + pBLVRenderParams->vPartyPos.y * pFace->pFacePlane_old.vNormal.y + pBLVRenderParams->vPartyPos.z * pFace->pFacePlane_old.vNormal.z;//plane equation
+    v5 = pFace->pFacePlane_old.dist +
+         pGame->pIndoorCameraD3D->vPartyPos.x * pFace->pFacePlane_old.vNormal.x +
+         pGame->pIndoorCameraD3D->vPartyPos.y * pFace->pFacePlane_old.vNormal.y +
+         pGame->pIndoorCameraD3D->vPartyPos.z * pFace->pFacePlane_old.vNormal.z;//plane equation
     if (pFace->Portal() && pFace->uSectorID != node->uSectorID )
       v5 = -v5;
     //v11 = v5 > 0;
@@ -4974,7 +4991,7 @@
         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);
+           - stru_5C6E00->Atan2(v6 - pGame->pIndoorCameraD3D->vPartyPos.x, a2 - pGame->pIndoorCameraD3D->vPartyPos.y);
         v37 = pBLVRenderParams->field_0_timer_;
         v9 = ((signed int)(stru_5C6E00->uIntegerPi + v8) >> 8) & 7;
         if (pParty->bTurnBasedModeOn)
@@ -4992,7 +5009,7 @@
           LOBYTE(v30) = v30 | 0x80;
         if ( (256 << v9) & v13 )
           v30 |= 4u;
-        if ( pGame->pIndoorCameraD3D->ApplyViewTransform_TrueIfStillVisible(a1, a2, a3, &x, &y, &z, 1) )
+        if ( pGame->pIndoorCameraD3D->ApplyViewTransform_TrueIfStillVisible_BLV(a1, a2, a3, &x, &y, &z, 1) )
         {
           v14 = abs(x);
           if ( v14 >= abs(y) )
@@ -5010,8 +5027,8 @@
               v15->uIndoorSectorID = uSectorID;
               if ( v16 )
               {
-                LODWORD(v21) = pBLVRenderParams->field_40 << 16;
-                HIDWORD(v21) = pBLVRenderParams->field_40 >> 16;
+                LODWORD(v21) = pBLVRenderParams->fov_rad_fixpoint << 16;
+                HIDWORD(v21) = pBLVRenderParams->fov_rad_fixpoint >> 16;
                 v37 = v21 / x;
                 //LODWORD(v31) = v12->scale;
                 v37 = v21 / x;
@@ -5135,56 +5152,56 @@
   //int v30; // [sp+30h] [bp+8h]@10
   //int v31; // [sp+3Ch] [bp+14h]@10
 
-  v8 = stru_5C6E00->Cos(pBLVRenderParams->sPartyRotY);
-  v29 = stru_5C6E00->Sin(pBLVRenderParams->sPartyRotY);
-  v28 = stru_5C6E00->Cos(pBLVRenderParams->sPartyRotX);
-  v9 = stru_5C6E00->Sin(pBLVRenderParams->sPartyRotX);
+  v8 = stru_5C6E00->Cos(pGame->pIndoorCameraD3D->sRotationY);
+  v29 = stru_5C6E00->Sin(pGame->pIndoorCameraD3D->sRotationY);
+  v28 = stru_5C6E00->Cos(pGame->pIndoorCameraD3D->sRotationX);
+  v9 = stru_5C6E00->Sin(pGame->pIndoorCameraD3D->sRotationX);
   //v11 = -pBLVRenderParams->vPartyPos.y;
   //v26 = -pBLVRenderParams->vPartyPos.x;
   //v27 = v9;
   //v12 = -pBLVRenderParams->vPartyPos.z;
-  if ( pBLVRenderParams->sPartyRotX )
+  if (pGame->pIndoorCameraD3D->sRotationX)
   {
-    v16 = v8 * -pBLVRenderParams->vPartyPos.x + v29 * -pBLVRenderParams->vPartyPos.y;
-    v17 = -65536 * pBLVRenderParams->vPartyPos.z;
-    this->field_0_party_dir_x = fixpoint_sub0(v16, v28) + fixpoint_sub0((-pBLVRenderParams->vPartyPos.z) << 16, v9);
-    this->field_4_party_dir_y = v8 * -pBLVRenderParams->vPartyPos.y - v29 * -pBLVRenderParams->vPartyPos.x;
-    this->field_8_party_dir_z = fixpoint_sub0(v17, v28) - fixpoint_sub0(v16, v9);
+    v16 = v8 * -pGame->pIndoorCameraD3D->vPartyPos.x + v29 * -pGame->pIndoorCameraD3D->vPartyPos.y;
+    v17 = -65536 * pGame->pIndoorCameraD3D->vPartyPos.z;
+    this->field_0_party_dir_x = fixpoint_mul(v16, v28) + fixpoint_mul((-pGame->pIndoorCameraD3D->vPartyPos.z) << 16, v9);
+    this->field_4_party_dir_y = v8 * -pGame->pIndoorCameraD3D->vPartyPos.y - v29 * -pGame->pIndoorCameraD3D->vPartyPos.x;
+    this->field_8_party_dir_z = fixpoint_mul(v17, v28) - fixpoint_mul(v16, v9);
   }
   else
   {
-    this->field_0_party_dir_x = v8 * -pBLVRenderParams->vPartyPos.x + v29 * -pBLVRenderParams->vPartyPos.y;
-    this->field_4_party_dir_y = v8 * -pBLVRenderParams->vPartyPos.y - v29 * -pBLVRenderParams->vPartyPos.x;
-    this->field_8_party_dir_z = (-pBLVRenderParams->vPartyPos.z) << 16;
+    this->field_0_party_dir_x = v8 * -pGame->pIndoorCameraD3D->vPartyPos.x + v29 * -pGame->pIndoorCameraD3D->vPartyPos.y;
+    this->field_4_party_dir_y = v8 * -pGame->pIndoorCameraD3D->vPartyPos.y - v29 * -pGame->pIndoorCameraD3D->vPartyPos.x;
+    this->field_8_party_dir_z = (-pGame->pIndoorCameraD3D->vPartyPos.z) << 16;
   }
 
-  if (pBLVRenderParams->sPartyRotX)
+  if (pGame->pIndoorCameraD3D->sRotationX)
   {
-    v19 = fixpoint_sub0(a2, v8) + fixpoint_sub0(a3, v29);
-
-    this->field_C = fixpoint_sub0(v19, v28) + fixpoint_sub0(a4, v9);
-    this->field_10 = fixpoint_sub0(a3, v8) - fixpoint_sub0(a2, v29);
-    this->field_14 = fixpoint_sub0(a4, v28) - fixpoint_sub0(v19, v9);
+    v19 = fixpoint_mul(a2, v8) + fixpoint_mul(a3, v29);
+
+    this->field_C = fixpoint_mul(v19, v28) + fixpoint_mul(a4, v9);
+    this->field_10 = fixpoint_mul(a3, v8) - fixpoint_mul(a2, v29);
+    this->field_14 = fixpoint_mul(a4, v28) - fixpoint_mul(v19, v9);
   }
   else
   {
-    this->field_C = fixpoint_sub0(a2, v8) + fixpoint_sub0(a3, v29);
-    this->field_10 = fixpoint_sub0(a3, v8) - fixpoint_sub0(a2, v29);
+    this->field_C = fixpoint_mul(a2, v8) + fixpoint_mul(a3, v29);
+    this->field_10 = fixpoint_mul(a3, v8) - fixpoint_mul(a2, v29);
     this->field_14 = a4;
   }
 
-  if (pBLVRenderParams->sPartyRotX)
+  if (pGame->pIndoorCameraD3D->sRotationX)
   {
-    v21 = fixpoint_sub0(a5, v8) + fixpoint_sub0(a6, v29);
-
-    this->field_18 = fixpoint_sub0(v21, v28) + fixpoint_sub0(a7, v9);
-    this->field_1C = fixpoint_sub0(a6, v8) - fixpoint_sub0(a5, v29);
-    this->field_20 = fixpoint_sub0(a7, v28) - fixpoint_sub0(v21, v9);
+    v21 = fixpoint_mul(a5, v8) + fixpoint_mul(a6, v29);
+
+    this->field_18 = fixpoint_mul(v21, v28) + fixpoint_mul(a7, v9);
+    this->field_1C = fixpoint_mul(a6, v8) - fixpoint_mul(a5, v29);
+    this->field_20 = fixpoint_mul(a7, v28) - fixpoint_mul(v21, v9);
   }
   else
   {
-    this->field_18 = fixpoint_sub0(a5, v8) + fixpoint_sub0(a6, v29);
-    this->field_1C = fixpoint_sub0(a6, v8) - fixpoint_sub0(a5, v29);
+    this->field_18 = fixpoint_mul(a5, v8) + fixpoint_mul(a6, v29);
+    this->field_1C = fixpoint_mul(a6, v8) - fixpoint_mul(a5, v29);
     this->field_20 = a7;
   }
 
@@ -5518,9 +5535,9 @@
           if ( v108 >= 0 )
           {
             if ( sub_4075DB(
-                   pOut.x + ((signed int)(fixpoint_sub0(v108, v143) + 32768) >> 16),
-                   pOut.y + ((signed int)(fixpoint_sub0(v108, v147) + 32768) >> 16),
-                   outz + ((signed int)(fixpoint_sub0(v108, v151) + 32768) >> 16),
+                   pOut.x + ((signed int)(fixpoint_mul(v108, v143) + 32768) >> 16),
+                   pOut.y + ((signed int)(fixpoint_mul(v108, v147) + 32768) >> 16),
+                   outz + ((signed int)(fixpoint_mul(v108, v151) + 32768) >> 16),
                    v62) )
             {
               v114 = 1;
@@ -5644,9 +5661,9 @@
         || v132 < v90->pBounding.y1
         || v136 > v90->pBounding.z2
         || v140 < v90->pBounding.z1
-        || (yb = fixpoint_sub0(v144, v90->pFacePlane_old.vNormal.x),
-            v_4b = fixpoint_sub0(v148, v90->pFacePlane_old.vNormal.y),
-            vf = fixpoint_sub0(v152, v90->pFacePlane_old.vNormal.z),
+        || (yb = fixpoint_mul(v144, v90->pFacePlane_old.vNormal.x),
+            v_4b = fixpoint_mul(v148, v90->pFacePlane_old.vNormal.y),
+            vf = fixpoint_mul(v152, v90->pFacePlane_old.vNormal.z),
             v20 = yb + vf + v_4b == 0,
             v91 = yb + vf + v_4b,
             vc = yb + vf + v_4b,
@@ -5687,9 +5704,9 @@
         if ( vd >= 0 )
         {
           if ( sub_4075DB(
-                 pOut.x + ((signed int)(fixpoint_sub0(vd, v144) + 32768) >> 16),
-                 pOut.y + ((signed int)(fixpoint_sub0(vd, v148) + 32768) >> 16),
-                 outz + ((signed int)(fixpoint_sub0(vd, v152) + 32768) >> 16),
+                 pOut.x + ((signed int)(fixpoint_mul(vd, v144) + 32768) >> 16),
+                 pOut.y + ((signed int)(fixpoint_mul(vd, v148) + 32768) >> 16),
+                 outz + ((signed int)(fixpoint_mul(vd, v152) + 32768) >> 16),
                  v90) )
           {
             v113 = 1;
@@ -5787,9 +5804,9 @@
         || v137 < v16->pBoundingBox.y1
         || v133 > v16->pBoundingBox.z2
         || v129 < v16->pBoundingBox.z1
-        || (v17 = fixpoint_sub0(v125, v16->pFacePlane.vNormal.x),
-            v18 = fixpoint_sub0(v121, v16->pFacePlane.vNormal.y),
-            v19 = fixpoint_sub0(v117, v16->pFacePlane.vNormal.z),
+        || (v17 = fixpoint_mul(v125, v16->pFacePlane.vNormal.x),
+            v18 = fixpoint_mul(v121, v16->pFacePlane.vNormal.y),
+            v19 = fixpoint_mul(v117, v16->pFacePlane.vNormal.z),
             v20 = v17 + v18 + v19 == 0,
             v21 = v17 + v18 + v19,
             v109 = v17 + v18 + v19,
@@ -5818,9 +5835,9 @@
         if ( v110 >= 0 )
         {
           if ( sub_4077F1(
-                 pOut.x + ((signed int)(fixpoint_sub0(v110, v125) + 32768) >> 16),
-                 pOut.y + ((signed int)(fixpoint_sub0(v110, v121) + 32768) >> 16),
-                 outz + ((signed int)(fixpoint_sub0(v110, v117) + 32768) >> 16),
+                 pOut.x + ((signed int)(fixpoint_mul(v110, v125) + 32768) >> 16),
+                 pOut.y + ((signed int)(fixpoint_mul(v110, v121) + 32768) >> 16),
+                 outz + ((signed int)(fixpoint_mul(v110, v117) + 32768) >> 16),
                  v16,
                  (BSPVertexBuffer *)a5) )
           {
@@ -5921,9 +5938,9 @@
         || v138 < v39->pBoundingBox.y1
         || v134 > v39->pBoundingBox.z2
         || v130 < v39->pBoundingBox.z1
-        || (ya = fixpoint_sub0(v126, v39->pFacePlane.vNormal.x),
-            ve = fixpoint_sub0(v122, v39->pFacePlane.vNormal.y),
-            v_4 = fixpoint_sub0(v118, v39->pFacePlane.vNormal.z),
+        || (ya = fixpoint_mul(v126, v39->pFacePlane.vNormal.x),
+            ve = fixpoint_mul(v122, v39->pFacePlane.vNormal.y),
+            v_4 = fixpoint_mul(v118, v39->pFacePlane.vNormal.z),
             v20 = ya + ve + v_4 == 0,
             v40 = ya + ve + v_4,
             va = ya + ve + v_4,
@@ -5951,9 +5968,9 @@
         if ( vb >= 0 )
         {
           if ( sub_4077F1(
-                 pOut.x + ((signed int)(fixpoint_sub0(vb, v126) + 32768) >> 16),
-                 pOut.y + ((signed int)(fixpoint_sub0(vb, v122) + 32768) >> 16),
-                 outz + ((signed int)(fixpoint_sub0(vb, v118) + 32768) >> 16),
+                 pOut.x + ((signed int)(fixpoint_mul(vb, v126) + 32768) >> 16),
+                 pOut.y + ((signed int)(fixpoint_mul(vb, v122) + 32768) >> 16),
+                 outz + ((signed int)(fixpoint_mul(vb, v118) + 32768) >> 16),
                  v39,
                  (BSPVertexBuffer *)a5a) )
           {
@@ -6465,9 +6482,9 @@
   memset(&PortalFace, 0, sizeof(stru367));
 
   //get direction the face(определение направленности фейса)*********************************************************************************
-  if ( pFace->pFacePlane_old.vNormal.x * (pIndoor->pVertices[pIndoor->pFaces[uFaceID].pVertexIDs[0]].x - pBLVRenderParams->vPartyPos.x)
-     + pFace->pFacePlane_old.vNormal.y * (pIndoor->pVertices[pIndoor->pFaces[uFaceID].pVertexIDs[0]].y - pBLVRenderParams->vPartyPos.y)
-     + pFace->pFacePlane_old.vNormal.z * (pIndoor->pVertices[pIndoor->pFaces[uFaceID].pVertexIDs[0]].z - pBLVRenderParams->vPartyPos.z) < 0 )
+  if ( pFace->pFacePlane_old.vNormal.x * (pIndoor->pVertices[pIndoor->pFaces[uFaceID].pVertexIDs[0]].x - pGame->pIndoorCameraD3D->vPartyPos.x)
+     + pFace->pFacePlane_old.vNormal.y * (pIndoor->pVertices[pIndoor->pFaces[uFaceID].pVertexIDs[0]].y - pGame->pIndoorCameraD3D->vPartyPos.y)
+     + pFace->pFacePlane_old.vNormal.z * (pIndoor->pVertices[pIndoor->pFaces[uFaceID].pVertexIDs[0]].z - pGame->pIndoorCameraD3D->vPartyPos.z) < 0 )
   {
     PortalFace.direction = true;
   }
@@ -6500,7 +6517,7 @@
   {
     for (uint i = 0; i < pFace->uNumVertices; ++i)
     {
-      pGame->pIndoorCameraD3D->ApplyViewTransform_TrueIfStillVisible(pIndoor->pVertices[pFace->pVertexIDs[i]].x,
+      pGame->pIndoorCameraD3D->ApplyViewTransform_TrueIfStillVisible_BLV(pIndoor->pVertices[pFace->pVertexIDs[i]].x,
                                                                      pIndoor->pVertices[pFace->pVertexIDs[i]].y,
                                                                      pIndoor->pVertices[pFace->pVertexIDs[i]].z,
         &PortalFace._view_transformed_z[i + 3], &PortalFace._view_transformed_x[i + 3], &PortalFace._view_transformed_y[i + 3], 0);
@@ -6633,8 +6650,8 @@
           pScreenY = 0x400000;  // 64.0
       }
     }
-    PortalFace._screen_space_x[i + 12] = pBLVRenderParams->uViewportCenterX - ((unsigned __int64)(SHIWORD(pBLVRenderParams->field_40) * (signed __int64)pScreenX) >> 16);
-    PortalFace._screen_space_y[i + 12] = pBLVRenderParams->uViewportCenterY - ((unsigned __int64)(SHIWORD(pBLVRenderParams->field_40) * (signed __int64)pScreenY) >> 16);
+    PortalFace._screen_space_x[i + 12] = pBLVRenderParams->uViewportCenterX - ((unsigned __int64)(SHIWORD(pBLVRenderParams->fov_rad_fixpoint) * (signed __int64)pScreenX) >> 16);
+    PortalFace._screen_space_y[i + 12] = pBLVRenderParams->uViewportCenterY - ((unsigned __int64)(SHIWORD(pBLVRenderParams->fov_rad_fixpoint) * (signed __int64)pScreenY) >> 16);
   }
   // результат: при повороте камеры, когда граница портала сдвигается к краю экрана, портал остается прозрачным(видимым)
   //******************************************************************************************************************************************
@@ -6868,39 +6885,39 @@
   float v13; // [sp+Ch] [bp-4h]@2
   float v14; // [sp+Ch] [bp-4h]@6
 
-  if ( pBLVRenderParams->sPartyRotX )
+  if (pGame->pIndoorCameraD3D->sRotationX)
   {
     v13 = a1->vWorldPosition.x - (double)pParty->vPosition.x;
     v11 = a1->vWorldPosition.y - (double)pParty->vPosition.y;
     v4 = a1->vWorldPosition.z - (double)pParty->vPosition.z;
-    if ( pRenderer->pRenderD3D )
-    {
-      v5 = v11 * pBLVRenderParams->fSineY + v13 * pBLVRenderParams->fCosineY;
-      a1->vWorldViewPosition.y = v13 * pBLVRenderParams->fSineY - v11 * pBLVRenderParams->fCosineY;
-    }
+    //if ( pRenderer->pRenderD3D )
+    //{
+      v5 = v11 * pGame->pIndoorCameraD3D->fRotationYSine + v13 * pGame->pIndoorCameraD3D->fRotationYCosine;
+      a1->vWorldViewPosition.y = v13 * pGame->pIndoorCameraD3D->fRotationYSine - v11 * pGame->pIndoorCameraD3D->fRotationYCosine;
+    /*}
     else
     {
       v5 = v13 * pBLVRenderParams->fCosineY - v11 * pBLVRenderParams->fSineY;
       a1->vWorldViewPosition.y = v13 * pBLVRenderParams->fSineY + v11 * pBLVRenderParams->fCosineY;
-    }
-    a1->vWorldViewPosition.x = v5 * pBLVRenderParams->fCosineNegX - v4 * pBLVRenderParams->fSineNegX;
-    a1->vWorldViewPosition.z = v5 * pBLVRenderParams->fSineNegX + v4 * pBLVRenderParams->fCosineNegX;
+    }*/
+    a1->vWorldViewPosition.x = v5 * pGame->pIndoorCameraD3D->fRotationXCosine - v4 * pGame->pIndoorCameraD3D->fRotationXSine;
+    a1->vWorldViewPosition.z = v5 * pGame->pIndoorCameraD3D->fRotationXSine + v4 * pGame->pIndoorCameraD3D->fRotationXCosine;
   }
   else
   {
     v14 = a1->vWorldPosition.x - (double)pParty->vPosition.x;
     v12 = a1->vWorldPosition.y - (double)pParty->vPosition.y;
     a1->vWorldViewPosition.z = a1->vWorldPosition.z - (double)pParty->vPosition.z;
-    if ( pRenderer->pRenderD3D )
-    {
-      a1->vWorldViewPosition.x = v12 * pBLVRenderParams->fSineY + v14 * pBLVRenderParams->fCosineY;
-      a1->vWorldViewPosition.y = v14 * pBLVRenderParams->fSineY - v12 * pBLVRenderParams->fCosineY;
-    }
+    //if ( pRenderer->pRenderD3D )
+    //{
+      a1->vWorldViewPosition.x = v12 * pGame->pIndoorCameraD3D->fRotationYSine + v14 * pGame->pIndoorCameraD3D->fRotationYCosine;
+      a1->vWorldViewPosition.y = v14 * pGame->pIndoorCameraD3D->fRotationYSine - v12 * pGame->pIndoorCameraD3D->fRotationYCosine;
+    /*}
     else
     {
       a1->vWorldViewPosition.x = v14 * pBLVRenderParams->fCosineY - v12 * pBLVRenderParams->fSineY;
       a1->vWorldViewPosition.y = v14 * pBLVRenderParams->fSineY + v12 * pBLVRenderParams->fCosineY;
-    }
+    }*/
   }
   return 0;
 }
\ No newline at end of file
--- a/Indoor.h	Wed Sep 18 06:30:53 2013 +0200
+++ b/Indoor.h	Wed Sep 18 06:32:15 2013 +0200
@@ -469,65 +469,37 @@
 
 
 
-/*  263 */
-#pragma pack(push, 1)
-struct IndoorLocation_drawstru
-{
-  int field_0_timer;
-  int uFlags;              // & INDOOR_CAMERA_DRAW_D3D_OUTLINES:  render d3d outlines
-  Vec3_int_ vPosition;
-  int sRotationY;
-  int sRotationX;
-  int field_1C_mb_fov;
-  unsigned __int16 *pRenderTarget;
-  unsigned int uTargetWidth;
-  unsigned int uTargetHeight;
-  signed int uViewportX;
-  signed int uViewportY;
-  signed int uViewportZ;
-  signed int uViewportW;
-  int field_3C;
-  int *pTargetZ;
-};
-#pragma pack(pop)
-
-
-
-
-
-
-
-
-
-
-
 
 /*  162 */
 #pragma pack(push, 1)
 struct BLVRenderParams
 {
-  inline BLVRenderParams():
-    uFlags(0)
-  {}
+  inline BLVRenderParams()
+  {
+    uViewportX = 0;
+    uViewportY = 0;
+    uViewportZ = 0;
+    uViewportW = 0;
+  }
 
-  int Reset(struct IndoorLocation_drawstru *a2);
+  void Reset();
 
   int field_0_timer_;
-  int uFlags;              // & INDOOR_CAMERA_DRAW_D3D_OUTLINES:  render d3d outlines
-  Vec3_int_ vPartyPos;
-  int sPartyRotY;
-  int sPartyRotX;
+  int _unused_uFlags;              // & INDOOR_CAMERA_DRAW_D3D_OUTLINES:  render d3d outlines
+  Vec3_int_ _unused_vPartyPos;
+  int _unused_sPartyRotY;
+  int _unused_sPartyRotX;
   int uPartySectorID;
-  int sCosineY;
-  int sSineY;
-  int sCosineNegX;
-  int sSineNegX;
-  float fCosineY;
-  float fSineY;
-  float fCosineNegX;
-  float fSineNegX;
-  int field_40;
-  int field_44;//float
+  int _unused_sCosineY;      // matches ODMRenderParams::int sines and cosines
+  int _unused_sSineY;        // computed in 0048600E
+  int _unused_sCosineNegX;   // merged into IndoorCameraD3D
+  int _unused_sSineNegX;     // --//--
+  float _unused_fCosineY;    // matches old IndoorCamera::fRotationCosineY (new IndoorCameraD3D::fRotationCosineY)
+  float _unused_fSineY;      // matches old IndoorCamera::fRotationSineY   (new IndoorCameraD3D::fRotationSineY)
+  float _unused_fCosineNegX; // the same
+  float _unused_fSineNegX;   // the same
+  int fov_rad_fixpoint;
+  int fov_rad_inv_fixpoint;//float
   unsigned __int16 *pRenderTarget;
   unsigned int uTargetWidth;
   unsigned int uTargetHeight;
@@ -538,7 +510,7 @@
   int field_64;
   int *pTargetZBuffer;
   int uViewportHeight;
-  int field_70;
+  int uViewportWidth;
   int uViewportCenterX;
   int uViewportCenterY;
   struct BspRenderer_PortalViewportData *field_7C;
@@ -550,8 +522,7 @@
   int field_94;
 };
 #pragma pack(pop)
-
-extern struct BLVRenderParams *pBLVRenderParams;
+extern BLVRenderParams *pBLVRenderParams;
 
 
 
--- a/IndoorCamera.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-#include "IndoorCamera.h"
-#include "Render.h"
-#include "Game.h"
-#include "Indoor.h"
-#include "Math.h"
-
-#include "mm7_data.h"
-
-
-
-
-
-IndoorCamera *pIndoorCamera; // idb
-
-
-
-
-
-//----- (00481CCE) --------------------------------------------------------
-float IndoorCamera::ViewTransform(RenderVertexSoft *a1)
-{
-  float result; // eax@1
-  double vCamToVertexZ; // st7@1
-  double v3; // st6@1
-  double v4; // st5@1
-  double v5; // st4@1
-  float v6; // ST04_4@3
-  float v7; // [sp+0h] [bp-14h]@1
-  float v8; // [sp+8h] [bp-Ch]@1
-  float vCamToVertexX; // [sp+Ch] [bp-8h]@1
-  float vCamToVertexY; // [sp+10h] [bp-4h]@1
-
-  v8 = fRotationXCosine;
-  result = fRotationXSine;
-  v7 = fRotationXSine;
-  vCamToVertexX = a1->vWorldPosition.x - (double)pos.x;
-  vCamToVertexY = a1->vWorldPosition.y - (double)pos.y;
-  vCamToVertexZ = a1->vWorldPosition.z - (double)pos.z;
-  v3 = fRotationYCosine;
-  v4 = fRotationYSine;
-  v5 = vCamToVertexY * fRotationYSine + fRotationYCosine * vCamToVertexX;
-  if ( sRotationX )
-  {
-    v6 = vCamToVertexY * fRotationYSine + fRotationYCosine * vCamToVertexX;
-    a1->vWorldViewPosition.x = v5 * fRotationXCosine + fRotationXSine * vCamToVertexZ;
-    a1->vWorldViewPosition.y = v3 * vCamToVertexY - v4 * vCamToVertexX;
-    a1->vWorldViewPosition.z = v8 * vCamToVertexZ - v6 * v7;
-  }
-  else
-  {
-    a1->vWorldViewPosition.x = vCamToVertexY * fRotationYSine + fRotationYCosine * vCamToVertexX;
-    a1->vWorldViewPosition.y = v3 * vCamToVertexY - v4 * vCamToVertexX;
-    a1->vWorldViewPosition.z = vCamToVertexZ;
-  }
-  return result;
-}
-
-
-
-//----- (0042394D) --------------------------------------------------------
-void IndoorCamera::Initialize(int degFov, unsigned int uViewportWidth, unsigned int uViewportHeight)
-{
-  IndoorCamera *v4; // esi@1
-  double v5; // st7@1
-
-  v4 = this;
-  v5 = (double)(signed int)(signed __int64)((double)(signed int)uViewportWidth
-                                          * 0.5
-                                          / tan((double)(degFov >> 1) * 0.01745329)
-                                          + 0.5);
-  v4->flt_1C_fov = v5;
-  v4->flt_20_inv_1C = 65536.0 / v5;
-}
-
-//----- (004239A7) --------------------------------------------------------
-void IndoorCamera::Initialize2()
-{
-  //IndoorCamera *v1; // esi@1
-  double v2; // st7@4
-  //double v3; // st7@6
-  //int v4; // eax@6
-  //int v5; // eax@6
-  //int v6; // ST04_4@6
-  //int v7; // eax@6
-  //int v8; // ST04_4@6
-
-  //v1 = this;
-  fRotationYSine = sin((3.141592653589793 + 3.141592653589793) * (double)sRotationY * 0.00048828125);
-  fRotationYCosine = cos((3.141592653589793 + 3.141592653589793) * (double)sRotationY * 0.00048828125);
-  if ( byte_4D864C && pGame->uFlags & 0x80 || uCurrentlyLoadedLevelType == LEVEL_Indoor)
-  {
-    fRotationXSine = sin((3.141592653589793 + 3.141592653589793) * (double)-sRotationX * 0.00048828125);
-    v2 = (3.141592653589793 + 3.141592653589793) * (double)-sRotationX;
-  }
-  else
-  {
-    fRotationXSine = sin((3.141592653589793 + 3.141592653589793) * (double)sRotationX * 0.00048828125);
-    v2 = (3.141592653589793 + 3.141592653589793) * (double)sRotationX;
-  }
-  //v3 = cos(v2 * 0.00048828125);
-  //v4 = sRotationY;
-  fRotationXCosine = cos(v2 * 0.00048828125);
-  //v5 = stru_5C6E00->SinCos(sRotationY - stru_5C6E00->uIntegerHalfPi);
-  //v6 = sRotationY;
-  _int_sine = stru_5C6E00->Sin(sRotationY);
-  _int_cosine = stru_5C6E00->Cos(sRotationY);
-  //v7 = stru_5C6E00->SinCos(sRotationX - stru_5C6E00->uIntegerHalfPi);
-  //v8 = sRotationX;
-  _int_sine_2 = stru_5C6E00->Sin(sRotationX);
-  _int_cosine_2 = stru_5C6E00->Cos(sRotationX);
-}
-// 4D864C: using guessed type char byte_4D864C;
\ No newline at end of file
--- a/IndoorCamera.h	Wed Sep 18 06:30:53 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-#pragma once
-#include "VectorTypes.h"
-
-
-#define INDOOR_CAMERA_DRAW_SW_OUTLINES 1
-#define INDOOR_CAMERA_DRAW_D3D_OUTLINES 2
-#define INDOOR_CAMERA_DRAW_TERRAIN_OUTLINES 4
-/*  157 */
-#pragma pack(push, 1)
-struct IndoorCamera
-{
-  //----- (0042391F) --------------------------------------------------------
-  IndoorCamera()
-  {
-    sRotationX = 0;
-    sRotationY = 0;
-    flt_1C_fov = 2000.0f;
-    flt_20_inv_1C = 32.768002f;
-
-    flags = 0;
-  }
-  void Initialize(int degFov, unsigned int uViewportWidth, unsigned int uViewportHeight);
-  void Initialize2();
-  float ViewTransform(struct RenderVertexSoft *a1);
-
-
-  Vec3_int_ pos;
-  unsigned int uMapGridCellX;
-  unsigned int uMapGridCellZ;
-  int sRotationX;
-  int sRotationY;
-  float flt_1C_fov;
-  float flt_20_inv_1C;
-  int field_24;
-  int field_28;
-  float fRotationYSine;
-  float fRotationYCosine;
-  float fRotationXSine;
-  float fRotationXCosine;
-  int _int_sine;
-  int _int_cosine;
-  int _int_sine_2;
-  int _int_cosine_2;
-  int flags;  // & INDOOR_CAMERA_DRAW_D3D_OUTLINES:  render terrain outlines in d3d
-};
-#pragma pack(pop)
-
-
-
-extern IndoorCamera *pIndoorCamera; // idb
\ No newline at end of file
--- a/IndoorCameraD3D.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/IndoorCameraD3D.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -3,14 +3,23 @@
 #include "Game.h"
 #include "Indoor.h"
 #include "Viewport.h"
-#include "IndoorCamera.h"
-#include "OutdoorCamera.h"
+#include "Outdoor_stuff.h"
 #include "Render.h"
 #include "LOD.h"
+#include "Math.h"
 #include "mm7_data.h"
 
 #include "stru9.h"
 
+
+// calculates FOV (Field of View) angle in radians for IndoorCamera::Initialize and BLVRenderParams::Reset
+float _calc_fov(int viewport_width, int angle_degree)
+{
+  return viewport_width * 0.5 / tan(angle_degree / 2 * 0.01745329) + 0.5;
+}
+
+
+
 //----- (004361EF) --------------------------------------------------------
 IndoorCameraD3D::IndoorCameraD3D()
 {
@@ -35,16 +44,16 @@
   //v3 = 0;//(double)pBLVRenderParams->vPartyPos.y;
   //v4 = 0;//(double)pBLVRenderParams->vPartyPos.x;
   v1->field_108 = 0.0;
-  v1->blv_party_x = 0;
-  v1->blv_party_y = 0;
-  v1->blv_party_z = 0;
+  //v1->blv_party_x = 0;
+  //v1->blv_party_y = 0;
+  //v1->blv_party_z = 0;
   //v5 = 0;//(double)pBLVRenderParams->vPartyPos.z;
   //v6 = 0;//(double)pBLVRenderParams->vPartyPos.y;
   //v7 = 300;//(double)(pBLVRenderParams->vPartyPos.x + 300);
   v1->field_138 = 0.0;
-  v1->blv_party_x_2 = 300;
-  v1->blv_party_y_2 = 0;
-  v1->blv_party_z_2 = 0;
+  //v1->blv_party_x_2 = 300;
+  //v1->blv_party_y_2 = 0;
+  //v1->blv_party_z_2 = 0;
   v1->field_168 = 0.0;
   v1->field_198 = 0.0;
   v1->field_1C8 = 0.0;
@@ -100,12 +109,20 @@
 //----- (0043643E) --------------------------------------------------------
 float IndoorCameraD3D::GetPickDepth()
 {
-  if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor)
-    return pOutdoorCamera->uPickDepth;
+  if (uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+    return pODMRenderParams->uPickDepth;
   else
     return 16192.0;
 }
 
+//----- (00436427) --------------------------------------------------------
+float IndoorCameraD3D::GetShadingDistMist()
+{
+  if (uCurrentlyLoadedLevelType == LEVEL_Outdoor)
+    return (double)pODMRenderParams->shading_dist_mist;
+  else
+    return 16192.0;
+}
 
 //----- (004364C5) --------------------------------------------------------
 void IndoorCameraD3D::ViewTransfrom_OffsetUV(RenderVertexSoft *pVertices, unsigned int uNumVertices, RenderVertexSoft *pOutVertices, stru320 *a5)
@@ -123,68 +140,56 @@
 }
 
 //----- (0043669D) --------------------------------------------------------
-char IndoorCameraD3D::ApplyViewTransform_TrueIfStillVisible(int x, int y, int z, signed int *pOutX, int *pOutZ, int *pOutY, char bDoNotShow)
+bool IndoorCameraD3D::ApplyViewTransform_TrueIfStillVisible_BLV(int x, int y, int z, signed int *pOutX, int *pOutZ, int *pOutY, char bDoNotShow)
 {
   int to_z; // esi@2
   int v9; // ecx@3
-  signed int *v10; // esi@5
-  int pOutY_; // ecx@5
-  signed int v12; // esi@7
+  //signed int *v10; // esi@5
+  //int pOutY_; // ecx@5
+  //signed int v12; // esi@7
   int v14; // [sp+8h] [bp-4h]@3
   int to_x; // [sp+14h] [bp+8h]@1
   int to_y; // [sp+18h] [bp+Ch]@1
   int a2b; // [sp+18h] [bp+Ch]@5
   int a3a; // [sp+1Ch] [bp+10h]@5
 
-  to_x = x - pBLVRenderParams->vPartyPos.x;
-  to_y = y - pBLVRenderParams->vPartyPos.y;
-  if ( pBLVRenderParams->sPartyRotX )
+  to_x = x - pGame->pIndoorCameraD3D->vPartyPos.x;
+  to_y = y - pGame->pIndoorCameraD3D->vPartyPos.y;
+  if (pGame->pIndoorCameraD3D->sRotationX)
   {
-    to_z = (z - pBLVRenderParams->vPartyPos.z) << 16;
-    if ( pRenderer->pRenderD3D )
-    {
-      v14 = (unsigned __int64)(to_x * (signed __int64)pBLVRenderParams->sCosineY)
-          + (unsigned __int64)(to_y * (signed __int64)pBLVRenderParams->sSineY);
-      v9 = (unsigned __int64)(to_x * (signed __int64)pBLVRenderParams->sSineY)
-         - (unsigned __int64)(to_y * (signed __int64)pBLVRenderParams->sCosineY);
-    }
-    else
-    {
-      v14 = ((unsigned __int64)(to_x * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
-          - ((unsigned __int64)(to_y * (signed __int64)pBLVRenderParams->sSineY) >> 16);
-      v9 = ((unsigned __int64)(to_x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
-         + ((unsigned __int64)(to_y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
-    }
-    a3a = (z - pBLVRenderParams->vPartyPos.z) << 16;
-    a2b = (unsigned __int64)(to_z * (signed __int64)pBLVRenderParams->sSineNegX) >> 16;
-    v10 = pOutX;
-    *pOutX = ((unsigned __int64)(v14 * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16) - a2b;
+    to_z = (z - pGame->pIndoorCameraD3D->vPartyPos.z) << 16;
+    //if ( pRenderer->pRenderD3D )
+    //{
+      v14 = (unsigned __int64)(to_x * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y)
+          + (unsigned __int64)(to_y * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y);
+      v9 = (unsigned __int64)(to_x * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y)
+         - (unsigned __int64)(to_y * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y);
+    //}
+    a3a = (z - pGame->pIndoorCameraD3D->vPartyPos.z) << 16;
+    a2b = (unsigned __int64)(to_z * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16;
+    //v10 = pOutX;
+    *pOutX = ((unsigned __int64)(v14 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16) - a2b;
     *pOutZ = v9;
-    pOutY_ = ((unsigned __int64)(v14 * (signed __int64)pBLVRenderParams->sSineNegX) >> 16)
-           + ((unsigned __int64)(a3a * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16);
+    *pOutY = ((unsigned __int64)(v14 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16)
+           + ((unsigned __int64)(a3a * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16);
   }
   else
   {
-    pOutY_ = (z - pBLVRenderParams->vPartyPos.z) << 16;
-    if ( pRenderer->pRenderD3D )
-    {
-      v10 = pOutX;
-      *pOutX = (unsigned __int64)(to_x * (signed __int64)pBLVRenderParams->sCosineY)
-             + (unsigned __int64)(to_y * (signed __int64)pBLVRenderParams->sSineY);
-      *pOutZ = (unsigned __int64)(to_x * (signed __int64)pBLVRenderParams->sSineY)
-             - (unsigned __int64)(to_y * (signed __int64)pBLVRenderParams->sCosineY);
-    }
-    else
-    {
-      v10 = pOutX;
-      *pOutX = ((unsigned __int64)(to_x * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
-             - ((unsigned __int64)(to_y * (signed __int64)pBLVRenderParams->sSineY) >> 16);
-      *pOutZ = ((unsigned __int64)(to_x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
-             + ((unsigned __int64)(to_y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
-    }
+    *pOutY = (z - pGame->pIndoorCameraD3D->vPartyPos.z) << 16;
+    //if ( pRenderer->pRenderD3D )
+    //{
+      //v10 = pOutX;
+      *pOutX = (unsigned __int64)(to_x * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y)
+             + (unsigned __int64)(to_y * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y);
+      *pOutZ = (unsigned __int64)(to_x * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y)
+             - (unsigned __int64)(to_y * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y);
+    //}
   }
-  *pOutY = pOutY_;
-  return !bDoNotShow || (v12 = *v10, v12 >= (signed int)0x40000u) && v12 <= (signed int)0x1F400000u;
+  if (!bDoNotShow)
+    return false;
+
+  return *pOutX >= fixpoint_from_int(4, 0) &&
+         *pOutX <= fixpoint_from_int(8000, 0);
 }
 
 //----- (00436455) --------------------------------------------------------
@@ -196,20 +201,21 @@
   return is_face_faced_to_camera(pFace, &v);
 }
 
+
 //----- (00436523) --------------------------------------------------------
 void IndoorCameraD3D::ViewTransform(RenderVertexSoft *a1a, unsigned int uNumVertices)
 {
   if (byte_4D864C && pGame->uFlags & 0x80 ||
       uCurrentlyLoadedLevelType == LEVEL_Indoor)
   {
-    float sin_x = pIndoorCamera->fRotationXSine,
-          cos_x = pIndoorCamera->fRotationXCosine;
-    float sin_y = pIndoorCamera->fRotationYSine,
-          cos_y = pIndoorCamera->fRotationYCosine;
+    float sin_x = fRotationXSine,
+          cos_x = fRotationXCosine;
+    float sin_y = fRotationYSine,
+          cos_y = fRotationYCosine;
 
     //v4 = uNumVertices;
     //v7 = pIndoorCamera->fRotationXSine;
-    if ( pIndoorCamera->sRotationX )
+    if (pGame->pIndoorCameraD3D->sRotationX)
     {
 
         //_EAX = a1a;
@@ -256,9 +262,9 @@
                                          // 4[pIndoorCamera->fRotationYSine]
                                          // 5[pIndoorCamera->fRotationYCosine]
             }*/
-            st0 = sin_y * (a1a[i].vWorldPosition.x - pIndoorCamera->pos.x) - cos_y * (a1a[i].vWorldPosition.y - pIndoorCamera->pos.y);
-            st1 = cos_y * (a1a[i].vWorldPosition.x - pIndoorCamera->pos.x) + sin_y * (a1a[i].vWorldPosition.y - pIndoorCamera->pos.y);
-            st2 = (a1a[i].vWorldPosition.z - pIndoorCamera->pos.z);
+            st0 = sin_y * (a1a[i].vWorldPosition.x - pGame->pIndoorCameraD3D->vPartyPos.x) - cos_y * (a1a[i].vWorldPosition.y - pGame->pIndoorCameraD3D->vPartyPos.y);
+            st1 = cos_y * (a1a[i].vWorldPosition.x - pGame->pIndoorCameraD3D->vPartyPos.x) + sin_y * (a1a[i].vWorldPosition.y - pGame->pIndoorCameraD3D->vPartyPos.y);
+            st2 = (a1a[i].vWorldPosition.z - pGame->pIndoorCameraD3D->vPartyPos.z);
           }
           else
           {
@@ -324,9 +330,9 @@
                                          // 4[pIndoorCamera->fRotationYSine]
                                          // 5[pIndoorCamera->fRotationYCosine]
             }*/
-            st0 = cos_y * (a1a[i].vWorldPosition.y - pIndoorCamera->pos.y) + sin_y * (a1a[i].vWorldPosition.x - pIndoorCamera->pos.x);
-            st1 = cos_y * (a1a[i].vWorldPosition.x - pIndoorCamera->pos.x) - sin_y * (a1a[i].vWorldPosition.y - pIndoorCamera->pos.y);
-            st2 = (a1a[i].vWorldPosition.z - pIndoorCamera->pos.z);
+            st0 = cos_y * (a1a[i].vWorldPosition.y - pGame->pIndoorCameraD3D->vPartyPos.y) + sin_y * (a1a[i].vWorldPosition.x - pGame->pIndoorCameraD3D->vPartyPos.x);
+            st1 = cos_y * (a1a[i].vWorldPosition.x - pGame->pIndoorCameraD3D->vPartyPos.x) - sin_y * (a1a[i].vWorldPosition.y - pGame->pIndoorCameraD3D->vPartyPos.y);
+            st2 = (a1a[i].vWorldPosition.z - pGame->pIndoorCameraD3D->vPartyPos.z);
           }
 
           a1a[i].vWorldViewPosition.x = st1*cos_x - st2*sin_x;
@@ -390,9 +396,9 @@
               fstp    dword ptr [eax+10h]
               fstp    dword ptr [eax+14h]
             }*/
-            a1a[i].vWorldViewPosition.x = cos_y * (a1a[i].vWorldPosition.x - pIndoorCamera->pos.x) + sin_y * (a1a[i].vWorldPosition.y - pIndoorCamera->pos.y);
-            a1a[i].vWorldViewPosition.y = sin_y * (a1a[i].vWorldPosition.x - pIndoorCamera->pos.x) - cos_y * (a1a[i].vWorldPosition.y - pIndoorCamera->pos.y);
-            a1a[i].vWorldViewPosition.z = (a1a[i].vWorldPosition.z - pIndoorCamera->pos.z);
+            a1a[i].vWorldViewPosition.x = cos_y * (a1a[i].vWorldPosition.x - pGame->pIndoorCameraD3D->vPartyPos.x) + sin_y * (a1a[i].vWorldPosition.y - pGame->pIndoorCameraD3D->vPartyPos.y);
+            a1a[i].vWorldViewPosition.y = sin_y * (a1a[i].vWorldPosition.x - pGame->pIndoorCameraD3D->vPartyPos.x) - cos_y * (a1a[i].vWorldPosition.y - pGame->pIndoorCameraD3D->vPartyPos.y);
+            a1a[i].vWorldViewPosition.z = (a1a[i].vWorldPosition.z - pGame->pIndoorCameraD3D->vPartyPos.z);
           }
           else
           {
@@ -419,9 +425,52 @@
     }
   }
   else for (uint i = 0; i < uNumVertices; ++i)
-    pIndoorCamera->ViewTransform(a1a + i);
+    //pIndoorCamera->ViewTransform_ODM(a1a + i);
+  {
+    //ViewTransform_ODM(a1a + i);
+
+    auto a1 = a1a + i;
+    //----- (00481CCE) --------------------------------------------------------
+    //void ViewTransform_ODM(RenderVertexSoft *a1)
+    {
+  float result; // eax@1
+  double vCamToVertexZ; // st7@1
+  double v3; // st6@1
+  double v4; // st5@1
+  double v5; // st4@1
+  float v6; // ST04_4@3
+  float v7; // [sp+0h] [bp-14h]@1
+  float v8; // [sp+8h] [bp-Ch]@1
+  float vCamToVertexX; // [sp+Ch] [bp-8h]@1
+  float vCamToVertexY; // [sp+10h] [bp-4h]@1
+
+  v8 = fRotationXCosine;
+  result = fRotationXSine;
+  v7 = fRotationXSine;
+  vCamToVertexX = a1->vWorldPosition.x - (double)pGame->pIndoorCameraD3D->vPartyPos.x;
+  vCamToVertexY = a1->vWorldPosition.y - (double)pGame->pIndoorCameraD3D->vPartyPos.y;
+  vCamToVertexZ = a1->vWorldPosition.z - (double)pGame->pIndoorCameraD3D->vPartyPos.z;
+  v3 = fRotationYCosine;
+  v4 = fRotationYSine;
+  v5 = vCamToVertexY * fRotationYSine + fRotationYCosine * vCamToVertexX;
+  if (pGame->pIndoorCameraD3D->sRotationX)
+  {
+    v6 = vCamToVertexY * fRotationYSine + fRotationYCosine * vCamToVertexX;
+    a1->vWorldViewPosition.x = v5 * fRotationXCosine + fRotationXSine * vCamToVertexZ;
+    a1->vWorldViewPosition.y = v3 * vCamToVertexY - v4 * vCamToVertexX;
+    a1->vWorldViewPosition.z = v8 * vCamToVertexZ - v6 * v7;
+  }
+  else
+  {
+    a1->vWorldViewPosition.x = vCamToVertexY * fRotationYSine + fRotationYCosine * vCamToVertexX;
+    a1->vWorldViewPosition.y = v3 * vCamToVertexY - v4 * vCamToVertexX;
+    a1->vWorldViewPosition.z = vCamToVertexZ;
+  }
+    }
+  }
 }
 
+
 //----- (00436932) --------------------------------------------------------
 bool IndoorCameraD3D::GetFacetOrientation(char polyType, Vec3_float_ *a2, Vec3_float_ *a3, Vec3_float_ *a4)
 {
@@ -491,9 +540,9 @@
     return false;
 
   //really strange cull; dot(to_cam, normal) < 0 means we see the BACK face, not font %_%
-  if ( (a2->vWorldPosition.z - (double)pIndoorCamera->pos.z) * (double)pFace->pFacePlane_old.vNormal.z
-     + (a2->vWorldPosition.y - (double)pIndoorCamera->pos.y) * (double)pFace->pFacePlane_old.vNormal.y
-     + (a2->vWorldPosition.x - (double)pIndoorCamera->pos.x) * (double)pFace->pFacePlane_old.vNormal.x < 0.0)
+  if ( (a2->vWorldPosition.z - (double)pGame->pIndoorCameraD3D->vPartyPos.z) * (double)pFace->pFacePlane_old.vNormal.z
+     + (a2->vWorldPosition.y - (double)pGame->pIndoorCameraD3D->vPartyPos.y) * (double)pFace->pFacePlane_old.vNormal.y
+     + (a2->vWorldPosition.x - (double)pGame->pIndoorCameraD3D->vPartyPos.x) * (double)pFace->pFacePlane_old.vNormal.x < 0.0)
     return false;
 
   return true;
@@ -847,15 +896,15 @@
   m5._21 = -sinf(0);        m5._22 = cosf(0);        m5._23 = 0;
   m5._31 = 0;               m5._32 = 0;              m5._33 = 1;
 
-  float cos_x1 = pIndoorCamera->fRotationXCosine,
-        sin_x1 = pIndoorCamera->fRotationXSine;
+  float cos_x1 = fRotationXCosine,
+        sin_x1 = fRotationXSine;
  //RotationX(x)
   m4._11 = 1;               m4._12 = 0;              m4._13 = 0;
   m4._21 = 0;               m4._22 = cos_x1;         m4._23 = sin_x1;
   m4._31 = 0;               m4._32 = -sin_x1;        m4._33 = cos_x1;
   
-  float cos_y1 = pIndoorCamera->fRotationYCosine,
-        sin_y1 = pIndoorCamera->fRotationYSine;
+  float cos_y1 = fRotationYCosine,
+        sin_y1 = fRotationYSine;
  //RotationY(some_angle)
   m3._11 = cos_y1;          m3._12 = 0;              m3._13 = -sin_y1;
   m3._21 = 0;               m3._22 = 1;              m3._23 = 0;
@@ -896,9 +945,9 @@
   double v4; // st7@1
   IndoorCameraD3D_Vec3 v8; // [sp+8h] [bp-1Ch]@1
 
-  v8.x = (double)pIndoorCamera->pos.x;
-  v8.y = (double)pIndoorCamera->pos.y;
-  v8.z = (double)pIndoorCamera->pos.z;
+  v8.x = (double)pGame->pIndoorCameraD3D->vPartyPos.x;
+  v8.y = (double)pGame->pIndoorCameraD3D->vPartyPos.y;
+  v8.z = (double)pGame->pIndoorCameraD3D->vPartyPos.z;
   Vec3Transform(a1, a2);
 
   v4 = v8.x * a2->x + v8.y * a2->y + v8.z * a2->z;
@@ -933,9 +982,9 @@
   v7.x = -sin(v3);
   v7.y = 0.0;
   v7.z = cos(v3);
-  _437607(&v7, std__vector_000034_prolly_frustrum);
+  _437607(&v7, std__vector_000034_prolly_frustrum + 0);
   v7.x = sin(v3);
-  _437607(&v7, &std__vector_000034_prolly_frustrum[1]);
+  _437607(&v7, std__vector_000034_prolly_frustrum + 1);
   v5 = atan(2.0 / inv_fov * fov / (fov_y + 0.5));
   //v12 = v5;
   //v11 = sin(v5);
@@ -976,9 +1025,9 @@
   if ( (signed int)*pOutNumVertices <= 3
     || ((v5 = a2,
          memcpy(&v18, a2, sizeof(v18)),
-         (v18.vWorldPosition.z - (double)pBLVRenderParams->vPartyPos.z) * thisa->face_plane.vNormal.z
-       + (v18.vWorldPosition.y - (double)pBLVRenderParams->vPartyPos.y) * thisa->face_plane.vNormal.y
-       + (v18.vWorldPosition.x - (double)pBLVRenderParams->vPartyPos.x) * thisa->face_plane.vNormal.x < 0.0) ? (v6 = 1.0) : (v6 = -1.0),
+         (v18.vWorldPosition.z - (double)pGame->pIndoorCameraD3D->vPartyPos.z) * thisa->face_plane.vNormal.z
+       + (v18.vWorldPosition.y - (double)pGame->pIndoorCameraD3D->vPartyPos.y) * thisa->face_plane.vNormal.y
+       + (v18.vWorldPosition.x - (double)pGame->pIndoorCameraD3D->vPartyPos.x) * thisa->face_plane.vNormal.x < 0.0) ? (v6 = 1.0) : (v6 = -1.0),
         a2_3 = 0,
         memcpy(&v5[v4], v5, sizeof(v5[v4])),
         memcpy(&v5[*pOutNumVertices + 1], &v5[1], sizeof(v5[*pOutNumVertices + 1])),
@@ -1191,7 +1240,7 @@
     {
       *(float *)v7 = 1.0 / (*((float *)v7 - 5) + 0.0000001);
       memcpy(pOutVertices_ - 28, v7 - 32, 0x30u);
-      v9 = (double)pOutdoorCamera->int_fov_rad * *(float *)&v7[v8];
+      v9 = (double)pODMRenderParams->int_fov_rad * *(float *)&v7[v8];
       v10 = (double)pViewport->uScreenCenterX - v9 * *((float *)v7 - 4);
       v7 += 48;
       *((float *)pOutVertices_ - 1) = v10;
@@ -1230,7 +1279,7 @@
   if ( uNumInVertices )
   {
     memcpy(&pInVertices[uNumInVertices], pInVertices, sizeof(pInVertices[uNumInVertices]));
-    v6 = (double)pOutdoorCamera->shading_dist_mist;
+    v6 = (double)pODMRenderParams->shading_dist_mist;
     v7 = 0;
     if ( v6 >= pInVertices->vWorldViewPosition.x )
       v7 = 1;
@@ -1494,17 +1543,17 @@
     //v8 = a2b + 6.7553994e15;
     *a6 = pViewport->uViewportBR_Y - floorf(a2b + 0.5f);
   }
-  else
+  /*else
   {
-    LODWORD(v9) = pBLVRenderParams->field_40 << 16;
-    HIDWORD(v9) = pBLVRenderParams->field_40 >> 16;
+    LODWORD(v9) = pBLVRenderParams->fov_rad_fixpoint << 16;
+    HIDWORD(v9) = pBLVRenderParams->fov_rad_fixpoint >> 16;
     v10 = v9 / x;
-    LODWORD(v9) = pBLVRenderParams->field_40 << 16;
-    HIDWORD(v9) = pBLVRenderParams->field_40 >> 16;
+    LODWORD(v9) = pBLVRenderParams->fov_rad_fixpoint << 16;
+    HIDWORD(v9) = pBLVRenderParams->fov_rad_fixpoint >> 16;
     *a5 = pBLVRenderParams->uViewportCenterX
         - ((signed int)(((unsigned __int64)(v10 * (signed __int64)y) >> 16) + 32768) >> 16);
     *a6 = pBLVRenderParams->uViewportCenterY - ((signed int)(((unsigned __int64)(v9 / x * z) >> 16) + 32768) >> 16);
-  }
+  }*/
 }
 
 //----- (00436A6D) --------------------------------------------------------
@@ -1559,4 +1608,39 @@
     while ( v3 );
   }
   return result;
+}
+
+
+
+// -- new
+// merged from IndoorCamera::Initialize2
+//         and ODMRenderParams::RotationToInts
+//         and BLVRenderParams::Reset
+void IndoorCameraD3D::CalculateRotations(int camera_rot_x, int camera_rot_y)
+{
+  sRotationX = camera_rot_x;
+  sRotationY = camera_rot_y;
+
+  fRotationYSine = sin((3.141592653589793 + 3.141592653589793) * (double)sRotationY / 2048.0);
+  fRotationYCosine = cos((3.141592653589793 + 3.141592653589793) * (double)sRotationY / 2048.0);
+  if (byte_4D864C && pGame->uFlags & 0x80 || uCurrentlyLoadedLevelType == LEVEL_Indoor)
+  {
+    fRotationXSine = sin((3.141592653589793 + 3.141592653589793) * (double)-sRotationX / 2048.0);
+    fRotationXCosine = cos((3.141592653589793 + 3.141592653589793) * (double)-sRotationX / 2048.0);
+
+    int_sine_y   = stru_5C6E00->Sin( pGame->pIndoorCameraD3D->sRotationY);
+    int_cosine_y = stru_5C6E00->Cos( pGame->pIndoorCameraD3D->sRotationY);
+    int_sine_x   = stru_5C6E00->Sin(-pGame->pIndoorCameraD3D->sRotationX);
+    int_cosine_x = stru_5C6E00->Cos(-pGame->pIndoorCameraD3D->sRotationX);
+  }
+  else
+  {
+    fRotationXSine = sin((3.141592653589793 + 3.141592653589793) * (double)sRotationX / 2048.0);
+    fRotationXCosine = cos((3.141592653589793 + 3.141592653589793) * (double)sRotationX / 2048.0);
+
+    int_sine_y   = stru_5C6E00->Sin(pGame->pIndoorCameraD3D->sRotationY);
+    int_cosine_y = stru_5C6E00->Cos(pGame->pIndoorCameraD3D->sRotationY);
+    int_sine_x   = stru_5C6E00->Sin(pGame->pIndoorCameraD3D->sRotationX);
+    int_cosine_x = stru_5C6E00->Cos(pGame->pIndoorCameraD3D->sRotationX);
+  }
 }
\ No newline at end of file
--- a/IndoorCameraD3D.h	Wed Sep 18 06:30:53 2013 +0200
+++ b/IndoorCameraD3D.h	Wed Sep 18 06:32:15 2013 +0200
@@ -1,5 +1,5 @@
 #pragma once
-
+#include "VectorTypes.h"
 
 
 
@@ -110,6 +110,13 @@
 };
 #pragma pack(pop)
 
+
+
+#define BLV_RENDER_DRAW_SW_OUTLINES      (1 << 0) // 1
+#define BLV_RENDER_DRAW_D3D_OUTLINES     (1 << 1) // 2
+#define ODM_RENDER_DRAW_D3D_OUTLINES     (1 << 2) // 4
+#define ODM_RENDER_DRAW_TERRAIN_OUTLINES (1 << 3) // 8
+
 /*  123 */
 #pragma pack(push, 1)
 struct IndoorCameraD3D
@@ -156,8 +163,9 @@
   void ViewTransform(struct RenderVertexSoft *a1a, unsigned int uNumVertices);
   bool IsCulled(struct BLVFace *pFace);
   void ViewTransfrom_OffsetUV(struct RenderVertexSoft *pVertices, unsigned int uNumVertices, struct RenderVertexSoft *pOutVertices, struct stru320 *a5);
-  char ApplyViewTransform_TrueIfStillVisible(int x, int y, int z, signed int *pOutX, int *pOutZ, int *pOutY, char bDoNotShow);
+  bool ApplyViewTransform_TrueIfStillVisible_BLV(int x, int y, int z, signed int *pOutX, int *pOutZ, int *pOutY, char bDoNotShow);
   float GetPickDepth();
+  float GetShadingDistMist();
 
   void DebugDrawPortal(struct BLVFace *pFace);
 
@@ -172,14 +180,14 @@
   float fov_x;
   float fov_y;
   float inv_fov;
-  float blv_party_x;
-  float blv_party_y;
-  float blv_party_z;
+  float _unused_blv_party_x;
+  float _unused_blv_party_y;
+  float _unused_blv_party_z;
   char field_E8[32];
   float field_108;
-  float blv_party_x_2;
-  float blv_party_y_2;
-  float blv_party_z_2;
+  float _unused_blv_party_x_2;
+  float _unused_blv_party_y_2;
+  float _unused_blv_party_z_2;
   char field_118[32];
   float field_138;
   char field_13C[44];
@@ -222,5 +230,26 @@
   unsigned int list_0037C_size;
   IndoorCameraD3D_stru2 list_E0380[256];
   int list_E0380_size;
+
+
+  void CalculateRotations(int camera_rot_x, int camera_rot_y);
+  int       sRotationY;        // moved  from 157 struct IndoorCamera::18
+  int       sRotationX;        // moved  from 157 struct IndoorCamera::14
+  float     fRotationYSine;    // moved  from 157 struct IndoorCamera::2C
+  float     fRotationYCosine;  // moved  from 157 struct IndoorCamera::30
+  float     fRotationXSine;    // moved  from 157 struct IndoorCamera::34
+  float     fRotationXCosine;  // moved  from 157 struct IndoorCamera::38
+  Vec3<int> vPartyPos;         // moved  from 157 struct IndoorCamera::00
+                               // merged from 162 struct BLVRenderParams::08
+  int        debug_flags;      // moved  from 157 struct IndoorCamera::4C
+                               // merged from 162 struct BLVRenderParams::04
+  int        int_sine_y;       // moved  from 157 struct ODMRenderParams::1C
+                               // merged from 162 struct BLVRenderParams::24
+  int        int_cosine_y;     // moved  from 157 struct ODMRenderParams::20
+                               // merged from 162 struct BLVRenderParams::20
+  int        int_sine_x;       // moved  from 157 struct ODMRenderParams::24
+                               // merged from 162 struct BLVRenderParams::2C
+  int        int_cosine_x;     // moved  from 157 struct ODMRenderParams::28
+                               // merged from 162 struct BLVRenderParams::28
 };
 #pragma pack(pop)
\ No newline at end of file
--- a/LOD.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/LOD.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -2151,10 +2151,10 @@
   v5->pLevelOfDetail0_prolly_alpha_mask = 0;
   if ( v6 )
   {
-    v7 = operator new(v6);
+    v7 = malloc(v6);
     v8 = v5->uTextureSize;
     v5->pLevelOfDetail0_prolly_alpha_mask = (unsigned __int8 *)v7;
-    pContainer = (const char *)operator new(v8);
+    pContainer = (const char *)malloc(v8);
     fread((void *)pContainer, 1u, (size_t)pDst, File);
     zlib::MemUnzip(v5->pLevelOfDetail0_prolly_alpha_mask, &v5->uDecompressedSize, pContainer, v5->uTextureSize);
     v9 = (void *)pContainer;
@@ -2163,7 +2163,7 @@
   }
   else
   {
-    v10 = (unsigned __int8 *)operator new(0);
+    v10 = (unsigned __int8 *)malloc(0);
     v11 = File;
     v5->pLevelOfDetail0_prolly_alpha_mask = v10;
     fread(v10, 1u, (size_t)pDst, v11);
@@ -2171,7 +2171,7 @@
   v5->pPalette24 = 0;
   if ( uTextureType == 1 )
   {
-    v12 = operator new(0x300u);
+    v12 = malloc(0x300u);
     v13 = File;
     v5->pPalette24 = (unsigned __int8 *)v12;
     fread(v12, 1u, 0x300u, v13);
@@ -2183,7 +2183,7 @@
     goto LABEL_10;
   v18 = 0;
   v5->pPalette16 = 0;
-  v5->pPalette16 = (unsigned __int16 *)operator new(0x400u);
+  v5->pPalette16 = (unsigned __int16 *)malloc(0x400u);
   do
   {
     fread((char *)&pContainer + 3, 1u, 1u, File);
@@ -2343,7 +2343,7 @@
         else
         {
           v4 = strlen(v3 - 2);
-          v5 = (char *)operator new(v4 + 2);
+          v5 = (char *)malloc(v4 + 2);
           *v5 = 'h';
           strcpy(v5 + 1, v3 - 2);
           pRenderer->LoadTexture(
@@ -2610,7 +2610,7 @@
     else
     {
       v11 = strlen(pContainer);
-      v12 = (enum TEXTURE_TYPE)(int)operator new(v11 + 2);
+      v12 = (enum TEXTURE_TYPE)(int)malloc(v11 + 2);
       eTextureType = v12;
       *(char *)v12 = 104;
       strcpy((char *)(v12 + 1), pContainer);
--- a/LOD.h	Wed Sep 18 06:30:53 2013 +0200
+++ b/LOD.h	Wed Sep 18 06:32:15 2013 +0200
@@ -2,11 +2,16 @@
 #include <stdio.h>
 #include <memory.h>
 
+#include "Log.h"
 #include "Texture.h"
 #include "ErrorHandling.h"
 
 class Sprite;
 
+
+#define MAX_LOD_TEXTURES 1000
+#define MAX_LOD_SPRITES  1500
+
 /*  354 */
 enum TEXTURE_TYPE
 {
@@ -164,12 +169,23 @@
   void _inlined_sub1();
   void _inlined_sub2();
 
-  inline struct Texture *GetTexture(int idx)
+  inline int LoadDummyTexture()
   {
-    Assert(idx < 1000, "Texture index out of bounds (%u)", idx);
+    for (unsigned int i = 0; i < uNumLoadedFiles; ++i)
+      if (!strcmp(pTextures[i].pName, "pending"))
+        return i;
+    return LoadTextureFromLOD(&pTextures[uNumLoadedFiles], "pending", TEXTURE_16BIT_PALETTE);
+  }
+
+  inline Texture *GetTexture(int idx)
+  {
+    Assert(idx < MAX_LOD_TEXTURES, "Texture index out of bounds (%u)", idx);
     if (idx == -1) 
-      return nullptr; // we need to return dummy texture here
-    return &pTextures[idx];
+    {
+      //Log::Warning(L"Texture id = %d missing", idx);
+      return pTextures + LoadDummyTexture();
+    }
+    return pTextures + idx;
   }
 
 
@@ -187,7 +203,7 @@
   struct LOD::Directory *pSubIndices;
   unsigned int uOffsetToSubIndex;
   FILE *pOutputFileHandle;*/
-  struct Texture pTextures[1000];
+  Texture pTextures[MAX_LOD_TEXTURES];
   unsigned int uNumLoadedFiles;
   int dword_11B80;
   int dword_11B84;
@@ -278,7 +294,7 @@
   struct LOD::Directory *pSubIndices;
   unsigned int uOffsetToSubIndex;
   FILE *pOutputFileHandle;*/
-  struct LODSprite pSpriteHeaders[1500];
+  struct LODSprite pSpriteHeaders[MAX_LOD_SPRITES];
   signed int uNumLoadedSprites;
   int field_ECA0;
   int field_ECA4;
--- a/LightmapBuilder.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/LightmapBuilder.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -6,7 +6,6 @@
 #include "Log.h"
 #include "ErrorHandling.h"
 
-#include "OutdoorCamera.h"
 #include "Lights.h"
 
 #include "mm7_data.h"
@@ -1312,223 +1311,6 @@
   ++*v53;
   return 1;
 }
-// 4E94D2: using guessed type char _4E94D2_light_type;
-
-//----- (0045D3C7) --------------------------------------------------------
-bool LightmapBuilder::_45D3C7(struct Polygon *a1)
-{
-  LightmapBuilder *v2; // ebx@1
-  struct Polygon *result; // eax@1
-  float v4; // ecx@2
-  Span *i; // edi@5
-
-  v2 = this;
-  result = (struct Polygon *)a1->prolly_head;
-  if ( result && (v4 = result->field_4, *(int *)&v4) != 0 && *(unsigned int *)(LODWORD(v4) + 60) )
-  {
-    for ( i = a1->prolly_head; ; i = i->pNext )
-    {
-      result = i->pParent;
-      if ( result->field_108 )
-        result = (struct Polygon *)_45D426(
-                              i,
-                              a1->pEdgeList1,
-                              a1->uEdgeList1Size,
-                              (Edge *)a1->pEdgeList2,
-                              a1->uEdgeList2Size);
-      if ( a1->prolly_tail == i )
-        break;
-    }
-    LOBYTE(result) = 1;
-  }
-  else
-  {
-    LOBYTE(result) = 0;
-  }
-  return (bool)result;
-}
-
-//----- (0045D426) --------------------------------------------------------
-int LightmapBuilder::_45D426(Span *a1, Edge **a2, unsigned int a3, Edge *a4, int a5)
-{
-  int v6; // edi@1
-  signed int v7; // ebx@3
-  signed int v8; // ecx@3
-  Span *v9; // esi@3
-  double v10; // st7@4
-  Edge *v11; // edx@5
-  double v12; // st7@11
-  int v13; // edx@12
-  int v14; // ebx@17
-  Edge *v15; // edi@17
-  float v16; // ST04_4@17
-  float v17; // ST04_4@17
-  double v18; // st7@17
-  int result; // eax@19
-  //double v20; // ST14_8@20
-  //double v21; // ST14_8@20
-  double v22; // st7@20
-  int v23; // ecx@20
-  double v24; // st6@20
-  double v25; // st7@23
-  double v26; // st7@28
-  __int16 v27; // fps@28
-  char v28; // c0@28
-  char v29; // c2@28
-  char v30; // c3@28
-  double v31; // st7@29
-  double v32; // st7@30
-  __int16 v33; // fps@30
-  char v34; // c0@30
-  char v35; // c2@30
-  char v36; // c3@30
-  LightmapBuilder *this_4; // [sp+14h] [bp-8h]@1
-  signed int v38; // [sp+18h] [bp-4h]@3
-  float a1a; // [sp+24h] [bp+8h]@20
-  float a2a; // [sp+28h] [bp+Ch]@17
-  float a3a; // [sp+2Ch] [bp+10h]@17
-  float a5a; // [sp+34h] [bp+18h]@20
-  float a5b; // [sp+34h] [bp+18h]@20
-
-  v6 = 0;
-  this_4 = this;
-  if ( a5 && a3 )
-  {
-    v7 = -1;
-    v8 = 0;
-    v9 = a1;
-    v38 = -1;
-    if ( (signed int)a3 > 0 )
-    {
-      v10 = (double)a1->field_A;
-      while ( 1 )
-      {
-        v11 = a2[v8];
-        if ( v10 >= v11->field_2C )
-        {
-          if ( v10 <= v11->field_30 )
-            break;
-        }
-        ++v8;
-        if ( v8 >= (signed int)a3 )
-          goto LABEL_10;
-      }
-      v38 = v8;
-    }
-LABEL_10:
-    if ( a5 > 0 )
-    {
-      v12 = (double)a1->field_A;
-      while ( 1 )
-      {
-        v13 = *((unsigned int *)&a4->field_0 + v6);
-        if ( v12 >= *(float *)(v13 + 44) )
-        {
-          if ( v12 <= *(float *)(v13 + 48) )
-            break;
-        }
-        ++v6;
-        if ( v6 >= a5 )
-          goto LABEL_17;
-      }
-      v7 = v6;
-    }
-LABEL_17:
-    v14 = *((unsigned int *)&a4->field_0 + v7);
-    v15 = a2[v38];
-    v16 = (double)a1->field_A;
-    a3a = _45D643(a2[v38], v16);
-    v17 = (double)a1->field_A;
-    v18 = _45D643((Edge *)v14, v17);
-    a2a = v18;
-    if ( byte_4D864C && BYTE1(pGame->uFlags) & 0x80 )
-    {
-      HIWORD(result) = HIWORD(a3a);
-      a1->field_14 = v18;
-      a1->field_10 = a3a;
-    }
-    else
-    {
-      a5a = ((double)a1->field_A - v15->field_2C) * v15->field_4 + v15->field_24 - 0.5;
-      //v20 = a5a + 6.7553994e15;
-      //a5b = (double)SLODWORD(v20);
-      a5b = (double)floorf(a5a + 0.5f);
-      a1a = ((double)a1->field_A - *(float *)(v14 + 44)) * *(float *)(v14 + 4) + *(float *)(v14 + 36) + 0.5;
-      //v21 = a1a + 6.7553994e15;
-      //v22 = (double)SLODWORD(v21);
-      v22 = (double)floorf(a1a + 0.5f);
-      result = v9->field_8;
-      v23 = v9->field_C;
-      v24 = -((a3a - a2a) / (v22 - a5b));
-      v9->field_10 = ((double)result - a5b) * v24 + a3a;
-      v9->field_14 = a2a - (v22 - (double)(result + v23)) * v24;
-    }
-    if ( v9->field_10 < 0.0 || v9->field_10 <= 1.0 )
-    {
-      if ( v9->field_10 >= 0.0 )
-        v25 = v9->field_10;
-      else
-        v25 = 0.0;
-    }
-    else
-    {
-      v25 = 1.0;
-    }
-    v9->field_10 = v25;
-      __debugbreak(); // warning C4700: uninitialized local variable 'v27' used
-    if ( v9->field_14 < 0.0
-      || (v26 = v9->field_14,
-          //UNDEF(v27),
-          v28 = 1.0 < v26,
-          v29 = 0,
-          v30 = 1.0 == v26,
-          BYTE1(result) = HIBYTE(v27),
-          v26 <= 1.0) )
-    {
-      v32 = v9->field_14;
-      //UNDEF(v33);
-      v34 = 0.0 < v32;
-      v35 = 0;
-      v36 = 0.0 == v32;
-      __debugbreak(); // warning C4700: uninitialized local variable 'v33' used
-      BYTE1(result) = HIBYTE(v33);
-      if ( v32 >= 0.0 )
-        v31 = v9->field_14;
-      else
-        v31 = 0.0;
-    }
-    else
-    {
-      v31 = 1.0;
-    }
-    v9->field_14 = v31;
-    LOBYTE(result) = 1;
-  }
-  else
-  {
-    LOBYTE(result) = 0;
-  }
-  return result;
-}
-// 4D864C: using guessed type char byte_4D864C;
-
-//----- (0045D643) --------------------------------------------------------
-double LightmapBuilder::_45D643(Edge *a1, float a2)
-{
-  double result; // st7@1
-
-  result = (a1->field_1C - a1->field_20) * -1.0 / (a1->field_30 - a1->field_2C) * (a2 - a1->field_2C) + a1->field_1C;
-  if ( result < 0.0 || result <= 1.0 )
-  {
-    if ( result < 0.0 )
-      result = 0.0;
-  }
-  else
-  {
-    result = 1.0;
-  }
-  return result;
-}
 
 //----- (0045D698) --------------------------------------------------------
 bool LightmapBuilder::DrawDebugOutlines(char bit_one_for_list1__bit_two_for_list2)
@@ -1741,7 +1523,7 @@
   uint uLightmapColor = uLightmapColorB | (uLightmapColorMaskG << 8) | (uLightmapColorMaskR << 16);
 
   if (uCurrentlyLoadedLevelType == LEVEL_Outdoor)
-    v10 = (double)pOutdoorCamera->shading_dist_mist;
+    v10 = (double)pODMRenderParams->shading_dist_mist;
   else
     v10 = 16192.0;
   v14 = 1.0 / v10;
--- a/LightmapBuilder.h	Wed Sep 18 06:30:53 2013 +0200
+++ b/LightmapBuilder.h	Wed Sep 18 06:32:15 2013 +0200
@@ -41,9 +41,9 @@
   bool DrawLightmaps(int *indices = nullptr);
   void DrawLightmapsType(int type);
   bool DrawDebugOutlines(char bit_one_for_list1__bit_two_for_list2);
-  double _45D643(struct Edge *a1, float a2);
-  int _45D426(struct Span *a1, struct Edge **a2, unsigned int a3, struct Edge *a4, int a5);
-  bool _45D3C7(struct Polygon *a1);
+  double _45D643_sw(struct Edge *a1, float a2);
+  //int _45D426_sw(struct Span *a1, struct Edge **a2, unsigned int a3, struct Edge *a4, int a5);
+  //bool _45D3C7_sw(struct Polygon *a1);
   bool StackLight_TerrainFace(struct StationaryLight *pLight, struct Vec3_float_ *pNormal, float *a3, struct RenderVertexSoft *a1, unsigned int uStripType, int X, unsigned int *pSlot);
   bool StackLights_TerrainFace(struct Vec3_float_ *pNormal, float *a3, struct RenderVertexSoft *a1, unsigned int uStripType, bool bLightBackfaces);
   bool ApplyLight_ODM(struct StationaryLight *pLight, struct ODMFace *pFace, unsigned int *pSlot, char a4);
--- a/Math.h	Wed Sep 18 06:30:53 2013 +0200
+++ b/Math.h	Wed Sep 18 06:32:15 2013 +0200
@@ -24,12 +24,12 @@
 };
 #pragma pack(pop)
 
-__int64 fixpoint_sub0(int, int);
-__int64 fixpoint_sub2(int, int);
+__int64 fixpoint_mul(int, int);
 __int64 fixpoint_dot(int x1, int x2, int y1, int y2, int z1, int z2);
 __int64 fixpoint_div(int, int);
-__int64 fixpoint_mul(int, int);
+__int64 fixpoint_sub_unknown(int, int);
 int fixpoint_from_float(float value);
+int fixpoint_from_int(int lhv, int rhv);
 
 template <typename FloatType>
 inline int bankersRounding(
--- a/Mouse.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/Mouse.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -414,7 +414,7 @@
       {
         if ( this->pCursorBitmap3_sysmembits_16bit )
           free(this->pCursorBitmap3_sysmembits_16bit);
-        this->pCursorBitmap3_sysmembits_16bit = (unsigned __int16 *)operator new(2 * pTexture->uTextureHeight * pTexture->uTextureWidth);
+        this->pCursorBitmap3_sysmembits_16bit = (unsigned __int16 *)malloc(2 * pTexture->uTextureHeight * pTexture->uTextureWidth);
         this->field_40 = a2;
         this->field_48 = a2 + pTextureWidth;
         this->field_44 = v6;
--- a/Outdoor.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/Outdoor.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -14,7 +14,6 @@
 #include "PaletteManager.h"
 #include "GUIProgressBar.h"
 #include "AudioPlayer.h"
-#include "IndoorCamera.h"
 #include "DecorationList.h"
 #include "Math.h"
 #include "ObjectList.h"
@@ -33,7 +32,6 @@
 
 
 #include "MapInfo.h"
-#include "OutdoorCamera.h"
 #include "Outdoor_stuff.h"
 #include "BSPModel.h"
 #include "GUIWindow.h"
@@ -41,15 +39,11 @@
 MapStartPoint uLevel_StartingPointType; // weak
 
 OutdoorLocation *pOutdoor = new OutdoorLocation;
-OutdoorCamera *pOutdoorCamera;
+ODMRenderParams *pODMRenderParams;
 
 
 stru149 stru_8019C8;
 std::array<struct Polygon, 2000 + 18000> array_77EC08;
-Surf stru_80C980;
-Edge defaultEdge; // weak
-Edge stru_80C9A4;
-Edge stru_80C9D8;
 
 
 struct FogProbabilityTableEntry
@@ -93,25 +87,19 @@
   int v4; // ST04_4@19
   int v5; // eax@19
 
-  pIndoorCamera->flags = 0;
+  pGame->pIndoorCameraD3D->debug_flags = 0;
   if (viewparams->draw_d3d_outlines)
-    pIndoorCamera->flags |= INDOOR_CAMERA_DRAW_D3D_OUTLINES;
-  //INDOOR_CAMERA_DRAW_TERRAIN_OUTLINES
+    pGame->pIndoorCameraD3D->debug_flags |= ODM_RENDER_DRAW_D3D_OUTLINES;
 
-  pIndoorCamera->sRotationX = pParty->sRotationX;
-  pIndoorCamera->sRotationY = pParty->sRotationY;
-  pIndoorCamera->pos.x = pParty->vPosition.x - fixpoint_sub0(stru_5C6E00->Cos(pParty->sRotationY), pParty->y_rotation_granularity);
-  pIndoorCamera->pos.y = pParty->vPosition.y - fixpoint_sub0(stru_5C6E00->Sin(pParty->sRotationY), pParty->y_rotation_granularity);
-  pIndoorCamera->pos.z = pParty->vPosition.z + pParty->sEyelevel;
   if (bRedraw || pRenderer->pRenderD3D)
   {
-    pOutdoorCamera->RotationToInts();
-    sub_481ED9_MessWithOutdoorCamera();
+    //pODMRenderParams->RotationToInts();
+    sub_481ED9_MessWithODMRenderParams();
   }
 
-  pIndoorCamera->uMapGridCellX = WorldPosToGridCellX(pParty->vPosition.x);
-  pIndoorCamera->uMapGridCellZ = WorldPosToGridCellZ(pParty->vPosition.y);
-  assert(pIndoorCamera->uMapGridCellX <= 127 && pIndoorCamera->uMapGridCellZ <= 127);
+  pODMRenderParams->uMapGridCellX = WorldPosToGridCellX(pParty->vPosition.x);
+  pODMRenderParams->uMapGridCellZ = WorldPosToGridCellZ(pParty->vPosition.y);
+  assert(pODMRenderParams->uMapGridCellX <= 127 && pODMRenderParams->uMapGridCellZ <= 127);
 
   if (bRedraw)
   {
@@ -138,7 +126,7 @@
       pRenderer->DrawBuildingsSW();  
       pRenderer->DrawBezierTerrain();
       sr_sub_486F92_MessWithEdgesAndSpans();
-      pOutdoorCamera->_487355();
+      pODMRenderParams->ApplyLightmapsSW();
     }*/
   }
 
@@ -165,17 +153,15 @@
     pGame->pLightmapBuilder->uFlags &= 0xFFFFFFFEu;
 
   uNumDecorationsDrawnThisFrame = 0;
-  _unused000 = 0;
   uNumSpritesDrawnThisFrame = 0;
   uNumBillboardsToDraw = 0;
 
   PrepareActorsDrawList();
-  if (!pOutdoorCamera->bDoNotRenderDecorations)
+  if (!pODMRenderParams->bDoNotRenderDecorations)
     pRenderer->PrepareDecorationsRenderList_ODM();
 
   pRenderer->DrawSpriteObjects_ODM();
   pRenderer->TransformBillboardsAndSetPalettesODM();
-  //sr_485F53((Vec2_int_ *)sr_6BE060.data());
 }
 
 
@@ -758,9 +744,9 @@
     v22 = v6->vWorldViewPosition.y - v4->vWorldViewPosition.y;
     v23 = v6->vWorldViewPosition.z - v4->vWorldViewPosition.z;
   }
-  if ( ((double)pIndoorCamera->pos.x - v4->vWorldPosition.x) * v26
-     + ((double)pIndoorCamera->pos.z - v4->vWorldPosition.z) * v25
-     + ((double)pIndoorCamera->pos.y - v4->vWorldPosition.y) * v24 > 0.0 )
+  if ( ((double)pGame->pIndoorCameraD3D->vPartyPos.x - v4->vWorldPosition.x) * v26
+     + ((double)pGame->pIndoorCameraD3D->vPartyPos.z - v4->vWorldPosition.z) * v25
+     + ((double)pGame->pIndoorCameraD3D->vPartyPos.y - v4->vWorldPosition.y) * v24 > 0.0 )
   {
     a3b = v23 * v18 - v22 * v20;
     v14 = a3b + 6.7553994e15;
@@ -2958,8 +2944,8 @@
             z = actor->vPosition.z;
         }
       }
-      v8 = stru_5C6E00->Atan2(actor->vPosition.x - pIndoorCamera->pos.x,
-                              actor->vPosition.y - pIndoorCamera->pos.y);
+      v8 = stru_5C6E00->Atan2(actor->vPosition.x - pGame->pIndoorCameraD3D->vPartyPos.x,
+                              actor->vPosition.y - pGame->pIndoorCameraD3D->vPartyPos.y);
 	  LOWORD(v9) = actor->uYawAngle;
       v41 = ((signed int)(stru_5C6E00->uIntegerPi + ((signed int)stru_5C6E00->uIntegerPi >> 3) + v9 - v8) >> 8) & 7;
 	  v10 = actor->uCurrentActionAnimation;
@@ -3014,50 +3000,50 @@
         //LOBYTE(v16) = byte_4E94D3;
         pMobileLightsStack->AddLight(x, y, z, 0, v15->uGlowRadius, 0xFFu, 0xFFu, 0xFFu, byte_4E94D3);
       }
-      v17 = (x - pIndoorCamera->pos.x) << 16;
-      if ( pIndoorCamera->sRotationX )
+      v17 = (x - pGame->pIndoorCameraD3D->vPartyPos.x) << 16;
+      if (pGame->pIndoorCameraD3D->sRotationX)
       {
-        v18 = (y - pIndoorCamera->pos.y) << 16;
-        v47 = ((unsigned __int64)(v17 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16)
-            + ((unsigned __int64)(v18 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16);
-        v50 = (unsigned __int64)(v17 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16;
-        v53 = (unsigned __int64)(v18 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16;
-        v44 = (z - pIndoorCamera->pos.z) << 16;
-        v19 = ((unsigned __int64)(v44 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_sine) >> 16)
-            + ((unsigned __int64)(v47 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_cosine) >> 16);
-        X = ((unsigned __int64)(v44 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_sine) >> 16)
-          + ((unsigned __int64)(v47 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_cosine) >> 16);
-        if ( v19 < 262144 || v19 > pOutdoorCamera->shading_dist_mist << 16 )
+        v18 = (y - pGame->pIndoorCameraD3D->vPartyPos.y) << 16;
+        v47 = ((unsigned __int64)(v17 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16)
+            + ((unsigned __int64)(v18 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16);
+        v50 = (unsigned __int64)(v17 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
+        v53 = (unsigned __int64)(v18 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16;
+        v44 = (z - pGame->pIndoorCameraD3D->vPartyPos.z) << 16;
+        v19 = ((unsigned __int64)(v44 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16)
+            + ((unsigned __int64)(v47 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16);
+        X = ((unsigned __int64)(v44 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16)
+          + ((unsigned __int64)(v47 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16);
+        if ( v19 < 262144 || v19 > pODMRenderParams->shading_dist_mist << 16 )
           continue;
         v20 = v53 - v50;
         v42 = v53 - v50;
-        v21 = ((unsigned __int64)(v44 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_cosine) >> 16)
-            - ((unsigned __int64)(v47 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_sine) >> 16);
+        v21 = ((unsigned __int64)(v44 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16)
+            - ((unsigned __int64)(v47 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16);
       }
       else
       {
-        v48 = (y - pIndoorCamera->pos.y) << 16;
-        v51 = (unsigned __int64)(v17 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16;
-        v22 = (unsigned __int64)(v48 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16;
+        v48 = (y - pGame->pIndoorCameraD3D->vPartyPos.y) << 16;
+        v51 = (unsigned __int64)(v17 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16;
+        v22 = (unsigned __int64)(v48 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
         X = v22 + v51;
-        if ( v22 + v51 < 262144 || v22 + v51 > pOutdoorCamera->shading_dist_mist << 16 )
+        if ( v22 + v51 < 262144 || v22 + v51 > pODMRenderParams->shading_dist_mist << 16 )
           continue;
-        v23 = (unsigned __int64)(((x - pIndoorCamera->pos.x) << 16)
-                               * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16;
-        v20 = ((unsigned __int64)(v48 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16) - v23;
-        v42 = ((unsigned __int64)(v48 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16) - v23;
-        v21 = (z - pIndoorCamera->pos.z) << 16;
+        v23 = (unsigned __int64)(((x - pGame->pIndoorCameraD3D->vPartyPos.x) << 16)
+                               * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
+        v20 = ((unsigned __int64)(v48 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16) - v23;
+        v42 = ((unsigned __int64)(v48 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16) - v23;
+        v21 = (z - pGame->pIndoorCameraD3D->vPartyPos.z) << 16;
       }
       v45 = v21;
       v24 = abs(v20);
       if ( abs(X) >= v24 )
       {
         LODWORD(v25) = 0;
-        HIDWORD(v25) = SLOWORD(pOutdoorCamera->int_fov_rad);
+        HIDWORD(v25) = SLOWORD(pODMRenderParams->int_fov_rad);
         v58 = v25 / X;
         v26 = v25 / X;
         LODWORD(v25) = 0;
-        HIDWORD(v25) = SLOWORD(pOutdoorCamera->int_fov_rad);
+        HIDWORD(v25) = SLOWORD(pODMRenderParams->int_fov_rad);
         v57 = v25 / X;
         v27 = pViewport->uScreenCenterX
             - ((signed int)(((unsigned __int64)(v26 * (signed __int64)v42) >> 16) + 32768) >> 16);
@@ -3128,8 +3114,6 @@
   }
   //return result;
 }
-// 4E94D3: using guessed type char byte_4E94D3;
-// 5187E4: using guessed type int uNumSpritesDrawnThisFrame;
 
 //----- (0044C1E8) --------------------------------------------------------
 bool ODMFace::HasEventHint()
@@ -3534,7 +3518,7 @@
     pActors[ai_near_actors_ids[i]].uAttributes |= 0x0400;
 }
 //----- (0046BE0A) --------------------------------------------------------
-void  ODM_UpdateUserInputAndOther()
+void ODM_UpdateUserInputAndOther()
 {
   bool v0; // eax@5
   char pOut[32]; // [sp+8h] [bp-20h]@5
@@ -3569,7 +3553,7 @@
   check_event_triggers();
 }
 //----- (0041F54A) --------------------------------------------------------
-void  LoadActualSkyFrame()
+void LoadActualSkyFrame()
 {
   if ( pTexture_RestUI_CurrentSkyFrame )
     pTexture_RestUI_CurrentSkyFrame->Release();
@@ -3605,3 +3589,61 @@
   pOMAP = 0;
 }
 
+
+
+
+//----- (00481E55) --------------------------------------------------------
+void ODM_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)pODMRenderParams->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 );
+  }
+}
+//----- (00485F64) --------------------------------------------------------
+void ODMRenderParams::Initialize()
+{
+  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;
+  //sr_6BE060[1] = 1;
+  //RotationToInts();
+}
--- a/Outdoor.h	Wed Sep 18 06:30:53 2013 +0200
+++ b/Outdoor.h	Wed Sep 18 06:32:15 2013 +0200
@@ -101,7 +101,7 @@
   signed __int16 pXInterceptDisplacements[20];
   signed __int16 pYInterceptDisplacements[20];
   signed __int16 pZInterceptDisplacements[20];
-  unsigned __int16 uTextureID;
+  __int16 uTextureID;
   __int16 sTextureDeltaU;
   __int16 sTextureDeltaV;
   struct BBox_short_ pBoundingBox;
--- a/OutdoorCamera.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-#include "OutdoorCamera.h"
-#include "IndoorCamera.h"
-#include "Outdoor_stuff.h"
-#include "Game.h"
-#include "LightmapBuilder.h"
-#include "Viewport.h"
-#include "Math.h"
-#include "mm7_data.h"
-
-//----- (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 );
-  }
-}
-//----- (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;
-  //sr_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);
-}
\ No newline at end of file
--- a/OutdoorCamera.h	Wed Sep 18 06:30:53 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-#pragma once
-
-
-/*   88 */
-#pragma pack(push, 1)
-struct OutdoorCamera
-{
-  //----- (00462684) --------------------------------------------------------
-  OutdoorCamera()
-  {
-    uPickDepth = 0;
-    this->shading_dist_shade = 2048;
-    shading_dist_shademist = 4096;
-    shading_dist_mist = 8192;
-    int_fov_rad = 0;
-    this->bNoSky = 0;
-    this->bDoNotRenderDecorations = 0;
-    this->field_5C = 0;
-    this->field_60 = 0;
-    this->outdoor_no_wavy_water = 0;
-    this->outdoor_no_mist = 0;
-  }
-
-  void _485F64();
-  void RotationToInts();
-  //void AllocSoftwareDrawBuffers();
-  //void ReleaseSoftwareDrawBuffers();
-
-  static void Project(unsigned int uNumVertices);
-  //static bool _487355();
-
-
-
-
-  int uPickDepth;
-  int shading_dist_shade;
-  int shading_dist_shademist;
-  int shading_dist_mist;
-  unsigned int uCameraFovInDegrees;
-  int int_fov_rad;
-  int int_fov_rad_inv;
-  int camera_rotation_y_int_sine;
-  int camera_rotation_y_int_cosine;
-  int camera_rotation_x_int_sine;
-  int camera_rotation_x_int_cosine;
-  int uNumPolygons;
-  unsigned int uNumEdges;
-  unsigned int uNumSurfs;
-  unsigned int uNumSpans;
-  unsigned int uNumBillboards;
-  float field_40;
-  int field_44;
-  int outdoor_grid_band_3;
-  int field_4C;
-  int field_50;
-  unsigned int bNoSky;
-  unsigned int bDoNotRenderDecorations;
-  int field_5C;
-  int field_60;
-  int outdoor_no_wavy_water;
-  int outdoor_no_mist;
-  int building_gamme;
-  int terrain_gamma;
-};
-#pragma pack(pop)
-
-
-
-
-extern struct OutdoorCamera *pOutdoorCamera;
\ No newline at end of file
--- a/Outdoor_stuff.h	Wed Sep 18 06:30:53 2013 +0200
+++ b/Outdoor_stuff.h	Wed Sep 18 06:32:15 2013 +0200
@@ -36,8 +36,8 @@
   int field_34;
   struct stru149 *ptr_38;
   struct Texture *pTexture;
-  struct Span *prolly_head;
-  struct Span *prolly_tail;
+  struct Span *_unused_prolly_head;
+  struct Span *_unused_prolly_tail;
   int **ptr_48;
   unsigned __int16 uTileBitmapID;
   __int16 field_4E;
@@ -88,73 +88,64 @@
 extern stru149 stru_8019C8;
 
 
-
-/*  143 */
+/*   88 */
 #pragma pack(push, 1)
-struct Span
+struct ODMRenderParams
 {
-  Span *pNext;
-  struct Polygon *pParent;
-  __int16 field_8;
-  __int16 field_A;
-  __int16 field_C;
-  __int16 field_E;
-  float field_10;
-  float field_14;
+  //----- (00462684) --------------------------------------------------------
+  ODMRenderParams()
+  {
+    uPickDepth = 0;
+    this->shading_dist_shade = 2048;
+    shading_dist_shademist = 4096;
+    shading_dist_mist = 8192;
+    int_fov_rad = 0;
+    this->bNoSky = 0;
+    this->bDoNotRenderDecorations = 0;
+    this->field_5C = 0;
+    this->field_60 = 0;
+    this->outdoor_no_wavy_water = 0;
+    this->outdoor_no_mist = 0;
+  }
+
+  void Initialize();
+
+  int uPickDepth;
+  int shading_dist_shade;
+  int shading_dist_shademist;
+  int shading_dist_mist;
+  unsigned int uCameraFovInDegrees;
+  int int_fov_rad;                          // 157 struct IndoorCamera::fov_rad
+  int int_fov_rad_inv;                      // 157 struct IndoorCamera::fov_rad_inv
+  int _unused_camera_rotation_y_int_sine;   // merged with BLVRenderParams equivalents
+  int _unused_camera_rotation_y_int_cosine; // into IndoorCameraD3D
+  int _unused_camera_rotation_x_int_sine;   // --//--
+  int _unused_camera_rotation_x_int_cosine; // --//--
+  int uNumPolygons;
+  unsigned int _unused_uNumEdges;
+  unsigned int _unused_uNumSurfs;
+  unsigned int _unused_uNumSpans;
+  unsigned int uNumBillboards;
+  float field_40;
+  int field_44;
+  int outdoor_grid_band_3;
+  int field_4C;
+  int field_50;
+  unsigned int bNoSky;
+  unsigned int bDoNotRenderDecorations;
+  int field_5C;
+  int field_60;
+  int outdoor_no_wavy_water;
+  int outdoor_no_mist;
+  int building_gamme;
+  int terrain_gamma;
+
+  unsigned int uMapGridCellX; // moved from 157 struct IndoorCamera::0C
+  unsigned int uMapGridCellZ; // moved from 157 struct IndoorCamera::10
 };
 #pragma pack(pop)
+extern ODMRenderParams *pODMRenderParams;
 
 
 
-/*  144 */
-#pragma pack(push, 1)
-struct Surf
-{
-  float field_0;
-  float field_4;
-  float field_8;
-  float field_C;
-  float field_10;
-  Surf *pNext;
-  Surf *pPrev;
-  struct Polygon *pParent;
-  __int16 field_20;
-  __int16 field_22;
-};
-#pragma pack(pop)
-extern Surf stru_80C980;
-
-
-
-
-/*  145 */
-#pragma pack(push, 1)
-struct Edge
-{
-  float field_0;
-  float field_4;
-  int field_8;
-  Surf *pSurf;
-  Edge *pNext;
-  Edge *pPrev;
-  Edge *ptr_18;
-  float field_1C;
-  float field_20;
-  float field_24;
-  float field_28;
-  float field_2C;
-  float field_30;
-};
-#pragma pack(pop)
-extern Edge defaultEdge; // weak
-
-extern Edge stru_80C9A4;
-extern Edge stru_80C9D8;
-
-
-
-
-
-
-
-
+void ODM_Project(unsigned int uNumVertices);
\ No newline at end of file
--- a/ParticleEngine.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/ParticleEngine.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -4,12 +4,11 @@
 #include "Viewport.h"
 #include "Outdoor.h"
 #include "Game.h"
-#include "IndoorCamera.h"
+#include "Outdoor_stuff.h"
 #include "Math.h"
 #include "LOD.h"
 
 #include "Sprites.h"
-#include "OutdoorCamera.h"
 #include "mm7_data.h"
 
 TrailParticleGenerator trail_particle_generator;
@@ -304,9 +303,9 @@
   //uParticleID = LODWORD(pParticle->z);
   //z_int_ = *(float *)&uParticleID + 6.7553994e15;
   z_int_ = floorf(pParticle->z + 0.5f);
-  if ( !pRenderer->pRenderD3D )
+  /*if ( !pRenderer->pRenderD3D )
   {
-    if ( pBLVRenderParams->sPartyRotX )
+    if (pGame->pIndoorCameraD3D->sRotationX)
     {
       if (pParticle->type & ParticleType_Line)
       {
@@ -314,22 +313,22 @@
         int _uParticleID = (int)(floorf(pParticle->_x + 0.5f) - pBLVRenderParams->vPartyPos.x) << 16;
         //v12 = pParticle->_y + 6.7553994e15;
         y = (int)(floorf(pParticle->_y + 0.5f) - pBLVRenderParams->vPartyPos.y) << 16;
-        z = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
-        HIDWORD(a5) = ((unsigned __int64)((signed int)_uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+        z = (unsigned __int64)(y * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
+        HIDWORD(a5) = ((unsigned __int64)((signed int)_uParticleID * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16)
                     - z;
-        a6 = (unsigned __int64)((signed int)_uParticleID * (signed __int64)pBLVRenderParams->sSineY) >> 16;
+        a6 = (unsigned __int64)((signed int)_uParticleID * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
         //v13 = pParticle->_z + 6.7553994e15;
         _uParticleID = (int)(floorf(pParticle->_z + 0.5f) - pBLVRenderParams->vPartyPos.z) << 16;
-        z = ((unsigned __int64)(SHIDWORD(a5) * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16)
-          - ((unsigned __int64)((signed int)_uParticleID * (signed __int64)pBLVRenderParams->sSineNegX) >> 16);
+        z = ((unsigned __int64)(SHIDWORD(a5) * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16)
+          - ((unsigned __int64)((signed int)_uParticleID * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16);
         v14 = z;
-        HIDWORD(v13) = (unsigned __int64)(SHIDWORD(a5) * (signed __int64)pBLVRenderParams->sSineNegX) >> 16;
-        HIDWORD(a5) = (unsigned __int64)((signed int)_uParticleID * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16;
+        HIDWORD(v13) = (unsigned __int64)(SHIDWORD(a5) * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16;
+        HIDWORD(a5) = (unsigned __int64)((signed int)_uParticleID * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16;
         //LODWORD(v15) = pBLVRenderParams->field_40 << 16;
         //HIDWORD(v15) = pBLVRenderParams->field_40 >> 16;
         //v16 = v15 / z;
         v16 = fixpoint_div(pBLVRenderParams->field_40, z);
-        v17 = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sCosineY) >> 16;
+        v17 = (unsigned __int64)(y * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16;
         pParticle->_screenspace_scale = v16;
         _uParticleID = (unsigned __int64)(v16 * (signed __int64)(a6 + v17)) >> 16;
         LODWORD(v18) = pBLVRenderParams->uViewportCenterX
@@ -344,20 +343,20 @@
       }
       int _uParticleID = (x_int - pBLVRenderParams->vPartyPos.x) << 16;
       y = (y_int_ - pBLVRenderParams->vPartyPos.y) << 16;
-      HIDWORD(a5) = ((unsigned __int64)((signed int)_uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
-                  - ((unsigned __int64)(y * (signed __int64)pBLVRenderParams->sSineY) >> 16);
-      a6 = (unsigned __int64)((signed int)_uParticleID * (signed __int64)pBLVRenderParams->sSineY) >> 16;
-      z_int_4 = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sCosineY) >> 16;
+      HIDWORD(a5) = ((unsigned __int64)((signed int)_uParticleID * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16)
+                  - ((unsigned __int64)(y * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16);
+      a6 = (unsigned __int64)((signed int)_uParticleID * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
+      z_int_4 = (unsigned __int64)(y * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16;
       _uParticleID = (z_int_ - pBLVRenderParams->vPartyPos.z) << 16;
-      v21 = (unsigned __int64)((signed int)_uParticleID * (signed __int64)pBLVRenderParams->sSineNegX) >> 16;
-      v22 = ((unsigned __int64)(SHIDWORD(a5) * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16) - v21;
-      z = ((unsigned __int64)(SHIDWORD(a5) * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16) - v21;
+      v21 = (unsigned __int64)((signed int)_uParticleID * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16;
+      v22 = ((unsigned __int64)(SHIDWORD(a5) * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16) - v21;
+      z = ((unsigned __int64)(SHIDWORD(a5) * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16) - v21;
       if ( v22 < (signed int)0x40000u || v22 > (signed int)0x1F400000u )
         return 0;
       v23 = a6 + z_int_4;
       a2 = a6 + z_int_4;
-      v24 = ((unsigned __int64)((signed int)_uParticleID * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16)
-          + ((unsigned __int64)(SHIDWORD(a5) * (signed __int64)pBLVRenderParams->sSineNegX) >> 16);
+      v24 = ((unsigned __int64)((signed int)_uParticleID * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16)
+          + ((unsigned __int64)(SHIDWORD(a5) * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16);
     }
     else
     {
@@ -367,17 +366,17 @@
         int _uParticleID = ((int)floorf(pParticle->_x + 0.5f) - pBLVRenderParams->vPartyPos.x) << 16;
         //v26 = pParticle->_y + 6.7553994e15;
         y = ((int)floorf(pParticle->_y + 0.5f) - pBLVRenderParams->vPartyPos.y) << 16;
-        auto _hiword_v25 = (__int64)(y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
-        v27 = ((unsigned __int64)((signed int)_uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16) - _hiword_v25;
-        z = ((unsigned __int64)((signed int)_uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16) - _hiword_v25;
-        v28 = (unsigned __int64)((signed int)_uParticleID * (signed __int64)pBLVRenderParams->sSineY) >> 16;
+        auto _hiword_v25 = (__int64)(y * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
+        v27 = ((unsigned __int64)((signed int)_uParticleID * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16) - _hiword_v25;
+        z = ((unsigned __int64)((signed int)_uParticleID * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16) - _hiword_v25;
+        v28 = (unsigned __int64)((signed int)_uParticleID * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
         //a5 = pParticle->_z + 6.7553994e15;
         v29 = ((int)floorf(pParticle->_z + 0.5f) - pBLVRenderParams->vPartyPos.z) << 16;
         //LODWORD(v30) = pBLVRenderParams->field_40 << 16;
         //HIDWORD(v30) = pBLVRenderParams->field_40 >> 16;
         //v31 = v30 / z;
         v31 = fixpoint_div(pBLVRenderParams->field_40, z);
-        v32 = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sCosineY) >> 16;
+        v32 = (unsigned __int64)(y * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16;
         pParticle->_screenspace_scale = v31;
         _uParticleID = (unsigned __int64)(v31 * (signed __int64)(v28 + v32)) >> 16;
         LODWORD(v33) = pBLVRenderParams->uViewportCenterX - ((signed int)((unsigned __int64)(v31 * (signed __int64)(v28 + v32)) >> 16) >> 16);
@@ -389,15 +388,15 @@
       }
       int _uParticleID = (x_int - pBLVRenderParams->vPartyPos.x) << 16;
       y = (y_int_ - pBLVRenderParams->vPartyPos.y) << 16;
-      v36 = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
-      v22 = ((unsigned __int64)((signed int)_uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16) - v36;
-      z = ((unsigned __int64)((signed int)_uParticleID * (signed __int64)pBLVRenderParams->sCosineY) >> 16) - v36;
+      v36 = (unsigned __int64)(y * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
+      v22 = ((unsigned __int64)((signed int)_uParticleID * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16) - v36;
+      z = ((unsigned __int64)((signed int)_uParticleID * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16) - v36;
       if ( v22 < 262144 || v22 > 524288000 )
         return 0;
-      v37 = (unsigned __int64)((signed int)_uParticleID * (signed __int64)pBLVRenderParams->sSineY) >> 16;
-      _uParticleID = (unsigned __int64)(y * (signed __int64)pBLVRenderParams->sCosineY) >> 16;
-      v23 = v37 + ((unsigned __int64)(y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
-      a2 = v37 + ((unsigned __int64)(y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
+      v37 = (unsigned __int64)((signed int)_uParticleID * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
+      _uParticleID = (unsigned __int64)(y * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16;
+      v23 = v37 + ((unsigned __int64)(y * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16);
+      a2 = v37 + ((unsigned __int64)(y * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16);
       v24 = (z_int_ - pBLVRenderParams->vPartyPos.z) << 16;
     }
     int _uParticleID = abs(v23);
@@ -416,15 +415,15 @@
       //uParticleID = v44 >> 16;
       LODWORD(v44) = (signed int)(v44 >> 16) >> 16;
       pParticle->uScreenSpaceY = pBLVRenderParams->uViewportCenterY - v44;
-      pParticle->_screenspace_scale = fixpoint_sub0(fixpoint_from_float(pParticle->flt_28), pParticle->_screenspace_scale);
+      pParticle->_screenspace_scale = fixpoint_mul(fixpoint_from_float(pParticle->flt_28), pParticle->_screenspace_scale);
       pParticle->sZValue = z;
       return true;
     }
     return false;
-  }
+  }*/
 
   int x;
-  if ( !pGame->pIndoorCameraD3D->ApplyViewTransform_TrueIfStillVisible(
+  if ( !pGame->pIndoorCameraD3D->ApplyViewTransform_TrueIfStillVisible_BLV(
           x_int,
           y_int_,
           z_int_,
@@ -443,7 +442,7 @@
   //v7 = pParticle->flt_28;
   //pParticle->_screenspace_scale = v6 / x;
   //v8 = v7;
-  pParticle->_screenspace_scale = fixpoint_sub0(fixpoint_from_float(pParticle->flt_28), v6 / x);
+  pParticle->_screenspace_scale = fixpoint_mul(fixpoint_from_float(pParticle->flt_28), v6 / x);
   pParticle->sZValue = x;
   return true;
 }
@@ -507,10 +506,10 @@
   //int uIDf; // [sp+58h] [bp+8h]@8
   //int uIDb; // [sp+58h] [bp+8h]@9
 
-  v3 = stru_5C6E00->Cos(pIndoorCamera->sRotationX);
-  v44 = stru_5C6E00->Sin(pIndoorCamera->sRotationX);
-  v4 = stru_5C6E00->Cos(pIndoorCamera->sRotationY);
-  v5 = stru_5C6E00->Sin(pIndoorCamera->sRotationY);
+  v3 = stru_5C6E00->Cos(pGame->pIndoorCameraD3D->sRotationX);
+  v44 = stru_5C6E00->Sin(pGame->pIndoorCameraD3D->sRotationX);
+  v4 = stru_5C6E00->Cos(pGame->pIndoorCameraD3D->sRotationY);
+  v5 = stru_5C6E00->Sin(pGame->pIndoorCameraD3D->sRotationY);
 
   v6 = &pParticles[uID];
   if (v6->type == ParticleType_Invalid)
@@ -528,36 +527,36 @@
         //uIDc = (LODWORD(v8) - pIndoorCamera->pos.x) << 16;
         //v9 = v6->_y + 6.7553994e15;
         //v10 = (LODWORD(v9) - pIndoorCamera->pos.y) << 16;
-        v11 = fixpoint_mul(v6->x - pIndoorCamera->pos.x, v4) + fixpoint_mul(v6->y - pIndoorCamera->pos.y, v5);
-        //HIDWORD(v8) = fixpoint_mul(v6->x - pIndoorCamera->pos.x, v5);
+        v11 = fixpoint_sub_unknown(v6->x - pGame->pIndoorCameraD3D->vPartyPos.x, v4) + fixpoint_sub_unknown(v6->y - pGame->pIndoorCameraD3D->vPartyPos.y, v5);
+        //HIDWORD(v8) = fixpoint_sub_unknown(v6->x - pIndoorCamera->pos.x, v5);
         //v12 = v6->_z + 6.7553994e15;
         //uIDd = (LODWORD(v12) - pIndoorCamera->pos.z) << 16;
-        auto _hidword_v12 = fixpoint_sub0(v11, v3) + fixpoint_mul(v6->z - pIndoorCamera->pos.z, v44);
+        auto _hidword_v12 = fixpoint_mul(v11, v3) + fixpoint_sub_unknown(v6->z - pGame->pIndoorCameraD3D->vPartyPos.z, v44);
         LODWORD(v13) = 0;
-        HIDWORD(v13) = SLOWORD(pOutdoorCamera->int_fov_rad);
+        HIDWORD(v13) = SLOWORD(pODMRenderParams->int_fov_rad);
         //v14 = v13 / _hidword_v12;
         v6->_screenspace_scale = v13 / _hidword_v12;
         //v15 = v6->_screenspace_scale;
         v6->uScreenSpaceX = pViewport->uScreenCenterX
                           - ((signed int)((unsigned __int64)(v6->_screenspace_scale
-                                                           * (signed __int64)(fixpoint_mul(v6->y - pIndoorCamera->pos.y, v4)
-                                                                                        - fixpoint_mul(v6->x - pIndoorCamera->pos.x, v5))) >> 16) >> 16);
+                                                           * (signed __int64)(fixpoint_sub_unknown(v6->y - pGame->pIndoorCameraD3D->vPartyPos.y, v4)
+                                                                                        - fixpoint_sub_unknown(v6->x - pGame->pIndoorCameraD3D->vPartyPos.x, v5))) >> 16) >> 16);
         v6->uScreenSpaceY = pViewport->uScreenCenterY
                           - ((signed int)((unsigned __int64)(v6->_screenspace_scale
-                                                           * (signed __int64)(fixpoint_mul(v6->z - pIndoorCamera->pos.z, v3)
+                                                           * (signed __int64)(fixpoint_sub_unknown(v6->z - pGame->pIndoorCameraD3D->vPartyPos.z, v3)
                                                                                         - ((unsigned __int64)(v11 * (signed __int64)v44) >> 16))) >> 16) >> 16);
         v6->sZValue = _hidword_v12;
       }
       //uIDe = (v41 - pIndoorCamera->pos.x) << 16;
       //v47 = (LODWORD(v39) - pIndoorCamera->pos.y) << 16;
-      v45 = fixpoint_mul(v6->x - pIndoorCamera->pos.x, v4) + fixpoint_mul(v6->y - pIndoorCamera->pos.y, v5);
-      //HIDWORD(v42) = fixpoint_mul(v6->x - pIndoorCamera->pos.x, v5);
+      v45 = fixpoint_sub_unknown(v6->x - pGame->pIndoorCameraD3D->vPartyPos.x, v4) + fixpoint_sub_unknown(v6->y - pGame->pIndoorCameraD3D->vPartyPos.y, v5);
+      //HIDWORD(v42) = fixpoint_sub_unknown(v6->x - pIndoorCamera->pos.x, v5);
       //uIDa = (LODWORD(v42) - pIndoorCamera->pos.z) << 16;
-      X_4 = fixpoint_mul(v6->z - pIndoorCamera->pos.z, v44) + fixpoint_sub0(v45, v3);
+      X_4 = fixpoint_sub_unknown(v6->z - pGame->pIndoorCameraD3D->vPartyPos.z, v44) + fixpoint_mul(v45, v3);
       if ( X_4 < 0x40000 )
         return 0;
-      v16 = fixpoint_mul(v6->y - pIndoorCamera->pos.y, v4) - fixpoint_mul(v6->x - pIndoorCamera->pos.x, v5);
-      v17 = fixpoint_mul(v6->z - pIndoorCamera->pos.z, v3) - fixpoint_sub0(v45, v44);
+      v16 = fixpoint_sub_unknown(v6->y - pGame->pIndoorCameraD3D->vPartyPos.y, v4) - fixpoint_sub_unknown(v6->x - pGame->pIndoorCameraD3D->vPartyPos.x, v5);
+      v17 = fixpoint_sub_unknown(v6->z - pGame->pIndoorCameraD3D->vPartyPos.z, v3) - fixpoint_mul(v45, v44);
     }
     else
     {
@@ -569,34 +568,34 @@
         //v20 = (LODWORD(v19) - pIndoorCamera->pos.y) << 16;
         //v21 = v6->_z + 6.7553994e15;
         LODWORD(v22) = 0;
-        HIDWORD(v22) = SLOWORD(pOutdoorCamera->int_fov_rad);
-        auto _var_123 = fixpoint_mul(v6->x - pIndoorCamera->pos.x, v4) + fixpoint_mul(v6->y - pIndoorCamera->pos.y, v5);
+        HIDWORD(v22) = SLOWORD(pODMRenderParams->int_fov_rad);
+        auto _var_123 = fixpoint_sub_unknown(v6->x - pGame->pIndoorCameraD3D->vPartyPos.x, v4) + fixpoint_sub_unknown(v6->y - pGame->pIndoorCameraD3D->vPartyPos.y, v5);
         //v23 = v22 / _var_123;
         v6->_screenspace_scale = v22 / _var_123;
         //v24 = v6->_screenspace_scale;
         v6->uScreenSpaceX = pViewport->uScreenCenterX
                           - ((signed int)((unsigned __int64)(v6->_screenspace_scale
-                                                           * (signed __int64)(fixpoint_mul(v6->y - pIndoorCamera->pos.y, v4)
-                                                                                        - fixpoint_mul(v6->x - pIndoorCamera->pos.x, v5))) >> 16) >> 16);
-        v6->uScreenSpaceY = pViewport->uScreenCenterY - (fixpoint_mul(v6->z, v6->_screenspace_scale) >> 16);
+                                                           * (signed __int64)(fixpoint_sub_unknown(v6->y - pGame->pIndoorCameraD3D->vPartyPos.y, v4)
+                                                                                        - fixpoint_sub_unknown(v6->x - pGame->pIndoorCameraD3D->vPartyPos.x, v5))) >> 16) >> 16);
+        v6->uScreenSpaceY = pViewport->uScreenCenterY - (fixpoint_sub_unknown(v6->z, v6->_screenspace_scale) >> 16);
         v6->sZValue = _var_123;
       }
       //uIDb = (v41 - pIndoorCamera->pos.x) << 16;
       //v48 = (LODWORD(v39) - pIndoorCamera->pos.y) << 16;
-      v26 = fixpoint_mul(v6->y - pIndoorCamera->pos.y, v5);
+      v26 = fixpoint_sub_unknown(v6->y - pGame->pIndoorCameraD3D->vPartyPos.y, v5);
       //v27 = v26 + ((unsigned __int64)(uIDb * (signed __int64)v4) >> 16);
-      X_4 = v26 + fixpoint_mul(v6->x - pIndoorCamera->pos.x, v4);
-      if ( X_4 < 0x40000 || X_4 > (pOutdoorCamera->uPickDepth - 1000) << 16 )
+      X_4 = v26 + fixpoint_sub_unknown(v6->x - pGame->pIndoorCameraD3D->vPartyPos.x, v4);
+      if ( X_4 < 0x40000 || X_4 > (pODMRenderParams->uPickDepth - 1000) << 16 )
         return 0;
       v17 = v6->z;
-      v16 = fixpoint_mul(v6->y - pIndoorCamera->pos.y, v4) - fixpoint_mul(v6->x - pIndoorCamera->pos.x, v5);
+      v16 = fixpoint_sub_unknown(v6->y - pGame->pIndoorCameraD3D->vPartyPos.y, v4) - fixpoint_sub_unknown(v6->x - pGame->pIndoorCameraD3D->vPartyPos.x, v5);
     }
     v40 = v17;
     v28 = abs(v16);
     if ( abs(X_4) >= v28 )
     {
       LODWORD(v29) = 0;
-      HIDWORD(v29) = SLOWORD(pOutdoorCamera->int_fov_rad);
+      HIDWORD(v29) = SLOWORD(pODMRenderParams->int_fov_rad);
       //v30 = v29 / X_4;
       v6->_screenspace_scale = v29 / X_4;
       //v31 = v6->_screenspace_scale;
@@ -605,7 +604,7 @@
       v33 = (signed int)((unsigned __int64)(v6->_screenspace_scale * (signed __int64)v40) >> 16) >> 16;
       //v34 = pViewport->uScreenCenterY - v33;
       v6->uScreenSpaceY = pViewport->uScreenCenterY - v33;
-      v6->_screenspace_scale = fixpoint_sub0(fixpoint_from_float(v6->flt_28), v6->_screenspace_scale);
+      v6->_screenspace_scale = fixpoint_mul(fixpoint_from_float(v6->flt_28), v6->_screenspace_scale);
       v6->sZValue = X_4;
       v36 = v6->uScreenSpaceX;
       if ( v36 >= (signed int)pViewport->uViewportTL_X )
@@ -779,7 +778,7 @@
             {
               pLines.pLineVertices[2 * pLines.uNumLines].pos.x = particle->uScreenSpaceX;
               pLines.pLineVertices[2 * pLines.uNumLines].pos.y = particle->uScreenSpaceY;
-              pLines.pLineVertices[2 * pLines.uNumLines].pos.z = 1.0 - 1.0 / ((double)particle->zbuffer_depth * 1000.0 / (double)pOutdoorCamera->shading_dist_mist);
+              pLines.pLineVertices[2 * pLines.uNumLines].pos.z = 1.0 - 1.0 / ((double)particle->zbuffer_depth * 1000.0 / (double)pODMRenderParams->shading_dist_mist);
               pLines.pLineVertices[2 * pLines.uNumLines].rhw = 1.0;
               pLines.pLineVertices[2 * pLines.uNumLines].diffuse = particle->uLightColor_bgr;
               pLines.pLineVertices[2 * pLines.uNumLines].specular = 0;
@@ -788,7 +787,7 @@
 
               pLines.pLineVertices[2 * pLines.uNumLines + 1].pos.x = particle->uScreenSpaceZ;
               pLines.pLineVertices[2 * pLines.uNumLines + 1].pos.y = particle->uScreenSpaceW;
-              pLines.pLineVertices[2 * pLines.uNumLines + 1].pos.z = 1.0 - 1.0 / ((double)particle->zbuffer_depth * 1000.0 / (double)pOutdoorCamera->shading_dist_mist);
+              pLines.pLineVertices[2 * pLines.uNumLines + 1].pos.z = 1.0 - 1.0 / ((double)particle->zbuffer_depth * 1000.0 / (double)pODMRenderParams->shading_dist_mist);
               pLines.pLineVertices[2 * pLines.uNumLines + 1].rhw = 1.0;
               pLines.pLineVertices[2 * pLines.uNumLines + 1].diffuse = particle->uLightColor_bgr;
               pLines.pLineVertices[2 * pLines.uNumLines + 1].specular = 0;
--- a/Render.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/Render.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -12,8 +12,6 @@
 #include "DecalBuilder.h"
 #include "ParticleEngine.h"
 #include "Render.h"
-#include "OutdoorCamera.h"
-#include "IndoorCamera.h"
 #include "Outdoor.h"
 #include "Party.h"
 #include "LOD.h"
@@ -145,7 +143,7 @@
   soft_billboard.uViewportZ = pBLVRenderParams->uViewportZ - 1;
   soft_billboard.uViewportW = pBLVRenderParams->uViewportW;
 
-  pOutdoorCamera->uNumBillboards = ::uNumBillboardsToDraw;
+  pODMRenderParams->uNumBillboards = ::uNumBillboardsToDraw;
   for (uint i = 0; i < ::uNumBillboardsToDraw; ++i)
   {
     auto p = pBillboardRenderList + i;
@@ -251,7 +249,7 @@
   {
     for (unsigned int x = 0; x < 127; ++x)
     {
-      pTilePolygon = &array_77EC08[pOutdoorCamera->uNumPolygons];
+      pTilePolygon = &array_77EC08[pODMRenderParams->uNumPolygons];
       pTilePolygon->flags = 0;
       pTilePolygon->field_32 = 0;
       pTilePolygon->uTileBitmapID = pOutdoor->DoGetTileTexture(x, z);
@@ -305,9 +303,9 @@
       pTilePolygon->dimming_level = 20.0 - floorf(20.0 * _f + 0.5f);
 //-----------------------------------------------------------------------------------------------
 
-      ++pOutdoorCamera->uNumPolygons;
-      ++pOutdoorCamera->field_44;
-      assert(pOutdoorCamera->uNumPolygons < 20000);
+      ++pODMRenderParams->uNumPolygons;
+      ++pODMRenderParams->field_44;
+      assert(pODMRenderParams->uNumPolygons < 20000);
 
       pTilePolygon->uBModelID = 0;
       pTilePolygon->uBModelFaceID = 0;
@@ -346,8 +344,8 @@
         //pTile->DrawBorderTiles();
 //--------------------------------------------------------------------------------------------------------------------------------
 
-      --pOutdoorCamera->uNumPolygons;
-      --pOutdoorCamera->field_44;
+      --pODMRenderParams->uNumPolygons;
+      --pODMRenderParams->field_44;
     }
   }
 }
@@ -385,7 +383,7 @@
   billboard.uViewportY = pViewport->uViewportTL_Y;
   billboard.uViewportZ = pViewport->uViewportBR_X - 1;
   billboard.uViewportW = pViewport->uViewportBR_Y;
-  pOutdoorCamera->uNumBillboards = uNumBillboardsToDraw;
+  pODMRenderParams->uNumBillboards = uNumBillboardsToDraw;
 
   for (int i = 0; i < ::uNumBillboardsToDraw; ++i)
   {
@@ -518,7 +516,7 @@
       //v28 = v4;
       v36 = v4->uFlags;
       a6 = v4->uGlowRadius * object->field_22_glow_radius_multiplier;
-      v6 = stru_5C6E00->Atan2(object->vPosition.x - pIndoorCamera->pos.x, object->vPosition.y - pIndoorCamera->pos.y);
+      v6 = stru_5C6E00->Atan2(object->vPosition.x - pGame->pIndoorCameraD3D->vPartyPos.x, object->vPosition.y - pGame->pIndoorCameraD3D->vPartyPos.y);
       //LOWORD(v7) = object->uFacing;
       //v8 = v36;
             v9 = ((signed int)(stru_5C6E00->uIntegerPi + ((signed int)stru_5C6E00->uIntegerPi >> 3) + object->uFacing - v6) >> 8) & 7;
@@ -544,52 +542,52 @@
               //LOBYTE(v11) = byte_4E94D3;
               pMobileLightsStack->AddLight(x, y, z, object->uSectorID, a6, 0xFFu, 0xFFu, 0xFFu, byte_4E94D3);
             }
-            v12 = (x - pIndoorCamera->pos.x) << 16;
-            if ( pIndoorCamera->sRotationX )
+            v12 = (x - pGame->pIndoorCameraD3D->vPartyPos.x) << 16;
+            if (pGame->pIndoorCameraD3D->sRotationX)
             {
-              v13 = (y - pIndoorCamera->pos.y) << 16;
-              v30 = ((unsigned __int64)(v12 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16)
-                  + ((unsigned __int64)(v13 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16);
-              v37 = (unsigned __int64)(v12 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16;
-              a6a = (unsigned __int64)(v13 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16;
-              v33 = (z - pIndoorCamera->pos.z) << 16;
-              v14 = (unsigned __int64)(v30 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_cosine) >> 16;
-              v15 = (unsigned __int64)(v33 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_sine) >> 16;
+              v13 = (y - pGame->pIndoorCameraD3D->vPartyPos.y) << 16;
+              v30 = ((unsigned __int64)(v12 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16)
+                  + ((unsigned __int64)(v13 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16);
+              v37 = (unsigned __int64)(v12 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
+              a6a = (unsigned __int64)(v13 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16;
+              v33 = (z - pGame->pIndoorCameraD3D->vPartyPos.z) << 16;
+              v14 = (unsigned __int64)(v30 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16;
+              v15 = (unsigned __int64)(v33 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16;
               v16 = v15 + v14;
               v42 = v15 + v14;
-              if ( v15 + v14 >= 262144 && v16 <= pOutdoorCamera->shading_dist_mist << 16 )
+              if ( v15 + v14 >= 262144 && v16 <= pODMRenderParams->shading_dist_mist << 16 )
               {
                 v17 = a6a - v37;
                 v40 = a6a - v37;
-                v18 = ((unsigned __int64)(v33 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_cosine) >> 16)
-                    - ((unsigned __int64)(v30 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_sine) >> 16);
+                v18 = ((unsigned __int64)(v33 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16)
+                    - ((unsigned __int64)(v30 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16);
                 goto LABEL_29;
               }
             }
             else
             {
-              v34 = (y - pIndoorCamera->pos.y) << 16;
-              v19 = (unsigned __int64)(v12 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16;
-              v20 = (unsigned __int64)(v34 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16;
+              v34 = (y - pGame->pIndoorCameraD3D->vPartyPos.y) << 16;
+              v19 = (unsigned __int64)(v12 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16;
+              v20 = (unsigned __int64)(v34 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
               v16 = v20 + v19;
               v42 = v20 + v19;
-              if ( v20 + v19 >= 262144 && v16 <= pOutdoorCamera->shading_dist_mist << 16 )
+              if ( v20 + v19 >= 262144 && v16 <= pODMRenderParams->shading_dist_mist << 16 )
               {
-                v21 = (unsigned __int64)(((x - pIndoorCamera->pos.x) << 16) * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16;
-                v17 = ((unsigned __int64)(v34 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16) - v21;
-                v40 = ((unsigned __int64)(v34 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16) - v21;
-                v18 = (z - pIndoorCamera->pos.z) << 16;
+                v21 = (unsigned __int64)(((x - pGame->pIndoorCameraD3D->vPartyPos.x) << 16) * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
+                v17 = ((unsigned __int64)(v34 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16) - v21;
+                v40 = ((unsigned __int64)(v34 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16) - v21;
+                v18 = (z - pGame->pIndoorCameraD3D->vPartyPos.z) << 16;
 LABEL_29:
                 v31 = v18;
                 v22 = abs(v17);
                 if ( abs(v16) >= v22 )
                 {
                   LODWORD(v23) = 0;
-                  HIDWORD(v23) = SLOWORD(pOutdoorCamera->int_fov_rad);
+                  HIDWORD(v23) = SLOWORD(pODMRenderParams->int_fov_rad);
                   v24 = v23 / v42;
                   v25 = v23 / v42;
                   LODWORD(v23) = 0;
-                  HIDWORD(v23) = SLOWORD(pOutdoorCamera->int_fov_rad);
+                  HIDWORD(v23) = SLOWORD(pODMRenderParams->int_fov_rad);
                   v35 = pViewport->uScreenCenterX - ((signed int)(((unsigned __int64)(v25 * (signed __int64)v40) >> 16) + 32768) >> 16);
                   v32 = LOWORD(pViewport->uScreenCenterY) - (((unsigned int)((unsigned __int64)(v23 / v42 * v31) >> 16) + 32768) >> 16);
 
@@ -637,8 +635,6 @@
     //while ( v41 < (signed int)uNumSpriteObjects );
   }
 }
-// 4E94D3: using guessed type char byte_4E94D3;
-// 5187E4: using guessed type int uNumSpritesDrawnThisFrame;
 
 //----- (0049D9BC) --------------------------------------------------------
 signed int __stdcall RenderD3D__DeviceEnumerator(GUID *lpGUID, const char *lpDevDesc, const char *lpDriverName, RenderD3D__DevInfo *pOut)
@@ -811,7 +807,7 @@
     v10 = strlen(lpDeviceDesc);
     a6->pInfo[v8].pDescription = new char[v10 + 1];
     strcpy(a6->pInfo[v8].pDescription, lpDeviceDesc);
-    a6->pInfo[v8].pGUID = (GUID *)operator new(0x10u);
+    a6->pInfo[v8].pGUID = new GUID;
     memcpy(a6->pInfo[v8].pGUID, lpGUID, 0x10u);
     v11 = strlen(a6->ptr_4->pDriverName);
     a6->pInfo[v8].pDriverName = new char[v11 + 1];
@@ -1000,8 +996,8 @@
           //v9 = v8;
           v42 = v8->uFlags;
           a5 = v8->uGlowRadius;
-          v10 = (unsigned __int16 *)stru_5C6E00->Atan2(decor->vPosition.x - pIndoorCamera->pos.x,
-                                                       decor->vPosition.y - pIndoorCamera->pos.y);
+          v10 = (unsigned __int16 *)stru_5C6E00->Atan2(decor->vPosition.x - pGame->pIndoorCameraD3D->vPartyPos.x,
+                                                       decor->vPosition.y - pGame->pIndoorCameraD3D->vPartyPos.y);
           v11 = *((int *)v0 + 2);
           v37 = v10;
           v12 = v42;
@@ -1044,27 +1040,27 @@
               v16,
               byte_4E94D0);
           }
-          v17 = (decor->vPosition.x - pIndoorCamera->pos.x) << 16;
-          if ( pIndoorCamera->sRotationX )
+          v17 = (decor->vPosition.x - pGame->pIndoorCameraD3D->vPartyPos.x) << 16;
+          if (pGame->pIndoorCameraD3D->sRotationX)
           {
-            v40 = (decor->vPosition.y - pIndoorCamera->pos.y) << 16;
-            v18 = ((unsigned __int64)(v17 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16)
-                + ((unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16);
+            v40 = (decor->vPosition.y - pGame->pIndoorCameraD3D->vPartyPos.y) << 16;
+            v18 = ((unsigned __int64)(v17 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16)
+                + ((unsigned __int64)(v40 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16);
             v42 = v18;
-            b = (unsigned __int64)(v17 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16;
-            a5 = (unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16;
-            v40 = (decor->vPosition.z - pIndoorCamera->pos.z) << 16;
-            v41 = (unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_sine) >> 16;
-            v19 = (unsigned __int64)(v18 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_cosine) >> 16;
-            v20 = v19 + ((unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_sine) >> 16);
-            v39 = v19 + ((unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_sine) >> 16);
-            if ( v20 >= 262144 && v20 <= pOutdoorCamera->shading_dist_mist << 16 )
+            b = (unsigned __int64)(v17 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
+            a5 = (unsigned __int64)(v40 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16;
+            v40 = (decor->vPosition.z - pGame->pIndoorCameraD3D->vPartyPos.z) << 16;
+            v41 = (unsigned __int64)(v40 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16;
+            v19 = (unsigned __int64)(v18 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16;
+            v20 = v19 + ((unsigned __int64)(v40 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16);
+            v39 = v19 + ((unsigned __int64)(v40 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16);
+            if ( v20 >= 262144 && v20 <= pODMRenderParams->shading_dist_mist << 16 )
             {
               v21 = a5 - b;
               v41 = a5 - b;
-              a5 = (unsigned __int64)(v42 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_sine) >> 16;
-              b = (unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_cosine) >> 16;
-              v22 = ((unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_x_int_cosine) >> 16) - a5;
+              a5 = (unsigned __int64)(v42 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16;
+              b = (unsigned __int64)(v40 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16;
+              v22 = ((unsigned __int64)(v40 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16) - a5;
 LABEL_30:
               v42 = v22;
               v40 = 2 * abs(v20);
@@ -1072,7 +1068,7 @@
               if ( v40 >= v23 )
               {
                 LODWORD(v24) = 0;
-                HIDWORD(v24) = SLOWORD(pOutdoorCamera->int_fov_rad);
+                HIDWORD(v24) = SLOWORD(pODMRenderParams->int_fov_rad);
                 a5 = v24 / v39;
                 v25 = pViewport->uScreenCenterX
                     - ((signed int)(((unsigned __int64)(v24 / v39 * v41) >> 16) + 32768) >> 16);
@@ -1129,19 +1125,19 @@
           }
           else
           {
-            v42 = (decor->vPosition.x - pIndoorCamera->pos.x) << 16;
-            v40 = (decor->vPosition.y - pIndoorCamera->pos.y) << 16;
-            b = (unsigned __int64)(v17 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16;
-            a5 = (unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16;
-            v20 = b + ((unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16);
-            v39 = b + ((unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16);
-            if ( v20 >= 262144 && v20 <= pOutdoorCamera->shading_dist_mist << 16 )
+            v42 = (decor->vPosition.x - pGame->pIndoorCameraD3D->vPartyPos.x) << 16;
+            v40 = (decor->vPosition.y - pGame->pIndoorCameraD3D->vPartyPos.y) << 16;
+            b = (unsigned __int64)(v17 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16;
+            a5 = (unsigned __int64)(v40 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
+            v20 = b + ((unsigned __int64)(v40 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16);
+            v39 = b + ((unsigned __int64)(v40 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16);
+            if ( v20 >= 262144 && v20 <= pODMRenderParams->shading_dist_mist << 16 )
             {
-              a5 = (unsigned __int64)(v42 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_sine) >> 16;
-              b = (unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16;
-              v21 = ((unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16) - a5;
-              v41 = ((unsigned __int64)(v40 * (signed __int64)pOutdoorCamera->camera_rotation_y_int_cosine) >> 16) - a5;
-              v22 = (decor->vPosition.z - pIndoorCamera->pos.z) << 16;
+              a5 = (unsigned __int64)(v42 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
+              b = (unsigned __int64)(v40 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16;
+              v21 = ((unsigned __int64)(v40 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16) - a5;
+              v41 = ((unsigned __int64)(v40 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16) - a5;
+              v22 = (decor->vPosition.z - pGame->pIndoorCameraD3D->vPartyPos.z) << 16;
               goto LABEL_30;
             }
           }
@@ -1172,8 +1168,6 @@
   }
     //while ( v35 < (signed int)uNumLevelDecorations );
 }
-// 4E94D0: using guessed type char byte_4E94D0;
-// 5187EC: using guessed type int uNumDecorationsDrawnThisFrame;
 
 //----- (0049D717) --------------------------------------------------------
 HRESULT __stdcall D3DZBufferFormatEnumerator(DDPIXELFORMAT *Src, DDPIXELFORMAT *Dst)
@@ -1886,7 +1880,7 @@
 		
 		  d3d_vertex_buffer[i].pos.x = array_50AC10[i].vWorldViewProjX;
 		  d3d_vertex_buffer[i].pos.y = array_50AC10[i].vWorldViewProjY;
-		  d3d_vertex_buffer[i].pos.z = 1.0 - 1.0 / ((array_50AC10[i].vWorldViewPosition.x * 1000) / (double)pOutdoorCamera->shading_dist_mist);
+		  d3d_vertex_buffer[i].pos.z = 1.0 - 1.0 / ((array_50AC10[i].vWorldViewPosition.x * 1000) / (double)pODMRenderParams->shading_dist_mist);
 		  d3d_vertex_buffer[i].rhw = 1.0 / (array_50AC10[i].vWorldViewPosition.x + 0.0000001);
 		  d3d_vertex_buffer[i].diffuse = ::GetActorTintColor(a3->dimming_level, 0, array_50AC10[i].vWorldViewPosition.x, 0, 0);
           pGame->AlterGamma_ODM(a4, &d3d_vertex_buffer[i].diffuse);
@@ -1929,7 +1923,7 @@
 		
 		  d3d_vertex_buffer[i].pos.x = array_50AC10[i].vWorldViewProjX;
 		  d3d_vertex_buffer[i].pos.y = array_50AC10[i].vWorldViewProjY;
-		  d3d_vertex_buffer[i].pos.z = 1.0 - 1.0 / ((array_50AC10[i].vWorldViewPosition.x * 1000) / (double)pOutdoorCamera->shading_dist_mist);
+		  d3d_vertex_buffer[i].pos.z = 1.0 - 1.0 / ((array_50AC10[i].vWorldViewPosition.x * 1000) / (double)pODMRenderParams->shading_dist_mist);
 		  d3d_vertex_buffer[i].rhw = 1.0 / (array_50AC10[i].vWorldViewPosition.x + 0.0000001);
 		  d3d_vertex_buffer[i].diffuse = GetActorTintColor(a3->dimming_level, 0, array_50AC10[i].vWorldViewPosition.x, 0, 0);
           if ( this->bUsingSpecular )
@@ -3310,7 +3304,7 @@
     {
       pTargetSurface = 0;
       ptr_400E8 = 0;
-      v20 = (int *)operator new(0x96020u);
+      v20 = (int *)malloc(0x96020u);
       ptr_400E8 = v20;
       if ( !v20
         || (memset(&pDesc, 0, 0x7Cu),
@@ -3384,7 +3378,7 @@
   CreateZBuffer();
   if ( bUserDirect3D )
   {
-    /*v3 = operator new(0x148u);
+    /*v3 = malloc(0x148u);
     thisa = (RenderD3D *)v3;
     v29 = 0;
     if ( v3 )
@@ -4651,7 +4645,7 @@
 
      pVertices[0].pos.x = array_50AC10[0].vWorldViewProjX;
      pVertices[0].pos.y = array_50AC10[0].vWorldViewProjY;
-     pVertices[0].pos.z = 1.0 - 1.0 / (1000 * array_50AC10[0].vWorldViewPosition.x / (double)pOutdoorCamera->shading_dist_mist);
+     pVertices[0].pos.z = 1.0 - 1.0 / (1000 * array_50AC10[0].vWorldViewPosition.x / (double)pODMRenderParams->shading_dist_mist);
      pVertices[0].rhw = 1.0 / (array_50AC10[0].vWorldViewPosition.x + 0.0000001000000011686097);
      pVertices[0].diffuse = GetActorTintColor(a3->field_58, 0, array_50AC10[0].vWorldViewPosition.x, 0, 0);
      pVertices[0].specular = 0;
@@ -4660,7 +4654,7 @@
  
      pVertices[1].pos.x = array_50AC10[3].vWorldViewProjX;
      pVertices[1].pos.y = array_50AC10[3].vWorldViewProjY;
-     pVertices[1].pos.z = 1.0 - 1.0 / (1000 * array_50AC10[3].vWorldViewPosition.x / (double)pOutdoorCamera->shading_dist_mist);
+     pVertices[1].pos.z = 1.0 - 1.0 / (1000 * array_50AC10[3].vWorldViewPosition.x / (double)pODMRenderParams->shading_dist_mist);
      pVertices[1].rhw = 1.0 / (array_50AC10[3].vWorldViewPosition.x + 0.0000001000000011686097);
      pVertices[1].diffuse = GetActorTintColor(a3->field_58, 0, array_50AC10[3].vWorldViewPosition.x, 0, 0);
      pVertices[1].specular = 0;
@@ -4669,7 +4663,7 @@
 
      pVertices[2].pos.x = array_50AC10[1].vWorldViewProjX;
      pVertices[2].pos.y = array_50AC10[1].vWorldViewProjY;
-     pVertices[2].pos.z = 1.0 - 1.0 / (1000 * array_50AC10[1].vWorldViewPosition.x / (double)pOutdoorCamera->shading_dist_mist);
+     pVertices[2].pos.z = 1.0 - 1.0 / (1000 * array_50AC10[1].vWorldViewPosition.x / (double)pODMRenderParams->shading_dist_mist);
      pVertices[2].rhw = 1.0 / (array_50AC10[1].vWorldViewPosition.x + 0.0000001000000011686097);
      pVertices[2].diffuse = GetActorTintColor(a3->field_58, 0, array_50AC10[1].vWorldViewPosition.x, 0, 0);
      pVertices[2].specular = 0;
@@ -4681,7 +4675,7 @@
 
      pVertices[5].pos.x = array_50AC10[2].vWorldViewProjX;
      pVertices[5].pos.y = array_50AC10[2].vWorldViewProjY;
-     pVertices[5].pos.z = 1.0 - 1.0 / (1000 * array_50AC10[2].vWorldViewPosition.x / (double)pOutdoorCamera->shading_dist_mist);
+     pVertices[5].pos.z = 1.0 - 1.0 / (1000 * array_50AC10[2].vWorldViewPosition.x / (double)pODMRenderParams->shading_dist_mist);
      pVertices[5].rhw = 1.0 / (array_50AC10[2].vWorldViewPosition.x + 0.0000001000000011686097);
      pVertices[5].diffuse = GetActorTintColor(a3->field_58, 0, array_50AC10[2].vWorldViewPosition.x, 0, 0);
      pVertices[5].specular = 0;
@@ -4810,7 +4804,7 @@
 		
 		  d3d_vertex_buffer[i].pos.x = array_50AC10[i].vWorldViewProjX;
 		  d3d_vertex_buffer[i].pos.y = array_50AC10[i].vWorldViewProjY;
-		  d3d_vertex_buffer[i].pos.z = 1.0 - 1.0 / ((array_50AC10[i].vWorldViewPosition.x * 1000) / (double)pOutdoorCamera->shading_dist_mist);
+		  d3d_vertex_buffer[i].pos.z = 1.0 - 1.0 / ((array_50AC10[i].vWorldViewPosition.x * 1000) / (double)pODMRenderParams->shading_dist_mist);
 		  d3d_vertex_buffer[i].rhw = 1.0 / (array_50AC10[i].vWorldViewPosition.x + 0.0000001);
 		  d3d_vertex_buffer[i].diffuse = ::GetActorTintColor(a4->dimming_level, 0, array_50AC10[i].vWorldViewPosition.x, 0, 0);
           if ( this->bUsingSpecular )
@@ -4841,7 +4835,7 @@
 		
 		  d3d_vertex_buffer[i].pos.x = array_50AC10[i].vWorldViewProjX;
 		  d3d_vertex_buffer[i].pos.y = array_50AC10[i].vWorldViewProjY;
-		  d3d_vertex_buffer[i].pos.z = 1.0 - 1.0 / ((array_50AC10[i].vWorldViewPosition.x * 1000) / (double)pOutdoorCamera->shading_dist_mist);
+		  d3d_vertex_buffer[i].pos.z = 1.0 - 1.0 / ((array_50AC10[i].vWorldViewPosition.x * 1000) / (double)pODMRenderParams->shading_dist_mist);
 		  d3d_vertex_buffer[i].rhw = 1.0 / (array_50AC10[i].vWorldViewPosition.x + 0.0000001);
 		  d3d_vertex_buffer[i].diffuse = GetActorTintColor(a4->dimming_level, 0, array_50AC10[i].vWorldViewPosition.x, 0, 0);
           if ( this->bUsingSpecular )
@@ -4921,7 +4915,8 @@
       }
     }
 
-    if (pIndoorCamera->flags & INDOOR_CAMERA_DRAW_TERRAIN_OUTLINES || pBLVRenderParams->uFlags & INDOOR_CAMERA_DRAW_TERRAIN_OUTLINES)
+    //if (pIndoorCamera->flags & INDOOR_CAMERA_DRAW_TERRAIN_OUTLINES || pBLVRenderParams->uFlags & INDOOR_CAMERA_DRAW_TERRAIN_OUTLINES)
+    if (pGame->pIndoorCameraD3D->debug_flags & ODM_RENDER_DRAW_TERRAIN_OUTLINES)
       pGame->pIndoorCameraD3D->debug_outline_d3d(d3d_vertex_buffer, uNumVertices, 0x00FFFFFF, 0.0);
   }
 // 4A26BC: could not find valid save-restore pair for esi
@@ -5013,20 +5008,20 @@
 void Render::DrawIndoorPolygonNoLight(unsigned int uNumVertices, unsigned int uFaceID)
 {
   BLVFace *pFace; // esi@1
-  unsigned int v3; // edi@1
-  PolygonType v4; // al@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
+  //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
+  //char *v14; // esi@8
   void *v15; // ecx@9
-  int v16; // eax@9
+  //int v16; // eax@9
   int v17; // edi@9
   double v18; // st7@9
   signed int v19; // ebx@9
@@ -5064,21 +5059,21 @@
   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
+  //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
   struct Polygon *v60; // [sp+0h] [bp-174h]@17
   IDirect3DTexture2 *v61; // [sp+4h] [bp-170h]@17
   struct Polygon v62; // [sp+14h] [bp-160h]@6
   unsigned int v63; // [sp+120h] [bp-54h]@7
-  double v64; // [sp+124h] [bp-50h]@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 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
@@ -5093,87 +5088,62 @@
   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);
+  if (pFace->uPolygonType == POLYGON_InBetweenFloorAndWall || pFace->uPolygonType == POLYGON_Floor)
+  {
+    int v69 = (GetTickCount() / 32) - pGame->pIndoorCameraD3D->vPartyPos.x;
+    int v55 = (GetTickCount() / 32) + pGame->pIndoorCameraD3D->vPartyPos.y;
+    for (uint i = 0; i < uNumVertices; ++i)
+    {
+      array_507D30[i].u = (v69 + array_507D30[i].u) * 0.25f;
+      array_507D30[i].v = (v55 + array_507D30[i].v) * 0.25f;
+    }
+    pRenderer->DrawIndoorPolygon(uNumVertices, pFace, pBitmaps_LOD->pHardwareTextures[pFace->uBitmapID], pFace->GetTexture(), PID(OBJECT_BModel, uFaceID), -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)
+  v70 = (signed __int64)((double)(pBLVRenderParams->fov_rad_fixpoint * pGame->pIndoorCameraD3D->vPartyPos.z)
+                       / (((double)pBLVRenderParams->fov_rad_fixpoint + 16192.0)
                         * 65536.0)
                        + *(float *)&v74);
-  v5 = (double)pIndoorCamera->sRotationX * 0.0030664064;
+  v5 = (double)pGame->pIndoorCameraD3D->sRotationX * 0.0030664064;
   *(float *)&v75 = v5;
-  v80 = cos(v5) * 16192.0;
   v6 = (signed __int64)(*(float *)&v74
-                      - (double)pBLVRenderParams->field_40
-                      / ((v80 + 0.0000001)
+                      - (double)pBLVRenderParams->fov_rad_fixpoint
+                      / ((cos(v5) * 16192.0 + 0.0000001)
                        * 65535.0)
-                      * (sin(*(float *)&v75) * -16192.0 - (double)SHIDWORD(v68)));
-  v7 = pFace->uPolygonType;
-  if ( v7 == 4 || v7 == 3 )
-    v70 = v6;
+                      * (sin(*(float *)&v75) * -16192.0 - (double)pGame->pIndoorCameraD3D->vPartyPos.z));
+
+
   stru_8019C8._48653D_frustum_blv(65536, 0, 0, 0, 65536, 0);
   v62.Create_48607B(&stru_8019C8);
   v62.uTileBitmapID = pFace->uBitmapID;
-  v62.pTexture = (Texture *)((signed __int16)v62.uTileBitmapID != -1 ? &pBitmaps_LOD->pTextures[(signed __int16)v62.uTileBitmapID] : 0);
+
+  v62.pTexture = pBitmaps_LOD->GetTexture(v62.uTileBitmapID);
   if ( !v62.pTexture )
     return;
-  v8 = pBLVRenderParams->sPartyRotX;
+
   v62.dimming_level = 0;
-  v62.uNumVertices = v3;
-  v9 = stru_5C6E00->Sin(pBLVRenderParams->sPartyRotX + 16);
+  v62.uNumVertices = uNumVertices;
   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;
+  v62.v_18.x = -stru_5C6E00->Sin(pGame->pIndoorCameraD3D->sRotationX + 16);
+  v62.v_18.z = -stru_5C6E00->Cos(pGame->pIndoorCameraD3D->sRotationX + 16);
+  memcpy(&array_507D30[uNumVertices], array_507D30, sizeof(array_507D30[uNumVertices]));
+  v62.field_24 = 0x2000000;
+
+  extern float _calc_fov(int viewport_width, int angle_degree);
+  //v64 = (double)(signed int)(pBLVRenderParams->uViewportZ - pBLVRenderParams->uViewportX) * 0.5;
+  //v72 = 65536 / (signed int)(signed __int64)(v64 / tan(0.6457717418670654) + 0.5);
+  v72 = 65536.0f / _calc_fov(pBLVRenderParams->uViewportZ - pBLVRenderParams->uViewportX, 74);
   v12 = v62.pTexture->uWidthMinus1;
   v13 = v62.pTexture->uHeightMinus1;
-  v67 = v11;
+  v67 = 1.0 / (double)v62.pTexture->uTextureWidth;
   v63 = 224 * pMiscTimer->uTotalGameTimeElapsed & v13;
   v66 = 224 * pMiscTimer->uTotalGameTimeElapsed & v12;
   v78 = 0;
   v81 = 0;
-  *((float *)&v68 + 1) = 1.0 / (double)SLODWORD(v80);
+  float v68 = 1.0 / (double)v62.pTexture->uTextureHeight;
   if ( (signed int)v62.uNumVertices <= 0 )
   {
 LABEL_17:
@@ -5183,23 +5153,21 @@
     v59 = v62.uNumVertices;
     goto LABEL_18;
   }
-  v14 = (char *)&array_507D30[0].vWorldViewProjY;
+
+  //v14 = (char *)&array_507D30[0].vWorldViewProjY;
+  int _507D30_idx = 0;
   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;
+    v15 = (void *)(v72 * (v70 - (int)array_507D30[_507D30_idx].vWorldViewProjY));
+    v77 = (unsigned __int64)(v62.ptr_38->field_14 * (signed __int64)(signed int)v15) >> 16;
+    v74 = 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;
+    v77 = (unsigned __int64)(v62.ptr_38->field_20 * (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;
+    v17 = v72 * (pBLVRenderParams->uViewportCenterX - (int)array_507D30[_507D30_idx].vWorldViewProjX);
+    v18 = array_507D30[_507D30_idx].vWorldViewProjY - 1.0;
     v19 = -v62.field_24;
     v77 = -v62.field_24;
     X = (int)((char *)v79 + v62.v_18.x);
@@ -5218,7 +5186,6 @@
       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);
@@ -5232,23 +5199,22 @@
       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));
+      LODWORD(v76) = v74 + ((unsigned __int64)(v62.ptr_38->field_10 * (signed __int64)v17) >> 16);
+      v75 = (RenderVertexSoft *)((char *)v75 + ((unsigned __int64)(v62.ptr_38->field_1C * (signed __int64)v17) >> 16));
       v77 = (unsigned __int64)(SLODWORD(v76) * v23 / X) >> 16;
       LODWORD(v73) = (unsigned __int64)((signed int)v75 * v23 / X) >> 16;
-      v14 += 48;
+      //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;
+      array_507D30[_507D30_idx].u = v24 * v67;
+      array_507D30[_507D30_idx].v = (double)SLODWORD(v80) * 0.000015259022 * v68;
+      array_507D30[_507D30_idx]._rhw = 65536.0 / (double)(signed int)v79;
+      _507D30_idx++;
       if ( !(v25 ^ v26) )
         goto LABEL_17;
       continue;
@@ -5374,7 +5340,7 @@
     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);
+    *((float *)v34 - 9) = (double)v78 * 0.000015259022 * v68;
     v46 = (double)(signed int)v79;
     *((float *)v34 - 16) = 0.000015258789 * v46;
     *((float *)v34 - 11) = 65536.0 / v46;
@@ -6022,7 +5988,7 @@
     pBillboardRenderListD3D[v8].pQuads[0].specular = 0;
     pBillboardRenderListD3D[v8].pQuads[0].diffuse = uDiffuse;
     pBillboardRenderListD3D[v8].pQuads[0].pos.y = v23;
-    v24 = 1.0 - 1.0 / (v6 * 1000.0 / (double)pOutdoorCamera->shading_dist_mist);
+    v24 = 1.0 - 1.0 / (v6 * 1000.0 / (double)pODMRenderParams->shading_dist_mist);
     pBillboardRenderListD3D[v8].pQuads[0].pos.z = v24;
     v25 = 1.0 / v6;
     pBillboardRenderListD3D[v8].pQuads[0].rhw = v25;
@@ -6156,7 +6122,7 @@
   pBillboardRenderListD3D[v8].pQuads[0].diffuse = diffuse;
   pBillboardRenderListD3D[v8].pQuads[0].pos.x = (double)a2->uScreenSpaceX - v14 * v30;
   pBillboardRenderListD3D[v8].pQuads[0].pos.y = (double)a2->uScreenSpaceY - v15 * v29;
-  pBillboardRenderListD3D[v8].pQuads[0].pos.z = 1.0 - 1.0 / (a2->zbuffer_depth * 1000.0 / (double)pOutdoorCamera->shading_dist_mist);
+  pBillboardRenderListD3D[v8].pQuads[0].pos.z = 1.0 - 1.0 / (a2->zbuffer_depth * 1000.0 / (double)pODMRenderParams->shading_dist_mist);
   pBillboardRenderListD3D[v8].pQuads[0].rhw = 1.0 / a2->zbuffer_depth;
   pBillboardRenderListD3D[v8].pQuads[0].specular = specular;
   pBillboardRenderListD3D[v8].pQuads[0].texcoord.x = 0.0;
@@ -6170,7 +6136,7 @@
     pBillboardRenderListD3D[v8].pQuads[1].diffuse = diffuse;
     pBillboardRenderListD3D[v8].pQuads[1].pos.x = (double)a2->uScreenSpaceX - v14 * v30;
     pBillboardRenderListD3D[v8].pQuads[1].pos.y = (double)a2->uScreenSpaceY - v15 * v29;
-    pBillboardRenderListD3D[v8].pQuads[1].pos.z = 1.0 - 1.0 / (a2->zbuffer_depth * 1000.0 / (double)pOutdoorCamera->shading_dist_mist);
+    pBillboardRenderListD3D[v8].pQuads[1].pos.z = 1.0 - 1.0 / (a2->zbuffer_depth * 1000.0 / (double)pODMRenderParams->shading_dist_mist);
     pBillboardRenderListD3D[v8].pQuads[1].rhw = 1.0 / a2->zbuffer_depth;
     pBillboardRenderListD3D[v8].pQuads[1].texcoord.x = 0.0;
     pBillboardRenderListD3D[v8].pQuads[1].texcoord.y = 1.0;
@@ -6183,7 +6149,7 @@
     pBillboardRenderListD3D[v8].pQuads[2].specular = specular;
     pBillboardRenderListD3D[v8].pQuads[2].pos.x = (double)a2->uScreenSpaceX + v14 * v30;
     pBillboardRenderListD3D[v8].pQuads[2].pos.y = (double)a2->uScreenSpaceY - v15 * v29;
-    pBillboardRenderListD3D[v8].pQuads[2].pos.z = 1.0 - 1.0 / (a2->zbuffer_depth * 1000.0 / (double)pOutdoorCamera->shading_dist_mist);
+    pBillboardRenderListD3D[v8].pQuads[2].pos.z = 1.0 - 1.0 / (a2->zbuffer_depth * 1000.0 / (double)pODMRenderParams->shading_dist_mist);
     pBillboardRenderListD3D[v8].pQuads[2].rhw = 1.0 / a2->zbuffer_depth;
     pBillboardRenderListD3D[v8].pQuads[2].texcoord.x = 1.0;
     pBillboardRenderListD3D[v8].pQuads[2].texcoord.y = 1.0;
@@ -6196,7 +6162,7 @@
     pBillboardRenderListD3D[v8].pQuads[3].specular = specular;
     pBillboardRenderListD3D[v8].pQuads[3].pos.x = (double)a2->uScreenSpaceX + v14 * v30;
     pBillboardRenderListD3D[v8].pQuads[3].pos.y = (double)a2->uScreenSpaceY - v15 * v29;
-    pBillboardRenderListD3D[v8].pQuads[3].pos.z = 1.0 - 1.0 / (a2->zbuffer_depth * 1000.0 / (double)pOutdoorCamera->shading_dist_mist);
+    pBillboardRenderListD3D[v8].pQuads[3].pos.z = 1.0 - 1.0 / (a2->zbuffer_depth * 1000.0 / (double)pODMRenderParams->shading_dist_mist);
     pBillboardRenderListD3D[v8].pQuads[3].rhw = 1.0 / a2->zbuffer_depth;
     pBillboardRenderListD3D[v8].pQuads[3].texcoord.x = 1.0;
     pBillboardRenderListD3D[v8].pQuads[3].texcoord.y = 0.0;
@@ -6305,8 +6271,8 @@
   v18 = (double)xDifference * v16 * a4;
   if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
   {
-    v20 = a3 * 1000.0 / (double)pOutdoorCamera->shading_dist_mist;
-    v25 = a7 * 1000.0 / (double)pOutdoorCamera->shading_dist_mist;
+    v20 = a3 * 1000.0 / (double)pODMRenderParams->shading_dist_mist;
+    v25 = a7 * 1000.0 / (double)pODMRenderParams->shading_dist_mist;
   }
   else
   {
@@ -6410,7 +6376,7 @@
     if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
       v11 = v10 * 0.061758894;
     else
-      v11 = v10 * 1000.0 / (double)pOutdoorCamera->shading_dist_mist;
+      v11 = v10 * 1000.0 / (double)pODMRenderParams->shading_dist_mist;
     pBillboardRenderListD3D[v5].pQuads[i].pos.z = 1.0 - 1.0 / v11;
     pBillboardRenderListD3D[v5].pQuads[i].rhw = 1.0 / a1->field_104[i].z;
 
--- a/SpriteObject.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/SpriteObject.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -82,11 +82,11 @@
     pSpriteObjects[v6].vVelocity.z = 0;
     if ( a4 )
     {
-      v13 = fixpoint_sub0(stru_5C6E00->Cos(angle), stru_5C6E00->Cos(pitch));
-      a5a = fixpoint_sub0(stru_5C6E00->Sin(angle), stru_5C6E00->Cos(pitch));
-      pSpriteObjects[v6].vVelocity.x = fixpoint_sub0(v13, a4);
-      pSpriteObjects[v6].vVelocity.y = fixpoint_sub0(a5a, a4);
-      pSpriteObjects[v6].vVelocity.z = fixpoint_sub0(stru_5C6E00->Sin(pitch), a4);
+      v13 = fixpoint_mul(stru_5C6E00->Cos(angle), stru_5C6E00->Cos(pitch));
+      a5a = fixpoint_mul(stru_5C6E00->Sin(angle), stru_5C6E00->Cos(pitch));
+      pSpriteObjects[v6].vVelocity.x = fixpoint_mul(v13, a4);
+      pSpriteObjects[v6].vVelocity.y = fixpoint_mul(a5a, a4);
+      pSpriteObjects[v6].vVelocity.z = fixpoint_mul(stru_5C6E00->Sin(pitch), a4);
     }
     else
     {
@@ -107,11 +107,11 @@
     pSpriteObjects[v6].vVelocity.z = 0;
     if ( a4 )
     {
-      v13 = fixpoint_sub0(stru_5C6E00->Cos(angle), stru_5C6E00->Cos(pitch));
-      a5a = fixpoint_sub0(stru_5C6E00->Sin(angle), stru_5C6E00->Cos(pitch));
-      pSpriteObjects[v6].vVelocity.x = fixpoint_sub0(v13, a4);
-      pSpriteObjects[v6].vVelocity.y = fixpoint_sub0(a5a, a4);
-      pSpriteObjects[v6].vVelocity.z = fixpoint_sub0(stru_5C6E00->Sin(pitch), a4);
+      v13 = fixpoint_mul(stru_5C6E00->Cos(angle), stru_5C6E00->Cos(pitch));
+      a5a = fixpoint_mul(stru_5C6E00->Sin(angle), stru_5C6E00->Cos(pitch));
+      pSpriteObjects[v6].vVelocity.x = fixpoint_mul(v13, a4);
+      pSpriteObjects[v6].vVelocity.y = fixpoint_mul(a5a, a4);
+      pSpriteObjects[v6].vVelocity.z = fixpoint_mul(stru_5C6E00->Sin(pitch), a4);
     }
     else
     {
@@ -132,11 +132,11 @@
     pSpriteObjects[v6].vVelocity.z = 0;
     if ( a4 )
     {
-      v13 = fixpoint_sub0(stru_5C6E00->Cos(angle), stru_5C6E00->Cos(pitch)) >> 16;
-      a5a = fixpoint_sub0(stru_5C6E00->Sin(angle), stru_5C6E00->Cos(pitch)) >> 16;
-      pSpriteObjects[v6].vVelocity.x = fixpoint_sub0(v13, a4);
-      pSpriteObjects[v6].vVelocity.y = fixpoint_sub0(a5a, a4);
-      pSpriteObjects[v6].vVelocity.z = fixpoint_sub0(stru_5C6E00->Sin(pitch), a4);
+      v13 = fixpoint_mul(stru_5C6E00->Cos(angle), stru_5C6E00->Cos(pitch)) >> 16;
+      a5a = fixpoint_mul(stru_5C6E00->Sin(angle), stru_5C6E00->Cos(pitch)) >> 16;
+      pSpriteObjects[v6].vVelocity.x = fixpoint_mul(v13, a4);
+      pSpriteObjects[v6].vVelocity.y = fixpoint_mul(a5a, a4);
+      pSpriteObjects[v6].vVelocity.z = fixpoint_mul(stru_5C6E00->Sin(pitch), a4);
     }
     else
     {
@@ -157,11 +157,11 @@
     pSpriteObjects[v6].vVelocity.z = 0;
     if ( a4 )
     {
-      v13 = fixpoint_sub0(stru_5C6E00->Cos(angle), stru_5C6E00->Cos(pitch));
-      a5a = fixpoint_sub0(stru_5C6E00->Sin(angle), stru_5C6E00->Cos(pitch));
-      pSpriteObjects[v6].vVelocity.x = fixpoint_sub0(v13, a4);
-      pSpriteObjects[v6].vVelocity.y = fixpoint_sub0(a5a, a4);
-      pSpriteObjects[v6].vVelocity.z = fixpoint_sub0(stru_5C6E00->Sin(pitch), a4);
+      v13 = fixpoint_mul(stru_5C6E00->Cos(angle), stru_5C6E00->Cos(pitch));
+      a5a = fixpoint_mul(stru_5C6E00->Sin(angle), stru_5C6E00->Cos(pitch));
+      pSpriteObjects[v6].vVelocity.x = fixpoint_mul(v13, a4);
+      pSpriteObjects[v6].vVelocity.y = fixpoint_mul(a5a, a4);
+      pSpriteObjects[v6].vVelocity.z = fixpoint_mul(stru_5C6E00->Sin(pitch), a4);
     }
     else
     {
@@ -182,11 +182,11 @@
     pSpriteObjects[v6].vVelocity.z = 0;
     if ( a4 )
     {
-      v13 = fixpoint_sub0(stru_5C6E00->Cos(angle), stru_5C6E00->Cos(pitch));
-      a5a = fixpoint_sub0(stru_5C6E00->Sin(angle), stru_5C6E00->Cos(pitch));
-      pSpriteObjects[v6].vVelocity.x = fixpoint_sub0(v13, a4);
-      pSpriteObjects[v6].vVelocity.y = fixpoint_sub0(a5a, a4);
-      pSpriteObjects[v6].vVelocity.z = fixpoint_sub0(stru_5C6E00->Sin(pitch), a4);
+      v13 = fixpoint_mul(stru_5C6E00->Cos(angle), stru_5C6E00->Cos(pitch));
+      a5a = fixpoint_mul(stru_5C6E00->Sin(angle), stru_5C6E00->Cos(pitch));
+      pSpriteObjects[v6].vVelocity.x = fixpoint_mul(v13, a4);
+      pSpriteObjects[v6].vVelocity.y = fixpoint_mul(a5a, a4);
+      pSpriteObjects[v6].vVelocity.z = fixpoint_mul(stru_5C6E00->Sin(pitch), a4);
     }
     else
     {
@@ -311,11 +311,11 @@
       v1->vVelocity.z -= LOWORD(pEventTimer->uTimeElapsed) * GetGravityStrength();
       v56 = abs(v51.y * v1->vVelocity.y + v51.z * v1->vVelocity.z + v51.x * v1->vVelocity.x) >> 16;
       //v60 = ((unsigned __int64)(v56 * (signed __int64)v51.x) >> 16);
-      v1->vVelocity.x += fixpoint_sub0(v56, v51.x);
+      v1->vVelocity.x += fixpoint_mul(v56, v51.x);
       //v60 = ((unsigned __int64)(v56 * (signed __int64)v51.y) >> 16);
-      v1->vVelocity.y += fixpoint_sub0(v56, v51.y);
+      v1->vVelocity.y += fixpoint_mul(v56, v51.y);
       //v60 = ((unsigned __int64)(v56 * (signed __int64)v51.z) >> 16);
-      v1->vVelocity.z += fixpoint_sub0(v56, v51.z);
+      v1->vVelocity.z += fixpoint_mul(v56, v51.z);
 LABEL_12:
       v7 = v54;
       goto LABEL_13;
@@ -331,9 +331,9 @@
     if ( !(v2->uFlags & OBJECT_DESC_BOUNCE) || (v21 = -v1->vVelocity.z >> 1, v1->vVelocity.z = v21, (signed __int16)v21 < 10) )
       v1->vVelocity.z = 0;
 
-    v1->vVelocity.x = fixpoint_sub0(58500, v1->vVelocity.x);
-    v1->vVelocity.y = fixpoint_sub0(58500, v1->vVelocity.y);
-    v1->vVelocity.z = fixpoint_sub0(58500, v1->vVelocity.z);
+    v1->vVelocity.x = fixpoint_mul(58500, v1->vVelocity.x);
+    v1->vVelocity.y = fixpoint_mul(58500, v1->vVelocity.y);
+    v1->vVelocity.z = fixpoint_mul(58500, v1->vVelocity.z);
 
     if ( (v1->vVelocity.y * v1->vVelocity.y + v1->vVelocity.x * v1->vVelocity.x) < 400 )
         {
@@ -503,12 +503,12 @@
         return;
       }
       //v60 = ((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.direction.x) >> 16);
-      v1->vPosition.x += fixpoint_sub0(stru_721530.field_7C, stru_721530.direction.x);
+      v1->vPosition.x += fixpoint_mul(stru_721530.field_7C, stru_721530.direction.x);
       //v60 = ((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.direction.y) >> 16);
-      v1->vPosition.y += fixpoint_sub0(stru_721530.field_7C, stru_721530.direction.y);
+      v1->vPosition.y += fixpoint_mul(stru_721530.field_7C, stru_721530.direction.y);
       //v60 = ((unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.direction.z) >> 16);
       v28 = LOWORD(stru_721530.uSectorID);
-      v1->vPosition.z += fixpoint_sub0(stru_721530.field_7C, stru_721530.direction.z);
+      v1->vPosition.z += fixpoint_mul(stru_721530.field_7C, stru_721530.direction.z);
       v29 = v1->vPosition.z;
       v1->uSectorID = v28;
       stru_721530.field_70 += stru_721530.field_7C;
@@ -786,11 +786,11 @@
         return;
       }
       //v40 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.direction.x) >> 16;
-      pSpriteObject->vPosition.x += fixpoint_sub0(stru_721530.field_7C, stru_721530.direction.x);
+      pSpriteObject->vPosition.x += fixpoint_mul(stru_721530.field_7C, stru_721530.direction.x);
       //v40 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.direction.y) >> 16;
-      pSpriteObject->vPosition.y += fixpoint_sub0(stru_721530.field_7C, stru_721530.direction.y);
+      pSpriteObject->vPosition.y += fixpoint_mul(stru_721530.field_7C, stru_721530.direction.y);
       //v40 = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.direction.z) >> 16;
-      pSpriteObject->vPosition.z += fixpoint_sub0(stru_721530.field_7C, stru_721530.direction.z);
+      pSpriteObject->vPosition.z += fixpoint_mul(stru_721530.field_7C, stru_721530.direction.z);
       pSpriteObject->uSectorID = stru_721530.uSectorID;
       stru_721530.field_70 += stru_721530.field_7C;
       if ( pObject->uFlags & 0x40 && !_46BFFA_check_object_intercept(uLayingItemID, stru_721530.uFaceID) )
@@ -801,8 +801,8 @@
         v40 = integer_sqrt(pSpriteObject->vVelocity.x * pSpriteObject->vVelocity.x + pSpriteObject->vVelocity.y * pSpriteObject->vVelocity.y);
         v23 = stru_5C6E00->Atan2(pSpriteObject->vPosition.x - pLevelDecorations[v15].vPosition.x,
                 pSpriteObject->vPosition.y - pLevelDecorations[v15].vPosition.y);
-        pSpriteObject->vVelocity.x = fixpoint_sub0(stru_5C6E00->Cos(v23), v40);
-        pSpriteObject->vVelocity.y = fixpoint_sub0(stru_5C6E00->Sin(v23), v40);
+        pSpriteObject->vVelocity.x = fixpoint_mul(stru_5C6E00->Cos(v23), v40);
+        pSpriteObject->vVelocity.y = fixpoint_mul(stru_5C6E00->Sin(v23), v40);
       }
       else
       {
@@ -816,9 +816,9 @@
                                                                     + v16->pFacePlane_old.vNormal.y * pSpriteObject->vVelocity.y) >> 16;
           if ( (stru_721530.speed >> 3) > v42 )
             v42 = stru_721530.speed >> 3;
-          pSpriteObject->vVelocity.x += 2 * fixpoint_sub0(v42, v16->pFacePlane_old.vNormal.x);
-          pSpriteObject->vVelocity.y += 2 * fixpoint_sub0(v42, v16->pFacePlane_old.vNormal.y);
-          v39 = fixpoint_sub0(v42, v16->pFacePlane_old.vNormal.z);
+          pSpriteObject->vVelocity.x += 2 * fixpoint_mul(v42, v16->pFacePlane_old.vNormal.x);
+          pSpriteObject->vVelocity.y += 2 * fixpoint_mul(v42, v16->pFacePlane_old.vNormal.y);
+          v39 = fixpoint_mul(v42, v16->pFacePlane_old.vNormal.z);
           if ( v16->pFacePlane_old.vNormal.z <= 32000 )
           {
             v22 = 2 * v39;
@@ -826,7 +826,7 @@
           else
           {
             pSpriteObject->vVelocity.z += v39;
-            v22 = fixpoint_sub0(32000, v39);
+            v22 = fixpoint_mul(32000, v39);
           }
           pSpriteObject->vVelocity.z += v22;
           if ( BYTE3(v16->uAttributes) & 0x10 )
@@ -861,9 +861,9 @@
 LABEL_63:
       //v2 = v37;
 LABEL_64:
-      pSpriteObject->vVelocity.x = fixpoint_sub0(58500, pSpriteObject->vVelocity.x);
-      pSpriteObject->vVelocity.y = fixpoint_sub0(58500, pSpriteObject->vVelocity.y);
-      pSpriteObject->vVelocity.z = fixpoint_sub0(58500, pSpriteObject->vVelocity.z);
+      pSpriteObject->vVelocity.x = fixpoint_mul(58500, pSpriteObject->vVelocity.x);
+      pSpriteObject->vVelocity.y = fixpoint_mul(58500, pSpriteObject->vVelocity.y);
+      pSpriteObject->vVelocity.z = fixpoint_mul(58500, pSpriteObject->vVelocity.z);
       ++uFaceID;
       v28 = __OFSUB__(uFaceID, 100);
       v27 = uFaceID - 100 < 0;
@@ -893,9 +893,9 @@
         pSpriteObject->vVelocity.z -= LOWORD(pEventTimer->uTimeElapsed) * GetGravityStrength();
       v8 = 0;
     }
-    pSpriteObject->vVelocity.x = fixpoint_sub0(58500, pSpriteObject->vVelocity.x);
-    pSpriteObject->vVelocity.y = fixpoint_sub0(58500, pSpriteObject->vVelocity.y);
-    pSpriteObject->vVelocity.z = fixpoint_sub0(58500, pSpriteObject->vVelocity.z);
+    pSpriteObject->vVelocity.x = fixpoint_mul(58500, pSpriteObject->vVelocity.x);
+    pSpriteObject->vVelocity.y = fixpoint_mul(58500, pSpriteObject->vVelocity.y);
+    pSpriteObject->vVelocity.z = fixpoint_mul(58500, pSpriteObject->vVelocity.z);
     v9 = pSpriteObject->vVelocity.x;
     if ( v9 * v9 + pSpriteObject->vVelocity.y * pSpriteObject->vVelocity.y < 400 )
     {
--- a/Texture.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/Texture.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -335,7 +335,7 @@
 }
 
 //----- (0044E19A) --------------------------------------------------------
-unsigned int TextureFrameTable::GetFrameTexture(int uFrameID, signed int a3)
+int TextureFrameTable::GetFrameTexture(int uFrameID, signed int a3)
 {
   int v3; // esi@1
   TextureFrame *v4; // edi@1
--- a/Texture.h	Wed Sep 18 06:30:53 2013 +0200
+++ b/Texture.h	Wed Sep 18 06:32:15 2013 +0200
@@ -111,7 +111,7 @@
   void ToFile();
   void FromFile(void *data_mm6, void *data_mm7, void *data_mm8);
   void LoadAnimationSequenceAndPalettes(signed int uIconID);
-  unsigned int GetFrameTexture(int uFrameID, signed int a3);
+  int GetFrameTexture(int uFrameID, int time);
   unsigned int FindTextureByName(const char *Str2);
 
 
--- a/UI/UICharacter.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/UI/UICharacter.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -12,7 +12,6 @@
 #include "..\Party.h"
 #include "..\AudioPlayer.h"
 #include "..\Render.h"
-#include "..\IndoorCamera.h"
 #include "..\LOD.h"
 #include "..\Viewport.h"
 #include "..\Time.h"
--- a/UI/UIHouses.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/UI/UIHouses.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -15,12 +15,12 @@
 #include "..\GUIFont.h"
 #include "..\Overlays.h"
 #include "..\Outdoor.h"
+#include "..\Outdoor_stuff.h"
 #include "..\AudioPlayer.h"
 #include "..\VideoPlayer.h"
 #include "..\Monsters.h"
 #include "..\Viewport.h"
 #include "..\Keyboard.h"
-#include "..\IndoorCamera.h"
 #include "..\MapInfo.h"
 #include "..\Log.h"
 #include "..\Game.h"
@@ -459,7 +459,7 @@
     }
     break;
 
-    case BuildingType_14:
+    case BuildingType_ElementalGuild:
     {
       CreateButtonInColumn(0, 18);
       CreateButtonInColumn(1, 48);
@@ -470,7 +470,7 @@
     }
     break;
 
-    case BuildingType_15:
+    case BuildingType_SelfGuild:
     {
       CreateButtonInColumn(0, 18);
       CreateButtonInColumn(1, 52);
@@ -1087,8 +1087,8 @@
     case BuildingType_BodyGuild:
     case BuildingType_LightGuild:
     case BuildingType_DarkGuild:
-    case BuildingType_14:
-    case BuildingType_15:
+    case BuildingType_ElementalGuild:
+    case BuildingType_SelfGuild:
     case BuildingType_16:
     {
       if ( pParty->field_3C.Shops_next_generation_time[window_SpeakInHouse->par1C] >= (signed __int64)pParty->uTimePlayed )
@@ -1920,7 +1920,6 @@
   int schedule_id; // esi@39
   GUIButton *pButton; // ebx@39
   signed int v25; // eax@41
-  unsigned int v30; // ecx@62
   MapInfo pMap; // [sp-3Ch] [bp-2CCh]@62
   char pTopicArray[5][100]; // [sp+14h] [bp-27Ch]@37
   GUIWindow travel_window; // [sp+208h] [bp-88h]@1
@@ -1969,7 +1968,7 @@
         }
 
         if (schedule_id != 255 && v25 && (!transport_schedule[schedule_id].uQuestBit
-           || _449B57_test_bit(pParty->_quest_bits, transport_schedule[schedule_id].uQuestBit)) )
+           || _449B57_test_bit(pParty->_quest_bits, transport_schedule[schedule_id].uQuestBit)) )//ошибка: рисуется несколько строчек одного направления путешествия
         {
   //get color for current string(определение цвета текущей строки)----------
           if ( pDialogueWindow->pCurrentPosActiveItem == pCurrentButton )
@@ -2005,9 +2004,8 @@
             strcat(pTopicArray[index], "\n \n");
             pButton->uY = pRealTextHeight;
             pTextHeight = pFontArrus->CalcTextHeight(pTmpBuf.data(), &travel_window, 0, 0);
-            v30 = pButton->uY;
             pButton->uHeight = pTextHeight;
-            pButton->uW = v30 + pTextHeight - 1;
+            pButton->uW = pButton->uY + pTextHeight - 1;
             pRealTextHeight += (LOBYTE(pFontArrus->uFontHeight) - 3) + pTextHeight;
           }
         }
@@ -2071,7 +2069,8 @@
         }
         else
         {
-          pIndoorCamera->sRotationY = 0;
+          pGame->pIndoorCameraD3D->sRotationY = 0;
+
           pParty->uFlags |= 2u;
           pParty->vPosition.x = pTravel->arrival_x;
           pParty->vPosition.y = pTravel->arrival_y;
@@ -2149,7 +2148,6 @@
   int v17; // ebx@28
   GUIButton *pButton; // eax@30
   int pTextHeight; // eax@30
-  unsigned int v23; // ecx@30
   unsigned __int16 pTextColor; // ax@30
   GUIWindow window; // [sp+60h] [bp-BCh]@21
   GUIWindow townHall_window; // [sp+B4h] [bp-68h]@1
@@ -2190,14 +2188,13 @@
           pButton = pDialogueWindow->GetControl(i);
           pButton->uY = v29 + v17;
           pTextHeight = pFontArrus->CalcTextHeight(pShopOptions[j], &townHall_window, 0, 0);
-          v23 = pButton->uY;
           pButton->uHeight = pTextHeight;
-          v17 = v23 + pTextHeight - 1;
+          v17 = pButton->uY + pTextHeight - 1;
           pButton->uW = v17;
           pTextColor = TargetColor(0xFFu, 0xFFu, 0x9Bu);
           if ( pDialogueWindow->pCurrentPosActiveItem != v31 )
             pTextColor = TargetColor(0xFFu, 0xFFu, 0xFFu);
-          townHall_window.DrawTitleText(pFontArrus, 0, v23, pTextColor, pShopOptions[j], 3);
+          townHall_window.DrawTitleText(pFontArrus, 0, pButton->uY, pTextColor, pShopOptions[j], 3);
           ++v31;
           ++j;
         }
@@ -2391,112 +2388,53 @@
 //----- (004B8285) --------------------------------------------------------
 void  TavernDialog()
 {
-  int v0;
+  int pPriceRoom;
+  int pPriceFood;
+  int pPriceSkill;
   int pItemNum;
   double v2; // st7@1
-  signed int v3; // ebx@1
-  int v4; // ecx@1
-  int v5; // esi@3
-  signed int v6; // edi@5
-  int v7; // ecx@5
   int pNumString; // edi@16
   signed int v9; // esi@16
-  unsigned int pNumActiveItem; // esi@18
-  int v11; // eax@18
-  unsigned int v12; // eax@19
-  int v13; // eax@21
-  int v14; // ecx@26
-  int v17; // eax@28
-  char *v18; // eax@30
-  int v19; // eax@30
-  unsigned int v20; // ecx@30
-  int v21; // edx@30
-  int v22; // eax@30
-  unsigned __int16 v23; // ax@30
-  int v24; // eax@34
-  int v25; // eax@34
-  char *v26; // esi@36
-  int v27; // edi@46
   unsigned int pColorText; // eax@57
-  signed int v31; // eax@59
-  int v34; // eax@64
-  int v35; // ecx@64
-  int v36; // esi@64
   GUIButton *pButton; // eax@65
-  int v39; // edx@69
-  int v40; // ecx@69
-  int v41; // ecx@69
-  int v42; // ecx@70
-  unsigned int v43; // edx@70
-  int v44; // edx@71
-  int v45; // ecx@71
-  int v46; // ecx@72
-  int v47; // eax@74
-  signed int v48; // edi@77
+  int pSkillCount;
+  signed int pOptionsCount; // edi@77
   signed int i; // esi@79
-  int v50; // eax@80
-  _QWORD v52; // qax@81
   signed int v53; // edi@81
   int v54; // edi@81
-  const char **v56; // eax@83
-  int v57; // eax@83
-  unsigned int v58; // ecx@83
-  unsigned __int16 v60; // ax@83
-  int v61; // eax@99
-  char *v63; // eax@99
-  GUIFont *v64; // edx@99
-  GUIFont *v65; // edi@100
-  unsigned int v66; // [sp-10h] [bp-284h]@75
-  unsigned __int16 v67; // [sp-Ch] [bp-280h]@75
-  int v68; // [sp-Ch] [bp-280h]@99
-  char *v69; // [sp-8h] [bp-27Ch]@75
-  int v70; // [sp-8h] [bp-27Ch]@99
-  unsigned int v71; // [sp-4h] [bp-278h]@75
-  const char *v72; // [sp-4h] [bp-278h]@93
-  unsigned int v73; // [sp-4h] [bp-278h]@99
+  const char *pText; // [sp-4h] [bp-278h]@93
   char pTopic1[100]; // [sp+Ch] [bp-268h]@55
   char pTopic4[100]; // [sp+70h] [bp-204h]@59
   char pTopic2[100]; // [sp+D4h] [bp-1A0h]@57
   char pTopic3[100]; // [sp+138h] [bp-13Ch]@59
   GUIWindow dialog_window; // [sp+1F0h] [bp-84h]@1
-  char *Str[2]; // [sp+244h] [bp-30h]@30
+  int v91; // [sp+270h] [bp-4h]@3
+  unsigned int pTopic1Height; // [sp+26Fh] [bp-5h]@55
+  unsigned __int8 pTopic2Height; // [sp+267h] [bp-Dh]@57
   unsigned __int8 pTopic3Height; // [sp+253h] [bp-21h]@59
-  int v83; // [sp+254h] [bp-20h]@1
-  int all_text_height; // [sp+260h] [bp-14h]@18
-  unsigned __int8 v87; // [sp+266h] [bp-Eh]@59
-  unsigned __int8 pTopic2Height; // [sp+267h] [bp-Dh]@57
-  int v89; // [sp+268h] [bp-Ch]@1
-  unsigned int pTopic1Height; // [sp+26Fh] [bp-5h]@55
-  int v91; // [sp+270h] [bp-4h]@3
-  GUIFont *pOutString;
   unsigned __int8 pTopic4Height;
   int pTextHeight;
+  int all_text_height; // [sp+260h] [bp-14h]@18
+  GUIFont *pOutString;
 
   memcpy(&dialog_window, window_SpeakInHouse, sizeof(dialog_window));
   dialog_window.uFrameX = 483;
   dialog_window.uFrameWidth = 148;
   dialog_window.uFrameZ = 334;
   v2 = p2DEvents[(unsigned int)window_SpeakInHouse->ptr_1C - 1].fPriceMultiplier;
-  *(float *)&v83 = v2;
-  *(float *)&v89 = v2 * v2;
-  v3 = (signed __int64)(*(float *)&v89 * 0.1);
-  pItemNum = v3 * (100 - pPlayers[uActiveCharacter]->GetMerchant()) / 100;
-  if ( pItemNum < v3 / 3 )
-    pItemNum = v3 / 3;
-  v5 = 1;
-  pOutString = (GUIFont *)pItemNum;
-  if ( pItemNum <= 0 )
-    pOutString = (GUIFont *)1;
-  v6 = (signed __int64)(*(float *)&v89 * *(float *)&v83 * 0.0099999998);
-  v7 = v6 * (100 - pPlayers[uActiveCharacter]->GetMerchant()) / 100;
-  if ( v7 < v6 / 3 )
-  v7 = v6 / 3;
-  v83 = v7;
-  if ( v7 <= 0 )
-  {
-    v7 = 1;
-    v83 = 1;
-  }
+
+  pPriceRoom = ((v2 * v2) / 10) * (100 - pPlayers[uActiveCharacter]->GetMerchant()) / 100;
+  if ( pPriceRoom < ((v2 * v2) / 10) / 3 )
+    pPriceRoom = ((v2 * v2) / 10) / 3;
+  if ( pPriceRoom <= 0 )
+    pPriceRoom = 1;
+
+  pPriceFood = ((v2 * v2) * v2 / 100) * (100 - pPlayers[uActiveCharacter]->GetMerchant()) / 100;
+  if ( pPriceFood < ((v2 * v2) * v2 / 100) / 3 )
+    pPriceFood = ((v2 * v2) * v2 / 100) / 3;
+  if ( pPriceFood <= 0 )
+    pPriceFood = 1;
+
 
   switch(dialog_menu_id)
   {
@@ -2506,14 +2444,14 @@
           return;
 
       sprintf(pTopic1, "\f%05d", pDialogueWindow->pCurrentPosActiveItem == 2 ? TargetColor(0xFFu, 0xFFu, 0x9Bu) : TargetColor(0xFFu, 0xFFu, 0xFFu));
-      sprintfex(pTmpBuf2.data(), pGlobalTXT_LocalizationStrings[178], pOutString); // Rent room for %d gold
+      sprintfex(pTmpBuf2.data(), pGlobalTXT_LocalizationStrings[178], pPriceRoom); // Rent room for %d gold
       strcat(pTopic1, pTmpBuf2.data());
       pTopic1Height = pFontArrus->CalcTextHeight(pTopic1, &dialog_window, 0, 0);
       strcat(pTopic1, "\n \n");
 
       sprintf(pTopic2, "\f%05d", pDialogueWindow->pCurrentPosActiveItem == 3 ? TargetColor(0xFFu, 0xFFu, 0x9Bu) : TargetColor(0xFFu, 0xFFu, 0xFFu));
       sprintfex(pTmpBuf2.data(), pGlobalTXT_LocalizationStrings[86], // Buy food for %d days for %d gold
-        (unsigned int)p2DEvents[(unsigned int)window_SpeakInHouse->ptr_1C - 1].fPriceMultiplier, v83);
+        (unsigned int)p2DEvents[(unsigned int)window_SpeakInHouse->ptr_1C - 1].fPriceMultiplier, pPriceFood);
       strcat(pTopic2, pTmpBuf2.data());
       pTopic2Height = pFontArrus->CalcTextHeight(pTopic2, &dialog_window, 0, 0);
       strcat(pTopic2, "\n \n");
@@ -2530,47 +2468,35 @@
         pTopic4Height = pFontArrus->CalcTextHeight(pTopic4, &dialog_window, 0, 0);
       }
 
-      v36 = LOBYTE(pFontArrus->uFontHeight) - 3;
       if ( pDialogueWindow->pNumPresenceButton )
       {
-        for ( pNumActiveItem = pDialogueWindow->pStartingPosActiveItem;
-              pNumActiveItem < pDialogueWindow->pStartingPosActiveItem + pDialogueWindow->pNumPresenceButton; ++pNumActiveItem )
+        for ( pItemNum = pDialogueWindow->pStartingPosActiveItem;
+              pItemNum < pDialogueWindow->pStartingPosActiveItem + pDialogueWindow->pNumPresenceButton; ++pItemNum )
         {
-          pButton = pDialogueWindow->GetControl(pNumActiveItem);
+          pButton = pDialogueWindow->GetControl(pItemNum);
           if ( pButton->msg_param == 15 )
           {
-            v46 = pTopic1Height;
             pButton->uHeight = pTopic1Height;
             pButton->uY = 146;
-            v41 = v46 + 145;
-            pButton->uW = v41;
+            pButton->uW = pTopic1Height + 145;
           }
           else if ( pButton->msg_param == 16 )
           {
-            v44 = pTopic2Height;
-            v45 = pTopic1Height + v36 + 146;
             pButton->uHeight = pTopic2Height;
-            pButton->uY = v45;
-            v41 = v45 + v44 - 1;
-            pButton->uW = v41;
+            pButton->uY = pTopic1Height + (LOBYTE(pFontArrus->uFontHeight) - 3) + 146;
+            pButton->uW = (pTopic1Height + (LOBYTE(pFontArrus->uFontHeight) - 3) + 146) + pTopic2Height - 1;
           }
           else if ( pButton->msg_param == 96 )
           {
-            v42 = pTopic1Height + pTopic2Height + 2 * v36 + 146;
-            v43 = pTopic3Height;
-            pButton->uY = v42;
-            pButton->uHeight = v43;
-            v41 = v43 + v42 - 1;
-            pButton->uW = v41;
+            pButton->uY = pTopic1Height + pTopic2Height + 2 * (LOBYTE(pFontArrus->uFontHeight) - 3) + 146;
+            pButton->uHeight = pTopic3Height;
+            pButton->uW = pTopic3Height + (pTopic1Height + pTopic2Height + 2 * (LOBYTE(pFontArrus->uFontHeight) - 3) + 146) - 1;
           }
           else if ( pButton->msg_param == 101 )
           {
-            v39 = pTopic1Height + 3 * v36 + pTopic4Height + pTopic2Height + 146;
-            v40 = pTopic4Height;
             pButton->uHeight = pTopic4Height;
-            pButton->uY = v39;
-            v41 = v39 + v40 - 1;
-            pButton->uW = v41;
+            pButton->uY = pTopic1Height + 3 * (LOBYTE(pFontArrus->uFontHeight) - 3) + pTopic4Height + pTopic2Height + 146;
+            pButton->uW = (pTopic1Height + 3 * (LOBYTE(pFontArrus->uFontHeight) - 3) + pTopic4Height + pTopic2Height + 146) + pTopic4Height - 1;
           }
         }
         sprintfex(pTmpBuf.data(), "%s%s%s%s", pTopic1, pTopic2, pTopic3, pTopic4);
@@ -2590,11 +2516,9 @@
         pOutString = pFontCreate;
         pTextHeight = pFontCreate->CalcTextHeight(pTmpBuf.data(), &dialog_window, 12, 0) + 7;
       }
-      auto pTex = pIcons_LOD->GetTexture(uTextureID_Leather);
-      pRenderer->GetLeather(8, 352 - pTextHeight, pTex, pTex->uTextureHeight - pTextHeight);
+      pRenderer->GetLeather(8, 352 - pTextHeight, pIcons_LOD->GetTexture(uTextureID_Leather), pIcons_LOD->GetTexture(uTextureID_Leather)->uTextureHeight - pTextHeight);
       pRenderer->DrawTextureIndexed(8, 347 - pTextHeight, pTexture_591428);
-      v63 = FitTextInAWindow(pTmpBuf.data(), pOutString, &dialog_window, 0xCu, 0);
-      window_SpeakInHouse->DrawText(pOutString, 12, 354 - pTextHeight, 0, v63, 0, 0, 0);
+      window_SpeakInHouse->DrawText(pOutString, 12, 354 - pTextHeight, 0, FitTextInAWindow(pTmpBuf.data(), pOutString, &dialog_window, 0xCu, 0), 0, 0, 0);
       break;
     }
     case HOUSE_DIALOGUE_TAVERN_ARCOMAGE_VICTORY_CONDITIONS:
@@ -2602,13 +2526,11 @@
       strcpy(pTmpBuf.data(), pNPCTopics[(uint)window_SpeakInHouse->ptr_1C + 247].pText);
       dialog_window.uFrameWidth = game_viewport_width;
       dialog_window.uFrameZ = 452;
-      v61 = pFontArrus->CalcTextHeight(pTmpBuf.data(), &dialog_window, 12, 0);
-      pTextHeight = v61 + 7;
-      auto pTex = pIcons_LOD->GetTexture(uTextureID_Leather);
-      pRenderer->GetLeather(8, 352 - (v61 + 7), pTex, pTex->uTextureHeight - (v61 + 7));
+      pTextHeight = pFontArrus->CalcTextHeight(pTmpBuf.data(), &dialog_window, 12, 0) + 7;
+      pRenderer->GetLeather(8, 352 - pTextHeight, pIcons_LOD->GetTexture(uTextureID_Leather), pIcons_LOD->GetTexture(uTextureID_Leather)->uTextureHeight - pTextHeight);
       pRenderer->DrawTextureIndexed(8, 347 - pTextHeight, pTexture_591428);
-      v63 = FitTextInAWindow(pTmpBuf.data(), pFontArrus, &dialog_window, 0xCu, 0);
-      window_SpeakInHouse->DrawText(pFontArrus, 12, 354 - pTextHeight, 0, v63, 0, 0, 0);
+      window_SpeakInHouse->DrawText(pFontArrus, 12, 354 - pTextHeight, 0,
+                                    FitTextInAWindow(pTmpBuf.data(), pFontArrus, &dialog_window, 0xCu, 0), 0, 0, 0);
       break;
     }
     case HOUSE_DIALOGUE_TAVERN_ARCOMAGE_RESULT:
@@ -2618,43 +2540,42 @@
       if ( pArcomageGame->uGameResult )
       {
         if ( pArcomageGame->uGameResult == 1 )
-          v72 = pGlobalTXT_LocalizationStrings[640];// You won!
+          pText = pGlobalTXT_LocalizationStrings[640];// You won!
         else
-          v72 = pGlobalTXT_LocalizationStrings[641];// You lost!
+          pText = pGlobalTXT_LocalizationStrings[641];// You lost!
       }
       else
       {
-        v72 = pGlobalTXT_LocalizationStrings[639];// A tie!
+        pText = pGlobalTXT_LocalizationStrings[639];// A tie!
       }
-      strcpy(pTmpBuf.data(), v72);
-      v66 = (174 - pFontArrus->CalcTextHeight(pTmpBuf.data(), &dialog_window, 0, 0)) / 2 + 138;
-      dialog_window.DrawTitleText(pFontArrus, 0, v66, TargetColor(0xFFu, 0xFFu, 0x9Bu), pTmpBuf.data(), 3);
+      strcpy(pTmpBuf.data(), pText);
+      dialog_window.DrawTitleText(pFontArrus, 0, (174 - pFontArrus->CalcTextHeight(pTmpBuf.data(), &dialog_window, 0, 0)) / 2 + 138,
+                                  TargetColor(0xFFu, 0xFFu, 0x9Bu), pTmpBuf.data(), 3);
       break;
     }
     case HOUSE_DIALOGUE_TAVERN_REST:
     {
-      if ( pParty->uNumGold >= (unsigned int)pOutString )
+      if ( pParty->uNumGold >= pPriceRoom )
       {
-        Party::TakeGold((unsigned int)pOutString);
-        v27 = (int)window_SpeakInHouse->ptr_1C;//107
+        Party::TakeGold(pPriceRoom);
         PlayHouseSound((unsigned int)window_SpeakInHouse->ptr_1C, HouseSound_NotEnoughMoney_TrainingSuccessful);
         dialog_menu_id = HOUSE_DIALOGUE_NULL;
         sub_4BD8B5();
         GetHouseGoodbyeSpeech();
         pVideoPlayer->Unload();
-        window_SpeakInHouse->Release();
-        window_SpeakInHouse = 0;
         if ( pMessageQueue_50CBD0->uNumMessages )
           pMessageQueue_50CBD0->uNumMessages = pMessageQueue_50CBD0->pMessages[0].field_8 != 0;
         pMessageQueue_50CBD0->pMessages[0].eType = UIMSG_RentRoom;
-        pMessageQueue_50CBD0->pMessages[0].param = v27;
+        pMessageQueue_50CBD0->pMessages[0].param = (int)window_SpeakInHouse->ptr_1C;//107
         pMessageQueue_50CBD0->pMessages[0].field_8 = 1;
         ++pMessageQueue_50CBD0->uNumMessages;
+        window_SpeakInHouse->Release();
+        window_SpeakInHouse = 0;
         return;
       }
-      ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2);
+      ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2);//У вас не хватает золота
       PlayHouseSound((unsigned int)window_SpeakInHouse->ptr_1C, HouseSound_Goodbye);
-      pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, v5, 0);
+      pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 1, 0);
       break;
     }
 
@@ -2662,74 +2583,60 @@
     {
       if ( !HouseUI_CheckIfPlayerCanInteract() )
         return;
-      v0 = 0;
+      pSkillCount = 0;
       v9 = (signed __int64)(p2DEvents[(unsigned int)window_SpeakInHouse->ptr_1C - 1].flt_24 * 500.0);
-      pItemNum = v9 * (100 - pPlayers[uActiveCharacter]->GetMerchant()) / 100;
-      if ( pItemNum < v9 / 3 )
-        pItemNum = v9 / 3;
-      pNumActiveItem = pDialogueWindow->pStartingPosActiveItem;
+      pPriceSkill = v9 * (100 - pPlayers[uActiveCharacter]->GetMerchant()) / 100;
+      if ( pPriceSkill < v9 / 3 )
+        pPriceSkill = v9 / 3;
       all_text_height = 0;
-      if ( pNumActiveItem < pNumActiveItem + pDialogueWindow->pNumPresenceButton )
+      for ( pItemNum = pDialogueWindow->pStartingPosActiveItem;
+            pItemNum < pDialogueWindow->pStartingPosActiveItem + pDialogueWindow->pNumPresenceButton; ++pItemNum )
       {
-        do
-        {
-          v12 = pDialogueWindow->GetControl(pNumActiveItem)->msg_param - 36;
-          if ( byte_4ED970_skill_learn_ability_by_class_table[pPlayers[uActiveCharacter]->classType][v12]
-              && !pPlayers[uActiveCharacter]->pActiveSkills[v12] )
-          {
-            all_text_height = pFontArrus->CalcTextHeight(pSkillNames[v12], &dialog_window, 0, 0);
-            v0++;
-          }
-          ++pNumActiveItem;
-        }
-        while ( pNumActiveItem < pDialogueWindow->pStartingPosActiveItem + pDialogueWindow->pNumPresenceButton );
-        if ( v0 )
+        if ( byte_4ED970_skill_learn_ability_by_class_table[pPlayers[uActiveCharacter]->classType][pDialogueWindow->GetControl(pItemNum)->msg_param - 36]
+            && !pPlayers[uActiveCharacter]->pActiveSkills[pDialogueWindow->GetControl(pItemNum)->msg_param - 36] )
         {
-          sprintf(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[401], pItemNum);
-          dialog_window.DrawTitleText(pFontArrus, 0, 0x92u, 0, pTmpBuf.data(), 3);
-          v91 = (149 - all_text_height) / v0;
-          if ( (149 - all_text_height) / v0 > 32 )
-            v91 = 32;
-          v14 = (149 - v0 * v91 - all_text_height) / 2 - v91 / 2 + 162;
-          pNumActiveItem = pDialogueWindow->pStartingPosActiveItem;
-          if ( pNumActiveItem < pNumActiveItem + pDialogueWindow->pNumPresenceButton )
-          {
-            pItemNum = 2;
-            do
-            {
-              pButton = pDialogueWindow->GetControl(pItemNum);
-              v17 = pButton->msg_param - 36;
-              if ( !byte_4ED970_skill_learn_ability_by_class_table[pPlayers[uActiveCharacter]->classType][v17]
-                 || pPlayers[uActiveCharacter]->pActiveSkills[v17] )
-              {
-                pButton->uW = 0;
-                pButton->uHeight = 0;
-                pButton->uY = 0;
-              }
-              else
-              {
-                pButton->uY = v91 + v14;
-                pTextHeight = pFontArrus->CalcTextHeight(pSkillNames[v17], &dialog_window, 0, 0);
-                pButton->uHeight = pTextHeight;
-                v14 = pTextHeight + pButton->uY - 1;
-                pButton->uW = v14;
-                pColorText = TargetColor(0xFFu, 0xFFu, 0x9Bu);
-                if ( pDialogueWindow->pCurrentPosActiveItem != pItemNum )
-                  pColorText = TargetColor(0xFFu, 0xFFu, 0xFFu);
-                dialog_window.DrawTitleText(pFontArrus, 0, pButton->uY, pColorText, pSkillNames[v17], 3);
-              }
-              pNumActiveItem = pDialogueWindow->pStartingPosActiveItem + pDialogueWindow->pNumPresenceButton;
-              pItemNum++;
-            }
-            while ( pItemNum < pNumActiveItem );
-          }
-          return;
+          all_text_height = pFontArrus->CalcTextHeight(pSkillNames[pDialogueWindow->GetControl(pItemNum)->msg_param - 36], &dialog_window, 0, 0);
+          pSkillCount++;
         }
       }
-      sprintf(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[544], pPlayers[uActiveCharacter]->pName,
+      if ( pSkillCount )
+      {
+        sprintf(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[401], pPriceSkill);//Стоимость навыка: %lu
+        dialog_window.DrawTitleText(pFontArrus, 0, 0x92u, 0, pTmpBuf.data(), 3);
+        v91 = (149 - all_text_height) / pSkillCount;
+        if ( (149 - all_text_height) / pSkillCount > 32 )
+          v91 = 32;
+        v54 = (149 - pSkillCount * v91 - all_text_height) / 2 - v91 / 2 + 162;
+        for ( pItemNum = pDialogueWindow->pStartingPosActiveItem;
+              pItemNum < pDialogueWindow->pStartingPosActiveItem + pDialogueWindow->pNumPresenceButton; pItemNum++ )
+        {
+          pButton = pDialogueWindow->GetControl(pItemNum);
+          if ( !byte_4ED970_skill_learn_ability_by_class_table[pPlayers[uActiveCharacter]->classType][pButton->msg_param - 36]
+            || pPlayers[uActiveCharacter]->pActiveSkills[pButton->msg_param - 36] )
+          {
+            pButton->uW = 0;
+            pButton->uHeight = 0;
+            pButton->uY = 0;
+          }
+          else
+          {
+            pButton->uY = v91 + v54;
+            pTextHeight = pFontArrus->CalcTextHeight(pSkillNames[pButton->msg_param - 36], &dialog_window, 0, 0);
+            pButton->uHeight = pTextHeight;
+            v54 = pTextHeight + pButton->uY - 1;
+            pButton->uW = v54;
+            pColorText = TargetColor(0xFFu, 0xFFu, 0x9Bu);
+            if ( pDialogueWindow->pCurrentPosActiveItem != pItemNum )
+              pColorText = TargetColor(0xFFu, 0xFFu, 0xFFu);
+            dialog_window.DrawTitleText(pFontArrus, 0, pButton->uY, pColorText, pSkillNames[pButton->msg_param - 36], 3);
+          }
+        }
+        return;
+      }
+      sprintf(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[544], pPlayers[uActiveCharacter]->pName,//Советую вам %s %s поискать знания еще где-нибудь
               pClassNames[pPlayers[uActiveCharacter]->classType]);
       strcat(pTmpBuf.data(), "\n \n");
-      strcat(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[528]);
+      strcat(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[528]);//Больше ничего не могу предложить.
       pTextHeight = (174 - pFontArrus->CalcTextHeight(pTmpBuf.data(), &dialog_window, 0, 0)) / 2 + 138;
       dialog_window.DrawTitleText(pFontArrus, 0, pTextHeight, TargetColor(0xFFu, 0xFFu, 0x9Bu), pTmpBuf.data(), 3);
       return;
@@ -2737,20 +2644,17 @@
 
     case HOUSE_DIALOGUE_TAVERN_BUY_FOOD:
     {
-      *(_QWORD *)Str = pParty->uNumFoodRations;
-      //if ( (double)pParty->uNumFoodRations >= p2DEvents_minus1__20[13 * (unsigned int)ptr_507BC0->ptr_1C] )
       if ( (double)pParty->uNumFoodRations >= p2DEvents[(unsigned int)window_SpeakInHouse->ptr_1C - 1].fPriceMultiplier )
       {
-        ShowStatusBarString(pGlobalTXT_LocalizationStrings[140], 2);
+        ShowStatusBarString(pGlobalTXT_LocalizationStrings[140], 2);//Вы уже купили еду!
         if ( uActiveCharacter )
           pPlayers[uActiveCharacter]->PlaySound(SPEECH_67, 0);
-        pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, v5, 0);
+        pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 1, 0);
         return;
       }
-      if ( pParty->uNumGold >= v7 )
+      if ( pParty->uNumGold >= pPriceFood )
       {
-        Party::TakeGold(v7);
-        //pParty->uNumFoodRations = (signed __int64)p2DEvents_minus1__20[13 * (unsigned int)ptr_507BC0->ptr_1C];
+        Party::TakeGold(pPriceFood);
         pParty->uNumFoodRations = (signed __int64)p2DEvents[(unsigned int)window_SpeakInHouse->ptr_1C - 1].fPriceMultiplier;
         PlayHouseSound((unsigned int)window_SpeakInHouse->ptr_1C, HouseSound_Greeting_2);
         pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 1, 0);
@@ -2758,7 +2662,7 @@
       }
       ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2);  // "You don't have enough gold"
       PlayHouseSound((unsigned int)window_SpeakInHouse->ptr_1C, HouseSound_Goodbye);
-      pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, v5, 0);
+      pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 1, 0);
       break;
     }
 
@@ -2766,42 +2670,34 @@
     {
       if ( HouseUI_CheckIfPlayerCanInteract() )
       {
-        v48 = 2;
-        pShopOptions[0] = pGlobalTXT_LocalizationStrings[620];
-        pShopOptions[1] = pGlobalTXT_LocalizationStrings[622];
-        pOutString = 0;
-        if ( pParty->HasItem(0x28Bu) )
-        {
-          pShopOptions[2] = pGlobalTXT_LocalizationStrings[621];
-          v48 = 3;
-        }
-        for ( i = 0; i < v48; ++i )
-          all_text_height = pFontArrus->CalcTextHeight(pShopOptions[i], &dialog_window, 0, 0);
-        all_text_height = (174 - all_text_height) / v48;
-        pNumActiveItem = pDialogueWindow->pStartingPosActiveItem;
-        v54 = (174 - v48 * (174 - all_text_height) / v48 - all_text_height) / 2 - (174 - all_text_height) / v48 / 2 + 138;
-        //v37 = -pDialogueWindow->pNumPresenceButton < 0;
-        if ( pNumActiveItem < pNumActiveItem + pDialogueWindow->pNumPresenceButton )
+        pOptionsCount = 2;
+        pShopOptions[0] = pGlobalTXT_LocalizationStrings[620];//Правила
+        pShopOptions[1] = pGlobalTXT_LocalizationStrings[622];//Условия победы
+        if ( pParty->HasItem(651) )//651 - Колода для игры в АркоМэйдж в Items.txt
         {
-          pItemNum = 2;
-          pNumString = 0;
-          do
-          {
-            pButton = pDialogueWindow->GetControl(pItemNum);
-            pButton->uY = all_text_height + v54;
-            pTextHeight = pFontArrus->CalcTextHeight((const char *)pShopOptions[pNumString], &dialog_window, 0, 0);
-            pButton->uHeight = pTextHeight;
-            v54 = pButton->uY + pTextHeight - 1;
-            pButton->uW = v54;
-            pColorText = TargetColor(0xFFu, 0xFFu, 0x9Bu);
-            if ( pDialogueWindow->pCurrentPosActiveItem != pItemNum )
-              pColorText = TargetColor(0xFFu, 0xFFu, 0xFFu);
-            dialog_window.DrawTitleText(pFontArrus, 0, pButton->uY, pColorText, (const char *)pShopOptions[pNumString], 3);
-            pItemNum++;
-            ++pNumString;
-            pNumActiveItem = pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem;
-          }
-          while ( pItemNum < pNumActiveItem );
+          pShopOptions[2] = pGlobalTXT_LocalizationStrings[621];//Играть
+          pOptionsCount = 3;
+        }
+        for ( i = 0; i < pOptionsCount; ++i )
+          all_text_height = pFontArrus->CalcTextHeight(pShopOptions[i], &dialog_window, 0, 0);
+        all_text_height = (174 - all_text_height) / pOptionsCount;
+        
+        v54 = (174 - pOptionsCount * (174 - all_text_height) / pOptionsCount - all_text_height) / 2 - (174 - all_text_height) / pOptionsCount / 2 + 138;
+        pNumString = 0;
+        for ( pItemNum = pDialogueWindow->pStartingPosActiveItem;
+              pItemNum < pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem ; pItemNum++ )
+        {
+          pButton = pDialogueWindow->GetControl(pItemNum);
+          pButton->uY = all_text_height + v54;
+          pTextHeight = pFontArrus->CalcTextHeight((const char *)pShopOptions[pNumString], &dialog_window, 0, 0);
+          pButton->uHeight = pTextHeight;
+          v54 = pButton->uY + pTextHeight - 1;
+          pButton->uW = v54;
+          pColorText = TargetColor(0xFFu, 0xFFu, 0x9Bu);
+          if ( pDialogueWindow->pCurrentPosActiveItem != pItemNum )
+            pColorText = TargetColor(0xFFu, 0xFFu, 0xFFu);
+          dialog_window.DrawTitleText(pFontArrus, 0, pButton->uY, pColorText, (const char *)pShopOptions[pNumString], 3);
+          ++pNumString;
         }
       }
       break;
@@ -2816,44 +2712,19 @@
 //----- (004B705E) --------------------------------------------------------
 void TempleDialog()
 {
-    int pPrice; // edi@1
-    int result; // eax@4
-    unsigned int v9; // eax@9
-    int pTextHeight; // eax@11
-    int v11; // eax@12
-    GUIWindow *v12; // ecx@16
-    int v13; // edx@16
-    GUIButton *v14; // eax@19
-    GUIButton *v15; // edi@19
-    int v16; // eax@19
-    unsigned int v19; // ecx@21
-    int v20; // eax@21
-    unsigned __int16 pTextColor; // ax@21
-    double v24; // st7@28
-    unsigned int v25; // ebx@28
-    DDM_DLV_Header *v26; // edi@29
-    int v27; // eax@31
-    int v28; // eax@32
-    unsigned int v30; // edx@36
-    unsigned int v31; // edx@38
-    unsigned int v32; // edx@40
-    unsigned int v33; // edx@42
-    unsigned int v34; // edx@44
-    int v35; // edi@50
-    signed int v36; // eax@50
-    unsigned __int8 v37; // al@54
-    int v38; // ecx@54
-    GUIWindow *v39; // eax@56
-    unsigned __int8 v40; // al@61
-    GUIButton *pButton; // edi@64
-    int v47; // edi@71
-    unsigned int v52; // ecx@73
-    GUIWindow tample_window; // [sp+13Ch] [bp-88h]@1
-    unsigned int v62; // [sp+1B0h] [bp-14h]@8
-    unsigned __int8 index; // [sp+1B7h] [bp-Dh]@64
-    int v64; // [sp+1B8h] [bp-Ch]@6
-    unsigned int pCurrentItem; // [sp+1BCh] [bp-8h]@6
-    int all_text_height; // [sp+1C0h] [bp-4h]@6
+  int pPrice; // edi@1
+  int pTextHeight; // eax@11
+  unsigned __int16 pTextColor; // ax@21
+  DDM_DLV_Header *v26; // edi@29
+  unsigned int v30; // edx@36
+  int v35; // edi@50
+  GUIButton *pButton; // edi@64
+  int v47; // edi@71
+  GUIWindow tample_window; // [sp+13Ch] [bp-88h]@1
+  unsigned __int8 index; // [sp+1B7h] [bp-Dh]@64
+  int v64; // [sp+1B8h] [bp-Ch]@6
+  unsigned int pCurrentItem; // [sp+1BCh] [bp-8h]@6
+  int all_text_height; // [sp+1C0h] [bp-4h]@6
 
   memcpy(&tample_window, window_SpeakInHouse, sizeof(tample_window));
   tample_window.uFrameX = 483;
@@ -2887,7 +2758,7 @@
     v64 = (174 - (signed int)all_text_height) / (pDialogueWindow->pNumPresenceButton - index);
     if ( v64 > 32 )
       v64 = 32;
-    v47 = (174 - v64 * (pDialogueWindow->pNumPresenceButton - index) - (signed int)all_text_height) / 2 - v64 / 2 + 138;
+    all_text_height = (174 - v64 * (pDialogueWindow->pNumPresenceButton - index) - (signed int)all_text_height) / 2 - v64 / 2 + 138;
     if ( index + pDialogueWindow->pStartingPosActiveItem < pDialogueWindow->pStartingPosActiveItem + pDialogueWindow->pNumPresenceButton )
     {
       uint i = index;
@@ -2895,16 +2766,15 @@
           (signed int)pCurrentItem < pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem; ++pCurrentItem )
       {
         pButton = pDialogueWindow->GetControl(pCurrentItem);
-        pButton->uY = v64 + v47;
+        pButton->uY = v64 + all_text_height;
         pTextHeight = pFontArrus->CalcTextHeight(pShopOptions[1 * i], &tample_window, 0, 0);
-        v52 = pButton->uY;
         pButton->uHeight = pTextHeight;
-        v47 = v52 + pTextHeight - 1;
-        pButton->uW = v47;
+        pButton->uW = pButton->uY + pTextHeight - 1;
+        all_text_height = pButton->uW;
         pTextColor = TargetColor(0xFFu, 0xFFu, 0x9Bu);
         if ( pDialogueWindow->pCurrentPosActiveItem != index + 2 )
           pTextColor = TargetColor(0xFFu, 0xFFu, 0xFFu);
-        tample_window.DrawTitleText(pFontArrus, 0, v52, pTextColor, pShopOptions[1 * i], 3);
+        tample_window.DrawTitleText(pFontArrus, 0, pButton->uY, pTextColor, pShopOptions[1 * i], 3);
         i++;
         index++;
       }
@@ -2916,12 +2786,11 @@
   {
     if ( !pPlayers[uActiveCharacter]->IsPlayerHealableByTemple() )
       return;
-    v25 = 0;
     if ( pParty->uNumGold < pPrice )
     {
-      ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2);
+      ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2);//"У вас не хватает золота"
       PlayHouseSound((unsigned int)window_SpeakInHouse->ptr_1C, HouseSound_NotEnoughMoney_TrainingSuccessful);
-      pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 1, v25);
+      pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 1, 0);
       return;
     }
     Party::TakeGold(pPrice);
@@ -2929,21 +2798,18 @@
     memset(pPlayers[uActiveCharacter], 0, 0xA0u);
     pPlayers[uActiveCharacter]->sHealth = pPlayers[uActiveCharacter]->GetMaxHealth();
     pPlayers[uActiveCharacter]->sMana = pPlayers[uActiveCharacter]->GetMaxMana();
-    v36 = (signed int)window_SpeakInHouse->ptr_1C;
-    if ( v36 != 78 && (v36 <= 80 || v36 > 82) )
+    if ( (signed int)window_SpeakInHouse->ptr_1C != 78 && ((signed int)window_SpeakInHouse->ptr_1C <= 80 || (signed int)window_SpeakInHouse->ptr_1C > 82) )
     {
       if ( (unsigned int)pPlayers[uActiveCharacter]->pConditions[17] | v35 )
       {
-        v37 = LOBYTE(pPlayers[uActiveCharacter]->uPrevFace);
-        v38 = pPlayers[uActiveCharacter]->uPrevVoiceID;
-        pPlayers[uActiveCharacter]->uCurrentFace = v37;
-        pPlayers[uActiveCharacter]->uVoiceID = v38;
-        ReloadPlayerPortraits(uActiveCharacter - 1, (char)v37);
+        pPlayers[uActiveCharacter]->uCurrentFace = pPlayers[uActiveCharacter]->uPrevFace;
+        pPlayers[uActiveCharacter]->uVoiceID = pPlayers[uActiveCharacter]->uPrevVoiceID;
+        ReloadPlayerPortraits(uActiveCharacter - 1, pPlayers[uActiveCharacter]->uPrevFace);
       }
       pAudioPlayer->PlaySound((SoundID)(SOUND_GoldReceived|0x2), -1, 0, -1, 0, 0, 0, 0);
       pPlayers[uActiveCharacter]->PlaySound(SPEECH_82, 0);
       pOtherOverlayList->_4418B1(20, uActiveCharacter + 99, 0, 65536);
-      pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 1, v25);
+      pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 1, 0);
       return;
     }
     if ( (unsigned int)pPlayers[uActiveCharacter]->pConditions[17] | v35 )
@@ -2958,117 +2824,105 @@
         pAudioPlayer->PlaySound((SoundID)(SOUND_GoldReceived|0x2), -1, 0, -1, 0, 0, 0, 0);
         pPlayers[uActiveCharacter]->PlaySound(SPEECH_82, 0);
         pOtherOverlayList->_4418B1(20, uActiveCharacter + 99, 0, 65536);
-        pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 1, v25);
+        pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 1, 0);
         return;
       }
       pPlayers[uActiveCharacter]->uPrevFace = pPlayers[uActiveCharacter]->uCurrentFace;
       pPlayers[uActiveCharacter]->uPrevVoiceID = pPlayers[uActiveCharacter]->uVoiceID;
       pPlayers[uActiveCharacter]->SetCondition(0x11u, 1);
       pPlayers[uActiveCharacter]->uVoiceID = (pPlayers[uActiveCharacter]->GetSexByVoice() != 0) + 23;
-      v40 = (pPlayers[uActiveCharacter]->GetSexByVoice() != 0) + 23;
-      pPlayers[uActiveCharacter]->uCurrentFace = v40;
-      ReloadPlayerPortraits(uActiveCharacter - 1, (char)v40);
+      pPlayers[uActiveCharacter]->uCurrentFace = (pPlayers[uActiveCharacter]->GetSexByVoice() != 0) + 23;
+      ReloadPlayerPortraits(uActiveCharacter - 1, (pPlayers[uActiveCharacter]->GetSexByVoice() != 0) + 23);
       LODWORD(pPlayers[uActiveCharacter]->pConditions[17]) = LODWORD(pParty->uTimePlayed);
-      v39 = (GUIWindow *)HIDWORD(pParty->uTimePlayed);
+      //v39 = (GUIWindow *)HIDWORD(pParty->uTimePlayed);
     }
-    HIDWORD(pPlayers[uActiveCharacter]->pConditions[17]) = (int)v39;
+    //HIDWORD(pPlayers[uActiveCharacter]->pConditions[17]) = (int)v39;
+    pPlayers[uActiveCharacter]->pConditions[17] =pParty->uTimePlayed;
     pAudioPlayer->PlaySound((SoundID)(SOUND_GoldReceived|0x2), -1, 0, -1, 0, 0, 0, 0);
     pPlayers[uActiveCharacter]->PlaySound(SPEECH_82, 0);
     pOtherOverlayList->_4418B1(20, uActiveCharacter + 99, 0, 65536);
-    pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 1, v25);
+    pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 1, 0);
     return;
   }
   //---------------------------------------------------
   if ( dialog_menu_id == HOUSE_DIALOGUE_TEMPLE_DONATE )
   {
-      v24 = p2DEvents[(unsigned int)window_SpeakInHouse->ptr_1C - 1].fPriceMultiplier;
-      v25 = 0;
-      if ( pParty->uNumGold >= (unsigned int)(signed __int64)v24 )
+    pPrice = p2DEvents[(unsigned int)window_SpeakInHouse->ptr_1C - 1].fPriceMultiplier;
+    if ( pParty->uNumGold >= (unsigned int)pPrice )
+    {
+      Party::TakeGold((unsigned int)pPrice);
+      v26 = &pOutdoor->ddm;
+      if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor )
+        v26 = &pIndoor->dlv;
+      if ( v26->uReputation > -5 )
       {
-        Party::TakeGold((signed __int64)v24);
-        v26 = &pOutdoor->ddm;
-        if ( uCurrentlyLoadedLevelType != LEVEL_Outdoor )
-          v26 = &pIndoor->dlv;
-        v27 = v26->uReputation;
-        //v66 = v26;
-        if ( v27 > -5 )
+        v26->uReputation = v26->uReputation - 1;
+        if ( v26->uReputation - 1 < -5 )
+          v26->uReputation = -5;
+      }
+      if ( (unsigned __int8)byte_F8B1EF[uActiveCharacter] == pParty->uDaysPlayed % 7 )
+      {
+        if ( v26->uReputation <= -5 )
         {
-          v28 = v27 - 1;
-          v26->uReputation = v28;
-          if ( v28 < -5 )
-            v26->uReputation = -5;
+          v30 = pParty->uDaysPlayed % 7 + 1;
+          LOBYTE(v30) = v30 | 0x80;
+          _42777D_CastSpell_UseWand_ShootArrow(SPELL_AIR_WIZARD_EYE, uActiveCharacter - 1, v30, 48, 0);
         }
-        if ( (unsigned __int8)byte_F8B1EF[uActiveCharacter] == pParty->uDaysPlayed % 7 )
+        if ( v26->uReputation <= -10 )
         {
-          if ( v26->uReputation <= -5 )
-          {
-            v30 = pParty->uDaysPlayed % 7 + 1;
-            LOBYTE(v30) = v30 | 0x80;
-            _42777D_CastSpell_UseWand_ShootArrow(SPELL_AIR_WIZARD_EYE, uActiveCharacter - 1, v30, 48, 0);
-          }
-          if ( v26->uReputation <= -10 )
-          {
-            v31 = pParty->uDaysPlayed % 7 + 1;
-            LOBYTE(v31) = v31 | 0x80;
-            _42777D_CastSpell_UseWand_ShootArrow(SPELL_SPIRIT_PRESERVATION, uActiveCharacter - 1, v31, 48, 0);
-            //v26 = v66;
-          }
-          if ( v26->uReputation <= -15 )
-          {
-            v32 = pParty->uDaysPlayed % 7 + 1;
-            LOBYTE(v32) = v32 | 0x80;
-            _42777D_CastSpell_UseWand_ShootArrow(SPELL_BODY_PROTECTION_FROM_MAGIC, uActiveCharacter - 1, v32, 48, 0);
-            //v26 = v66;
-          }
-          if ( v26->uReputation <= -20 )
-          {
-            v33 = pParty->uDaysPlayed % 7 + 1;
-            LOBYTE(v33) = v33 | 0x80;
-            _42777D_CastSpell_UseWand_ShootArrow(SPELL_LIGHT_HOUR_OF_POWER, uActiveCharacter - 1, v33, 48, 0);
-            //v26 = v66;
-          }
-          if ( v26->uReputation <= -25 )
-          {
-            v34 = pParty->uDaysPlayed % 7 + 1;
-            LOBYTE(v34) = v34 | 0x80;
-            _42777D_CastSpell_UseWand_ShootArrow(SPELL_LIGHT_DAY_OF_PROTECTION, uActiveCharacter - 1, v34, 48, 0);
-          }
+          v30 = pParty->uDaysPlayed % 7 + 1;
+          LOBYTE(v30) = v30 | 0x80;
+          _42777D_CastSpell_UseWand_ShootArrow(SPELL_SPIRIT_PRESERVATION, uActiveCharacter - 1, v30, 48, 0);
+        }
+        if ( v26->uReputation <= -15 )
+        {
+          v30 = pParty->uDaysPlayed % 7 + 1;
+          LOBYTE(v30) = v30 | 0x80;
+          _42777D_CastSpell_UseWand_ShootArrow(SPELL_BODY_PROTECTION_FROM_MAGIC, uActiveCharacter - 1, v30, 48, 0);
+        }
+        if ( v26->uReputation <= -20 )
+        {
+          v30 = pParty->uDaysPlayed % 7 + 1;
+          LOBYTE(v30) = v30 | 0x80;
+          _42777D_CastSpell_UseWand_ShootArrow(SPELL_LIGHT_HOUR_OF_POWER, uActiveCharacter - 1, v30, 48, 0);
         }
-        ++byte_F8B1EF[uActiveCharacter];
-        pPlayers[uActiveCharacter]->PlaySound(SPEECH_83, 0);
-        ShowStatusBarString(pGlobalTXT_LocalizationStrings[527], 2); // "Thank You!"
-        pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 1, v25);
-        return;
+        if ( v26->uReputation <= -25 )
+        {
+          v30 = pParty->uDaysPlayed % 7 + 1;
+          LOBYTE(v30) = v30 | 0x80;
+          _42777D_CastSpell_UseWand_ShootArrow(SPELL_LIGHT_DAY_OF_PROTECTION, uActiveCharacter - 1, v30, 48, 0);
+        }
       }
-      ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2);
-      PlayHouseSound((unsigned int)window_SpeakInHouse->ptr_1C, HouseSound_NotEnoughMoney_TrainingSuccessful);
-      pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 1, v25);
+      ++byte_F8B1EF[uActiveCharacter];
+      pPlayers[uActiveCharacter]->PlaySound(SPEECH_83, 0);
+      ShowStatusBarString(pGlobalTXT_LocalizationStrings[527], 2); // "Thank You!"
+      pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 1, 0);
       return;
+    }
+    ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2);//"У вас не хватает золота"
+    PlayHouseSound((unsigned int)window_SpeakInHouse->ptr_1C, HouseSound_NotEnoughMoney_TrainingSuccessful);
+    pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 1, 0);
+    return;
   }
   //------------------------------------------------
   if ( dialog_menu_id == HOUSE_DIALOGUE_LEARN_SKILLS )
   {
     if ( HouseUI_CheckIfPlayerCanInteract() )
     {
-      //v61 = pDialogueWindow;
       all_text_height = 0;
       pCurrentItem = (signed __int64)(p2DEvents[(signed int)window_SpeakInHouse->ptr_1C - 1].flt_24 * 500.0);
       v64 = (signed int)(pCurrentItem * (100 - pPlayers[uActiveCharacter]->GetMerchant())) / 100;
       if ( v64 < (signed int)pCurrentItem / 3 )
         v64 = (signed int)pCurrentItem / 3;
       pCurrentItem = 0;
-      //if ( (signed int)pDialogueWindow->pStartingPosActiveItem >= v8 )
-      //goto LABEL_78;
-      for ( v62 = pDialogueWindow->pStartingPosActiveItem; (signed int)v62 < pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem; ++v62 )
+      for ( int i = pDialogueWindow->pStartingPosActiveItem; i < pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem; ++i )
       {
-        v9 = pDialogueWindow->GetControl(v62)->msg_param - 36;
-        if ( byte_4ED970_skill_learn_ability_by_class_table[pPlayers[uActiveCharacter]->classType][v9] && !pPlayers[uActiveCharacter]->pActiveSkills[v9] )
+        if ( byte_4ED970_skill_learn_ability_by_class_table[pPlayers[uActiveCharacter]->classType][pDialogueWindow->GetControl(i)->msg_param - 36]
+         && !pPlayers[uActiveCharacter]->pActiveSkills[pDialogueWindow->GetControl(i)->msg_param - 36] )
         {
-          all_text_height += pFontArrus->CalcTextHeight(pSkillNames[v9], &tample_window, 0, 0);
-          //v66 = (DDM_DLV_Header *)((char *)v66 + pTextHeight);
+          all_text_height += pFontArrus->CalcTextHeight(pSkillNames[pDialogueWindow->GetControl(i)->msg_param - 36], &tample_window, 0, 0);
           ++pCurrentItem;
         }
-        v11 = pDialogueWindow->pStartingPosActiveItem;
       }
       if ( pCurrentItem )
       {
@@ -3077,55 +2931,42 @@
         v64 = (149 - (signed int)all_text_height) / (signed int)pCurrentItem;
         if ( v64 > 32 )
           v64 = 32;
-        pCurrentItem = (signed int)(149 - pCurrentItem * v64 - (int)all_text_height) / 2 - v64 / 2 + 162;
-        v12 = pDialogueWindow;
-        result = pDialogueWindow->pStartingPosActiveItem;
-        v13 = result + pDialogueWindow->pNumPresenceButton;
-        v62 = pDialogueWindow->pStartingPosActiveItem;
-        if ( result < v13 )
+        all_text_height = (signed int)(149 - pCurrentItem * v64 - (int)all_text_height) / 2 - v64 / 2 + 162;
+        if ( pDialogueWindow->pStartingPosActiveItem < pDialogueWindow->pStartingPosActiveItem + pDialogueWindow->pNumPresenceButton )
         {
-          all_text_height = 2;
-          while ( 1 )
+          pCurrentItem = 2;
+          for ( int i = pDialogueWindow->pStartingPosActiveItem;
+                    i < pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem; ++i )
           {
-            v14 = v12->GetControl(v62);
-            v15 = v14;
-            v16 = v14->msg_param - 36;
-            if ( !byte_4ED970_skill_learn_ability_by_class_table[pPlayers[uActiveCharacter]->classType][v16] || pPlayers[uActiveCharacter]->pActiveSkills[v16] )
+            pButton = pDialogueWindow->GetControl(i);
+            if ( !byte_4ED970_skill_learn_ability_by_class_table[pPlayers[uActiveCharacter]->classType][pButton->msg_param - 36]
+              || pPlayers[uActiveCharacter]->pActiveSkills[pButton->msg_param - 36] )
             {
-              v15->uW = 0;
-              v15->uHeight = 0;
-              v15->uY = 0;
+              pButton->uW = 0;
+              pButton->uHeight = 0;
+              pButton->uY = 0;
             }
             else
             {
-              v15->uY = v64 + pCurrentItem;
-              pTextHeight = pFontArrus->CalcTextHeight(pSkillNames[v16], &tample_window, 0, 0);
-              v19 = v15->uY;
-              v15->uHeight = pTextHeight;
-              v20 = v19 + pTextHeight - 1;
-              v15->uW = v20;
-              pCurrentItem = v20;
+              pButton->uY = v64 + all_text_height;
+              pTextHeight = pFontArrus->CalcTextHeight(pSkillNames[pButton->msg_param - 36], &tample_window, 0, 0);
+              pButton->uHeight = pTextHeight;
+              pButton->uW = pButton->uY + pTextHeight - 1;
+              all_text_height = pButton->uW;
               pTextColor = TargetColor(0xFFu, 0xFFu, 0x9Bu);
-              if ( pDialogueWindow->pCurrentPosActiveItem != all_text_height )
+              if ( pDialogueWindow->pCurrentPosActiveItem != pCurrentItem )
                 pTextColor = TargetColor(0xFFu, 0xFFu, 0xFFu);
-              tample_window.DrawTitleText(pFontArrus, 0, v19, pTextColor, pSkillNames[v16], 3);
+              tample_window.DrawTitleText(pFontArrus, 0, pButton->uY, pTextColor, pSkillNames[pButton->msg_param - 36], 3);
             }
-            result = (int)pDialogueWindow;
-            ++v62;
-            //v66 = (DDM_DLV_Header *)((char *)v66 + 1);
-	        all_text_height++;
-            if ( (signed int)v62 >= pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem )
-              break;
-            v12 = pDialogueWindow;
+            pCurrentItem++;
           }
         }
       }
       else
       {
-LABEL_78:
-        sprintf(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[544], pPlayers[uActiveCharacter]->pName, pClassNames[pPlayers[uActiveCharacter]->classType]);
+        sprintf(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[544], pPlayers[uActiveCharacter]->pName, pClassNames[pPlayers[uActiveCharacter]->classType]);//"Советую вам %s %s поискать знания еще где-нибудь"
         strcat(pTmpBuf.data(), "\n \n");
-        strcat(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[528]);
+        strcat(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[528]);//"Больше ничего не могу предложить."
         pTextHeight = pFontArrus->CalcTextHeight(pTmpBuf.data(), &tample_window, 0, 0);
         tample_window.DrawTitleText(pFontArrus, 0, (174 - pTextHeight) / 2 + 138, TargetColor(0xFFu, 0xFFu, 0x9Bu), pTmpBuf.data(), 3);
       }
@@ -3137,250 +2978,148 @@
 //----- (004B4710) --------------------------------------------------------
 void TrainingDialog()
 {
-  //Player *v0; // ebx@1
-  int color2; // eax@1
-  //unsigned int v2; // ecx@1
-  //int v3; // eax@1
-  //signed int v4; // edx@1
   unsigned __int64 v5; // edi@3
-  //unsigned int v6; // esi@3
-  //void *v7; // ecx@3
   int v8; // edx@4
   double v9; // st7@6
   signed int v10; // esi@6
-  int v11; // ecx@6
-  //int result; // eax@9
-  GUIWindow *v13; // edi@14
+  int pPrice; // ecx@6
   signed int v14; // esi@14
-  unsigned int v15; // esi@16
+  //unsigned int v15; // esi@16
   int v16; // eax@16
-  unsigned int v17; // eax@17
-  int v18; // eax@19
+  //unsigned int v17; // eax@17
   int v19; // ecx@24
-  GUIButton *v20; // eax@26
-  GUIButton *v21; // esi@26
-  int v22; // eax@26
-  const char *v23; // eax@28
-  int v24; // eax@28
-  unsigned int v25; // ecx@28
-  int v26; // eax@28
-  unsigned __int16 v27; // ax@28
-  //int v28; // eax@32
-  unsigned __int16 v29; // ST14_2@34
-  int v30; // eax@34
-  //const char *v31; // ST18_4@36
-  //unsigned __int16 v32; // ST14_2@36
+  //GUIButton *v20; // eax@26
+  //GUIButton *v21; // esi@26
+  //int v22; // eax@26
+  //const char *v23; // eax@28
+  //int v24; // eax@28
+  //unsigned int v25; // ecx@28
+  //int v26; // eax@28
+  //unsigned __int16 v27; // ax@28
+  //unsigned __int16 v29; // ST14_2@34
+  //int v30; // eax@34
   int v33; // eax@36
-  int v34; // eax@37
-  unsigned int v35; // edi@38
   unsigned int v36; // eax@38
-  //int v37; // ecx@41
-  //char *v38; // eax@41
-  //int *v39; // eax@45
-  unsigned int v40; // eax@46
-  //void *v41; // ecx@46
   unsigned int v42; // eax@46
-  GUIWindow *v43; // ecx@59
-  int v44; // edx@59
-  char **v45; // esi@60
-  //int v46; // eax@62
-  int v47; // eax@68
-  //int v48; // edx@69
+  int index;
+  int all_text_height; // eax@68
   int v49; // ebx@69
-  //unsigned __int8 v50; // sf@69
-  char **v51; // edi@70
-  GUIButton *v52; // eax@71
-  GUIButton *v53; // esi@71
-  int v54; // eax@71
-  unsigned int v55; // ecx@71
-  int v56; // eax@71
-  unsigned __int16 v57; // ax@71
-  unsigned __int16 v58; // [sp-Ch] [bp-90h]@38
-  //const char *v59; // [sp-Ch] [bp-90h]@63
-  char *v60; // [sp-8h] [bp-8Ch]@38
-  //char *v61; // [sp-8h] [bp-8Ch]@63
-  unsigned int v62; // [sp-4h] [bp-88h]@38
-  int v63; // [sp-4h] [bp-88h]@52
-  //char *v64; // [sp-4h] [bp-88h]@63
-  GUIWindow v65; // [sp+Ch] [bp-78h]@1
-  //__int64 v66; // [sp+60h] [bp-24h]@3
-  unsigned int white; // [sp+68h] [bp-1Ch]@1
-  int v68; // [sp+6Ch] [bp-18h]@3
+  GUIButton *pButton; // eax@71
+  int pTextHeight; // eax@71
+  unsigned __int16 pTextColor; // ax@71
+  GUIWindow training_dialog_window; // [sp+Ch] [bp-78h]@1
+  //int v68; // [sp+6Ch] [bp-18h]@3
   int v69; // [sp+70h] [bp-14h]@6
-  //unsigned int i; // [sp+74h] [bp-10h]@1
-  //int v71; // [sp+78h] [bp-Ch]@1
-  int v72; // [sp+7Ch] [bp-8h]@16
   int v73; // [sp+80h] [bp-4h]@14
 
-  //v0 = pPlayers[uActiveCharacter];
-  memcpy(&v65, window_SpeakInHouse, sizeof(v65));
-  v65.uFrameX = 483;
-  v65.uFrameWidth = 148;
-  v65.uFrameZ = 334;
-  white = TargetColor(255, 255, 255);
-  color2 = TargetColor(0xE1u, 0xCDu, 0x23u);
-  //v71 = color2;
-  //v2 = v0->uLevel;
-  //v3 = 0;
-  //v4 = 0;
-  //for ( i = v2; v4 < (signed int)v2; ++v4 )
-  //  v3 += v4 + 1;
-  //v5 = 1000 * v3;
+  memcpy(&training_dialog_window, window_SpeakInHouse, sizeof(training_dialog_window));
+  training_dialog_window.uFrameX = 483;
+  training_dialog_window.uFrameWidth = 148;
+  training_dialog_window.uFrameZ = 334;
   v5 = 1000ui64 * pPlayers[uActiveCharacter]->uLevel * (pPlayers[uActiveCharacter]->uLevel + 1) / 2;  // E n = n(n + 1) / 2
-  //v6 = HIDWORD(v0->uExperience);
-  //v7 = window_SpeakInHouse->ptr_1C;
-  v68 = pMaxLevelPerTrainingHallType[(unsigned int)window_SpeakInHouse->ptr_1C - HOUSE_TRAINING_HALL_EMERALD_ISLE];
-  //v66 = 1000 * v3;
+  //v68 = pMaxLevelPerTrainingHallType[(unsigned int)window_SpeakInHouse->ptr_1C - HOUSE_TRAINING_HALL_EMERALD_ISLE];
   if (pPlayers[uActiveCharacter]->uExperience >= v5)
   {
     v8 = pPlayers[uActiveCharacter]->classType % 4 + 1;
     if ( v8 == 4 )
       v8 = 3;
     v9 = (double)pPlayers[uActiveCharacter]->uLevel;
-    //i = 0;
     v69 = v8;
-    //v10 = (signed __int64)(v9 * p2DEvents_minus1__20[13 * (signed int)v7] * (double)v8);
     v10 = (signed __int64)(v9 * p2DEvents[(signed int)window_SpeakInHouse->ptr_1C - 1].fPriceMultiplier * (double)v8);
-    v11 = v10 * (100 - pPlayers[uActiveCharacter]->GetMerchant()) / 100;
-    if ( v11 < v10 / 3 )
-      v11 = v10 / 3;
-    //i = v11;
+    pPrice = v10 * (100 - pPlayers[uActiveCharacter]->GetMerchant()) / 100;
+    if ( pPrice < v10 / 3 )
+      pPrice = v10 / 3;
   }
-
+//-------------------------------------------------------
+  all_text_height = 0;
   if (HouseUI_CheckIfPlayerCanInteract())
   {
-    if ( dialog_menu_id != HOUSE_DIALOGUE_MAIN )
+    if ( dialog_menu_id == HOUSE_DIALOGUE_MAIN )
     {
-      if ( dialog_menu_id != HOUSE_DIALOGUE_TRAININGHALL_TRAIN )
+      if (HouseUI_CheckIfPlayerCanInteract())
       {
-        if ( dialog_menu_id == HOUSE_DIALOGUE_LEARN_SKILLS )
+        index = 0;
+        pShopOptions[0] = pTmpBuf.data();
+        pShopOptions[1] = pGlobalTXT_LocalizationStrings[160];// "Learn Skills"
+        if ( pDialogueWindow->pStartingPosActiveItem < pDialogueWindow->pStartingPosActiveItem + pDialogueWindow->pNumPresenceButton )
         {
-          if (HouseUI_CheckIfPlayerCanInteract())
+          for ( int i = pDialogueWindow->pStartingPosActiveItem;
+                i < pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem; ++i )
           {
-            //i = 0;
-            int _v0 = 0;
-            v13 = pDialogueWindow;
-            //v14 = (signed __int64)(*(float *)&p2DEvents_minus1__24[13 * (unsigned int)ptr_507BC0->ptr_1C] * 500.0);
-            v14 = (signed __int64)(p2DEvents[(unsigned int)window_SpeakInHouse->ptr_1C - 1].flt_24 * 500.0);
-            v73 = v14 * (100 - pPlayers[uActiveCharacter]->GetMerchant()) / 100;
-            if ( v73 < v14 / 3 )
-              v73 = v14 / 3;
-            v15 = v13->pStartingPosActiveItem;
-            v16 = v13->pNumPresenceButton;
-            v72 = 0;
-            if ( (signed int)v15 >= (signed int)(v15 + v16) )
-              goto LABEL_76;
-            do
-            {
-              v17 = v13->GetControl(v15)->msg_param - 36;
-              if ( byte_4ED970_skill_learn_ability_by_class_table[pPlayers[uActiveCharacter]->classType][v17] && !pPlayers[uActiveCharacter]->pActiveSkills[v17] )
-              {
-                v18 = pFontArrus->CalcTextHeight(pSkillNames[v17], &v65, 0, 0);
-                _v0 += v18;
-                ++v72;
-              }
-              ++v15;
-            }
-            while ( (signed int)v15 < v13->pNumPresenceButton + v13->pStartingPosActiveItem );
-            if ( v72 )
+            if ( pDialogueWindow->GetControl(i)->msg_param == HOUSE_DIALOGUE_TRAININGHALL_TRAIN )
             {
-              sprintf(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[401], v73);// "Skill Cost: %lu"
-              v65.DrawTitleText(pFontArrus, 0, 0x92u, 0, pTmpBuf.data(), 3u);
-              v73 = (signed int)(149 - _v0) / v72;
-              if ( v73 > 32 )
-                v73 = 32;
-              //result = v13->pStartingPosActiveItem;
-              v19 = (signed int)(149 - v72 * v73 - _v0) / 2 - v73 / 2 + 162;
-              int _v1 = v13->pStartingPosActiveItem;
-              v68 = v19;
-              if (v13->pStartingPosActiveItem < v13->pStartingPosActiveItem + v13->pNumPresenceButton )
+              if (pPlayers[uActiveCharacter]->uLevel >= pMaxLevelPerTrainingHallType[(unsigned int)window_SpeakInHouse->ptr_1C - HOUSE_TRAINING_HALL_EMERALD_ISLE])
+                sprintfex(pShopOptions[index], "%s\n \n%s", pGlobalTXT_LocalizationStrings[536], pGlobalTXT_LocalizationStrings[529]); //"With your skills, you should be working here as a teacher."    "Sorry, but we are unable to train you."
+              else
               {
-                v72 = 2;
-                do
-                {
-                  v20 = v13->GetControl(_v1);
-                  v21 = v20;
-                  v22 = v20->msg_param - 36;
-                  if ( !byte_4ED970_skill_learn_ability_by_class_table[pPlayers[uActiveCharacter]->classType][v22] || pPlayers[uActiveCharacter]->pActiveSkills[v22] )
-                  {
-                    v21->uW = 0;
-                    v21->uHeight = 0;
-                    v21->uY = 0;
-                  }
-                  else
-                  {
-                    v23 = pSkillNames[v22];
-                    v21->uY = v73 + v68;
-                    //HIDWORD(v66) = (int)v23;
-                    v24 = pFontArrus->CalcTextHeight(v23, &v65, 0, 0);
-                    v25 = v21->uY;
-                    v21->uHeight = v24;
-                    v26 = v25 + v24 - 1;
-                    v21->uW = v26;
-                    v68 = v26;
-                    v27 = color2;
-                    if ( pDialogueWindow->pCurrentPosActiveItem != v72 )
-                      v27 = white;
-                    v65.DrawTitleText(pFontArrus, 0, v25, v27, v23, 3u);
-                  }
-                  ++_v1;
-                  ++v72;
-                }
-                while ( (signed int)_v1 < v13->pStartingPosActiveItem + v13->pNumPresenceButton );
+                if (pPlayers[uActiveCharacter]->uExperience < v5)
+                  sprintfex(pShopOptions[index], pGlobalTXT_LocalizationStrings[538], (uint)(v5 - pPlayers[uActiveCharacter]->uExperience), pPlayers[uActiveCharacter]->uLevel + 1); // "You need %d more experience to train to level %d"
+                else
+                  sprintfex(pShopOptions[index], pGlobalTXT_LocalizationStrings[537], pPlayers[uActiveCharacter]->uLevel + 1, pPrice); // "Train to level %d for %d gold"
               }
             }
-            else
-            {
-LABEL_76:
-              sprintf(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[544], pPlayers[uActiveCharacter]->pName, pClassNames[pPlayers[uActiveCharacter]->classType]);// 
-                                                // "Seek knowledge elsewhere %s the %s"
-              strcat(pTmpBuf.data(), "\n \n");
-              strcat(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[528]);// "I can offer you nothing further."
-              v29 = color2;
-              v30 = pFontArrus->CalcTextHeight(pTmpBuf.data(), &v65, 0, 0);
-              v65.DrawTitleText(pFontArrus, 0, (174 - v30) / 2 + 138, v29, pTmpBuf.data(), 3u);
-            }
+            all_text_height += pFontArrus->CalcTextHeight(pShopOptions[index], &training_dialog_window, 0, 0);
+            ++index;
           }
         }
-        return;
+        v49 = (2 * (87 - (174 - all_text_height) / 2) - all_text_height) / 2 - (174 - all_text_height) / 2 / 2 + 138;
+        if (pDialogueWindow->pStartingPosActiveItem < pDialogueWindow->pStartingPosActiveItem + pDialogueWindow->pNumPresenceButton)
+        {
+          //int pCurrentItem = 2;
+          index = 0;
+          for ( int i = pDialogueWindow->pStartingPosActiveItem;
+                i < pDialogueWindow->pStartingPosActiveItem + pDialogueWindow->pNumPresenceButton; ++i )
+          {
+            pButton = pDialogueWindow->GetControl(i);
+            pButton->uY = (174 - all_text_height) / 2 + v49;
+            pTextHeight = pFontArrus->CalcTextHeight(pShopOptions[index], &training_dialog_window, 0, 0);
+            pButton->uHeight = pTextHeight;
+            pButton->uW = pTextHeight + pButton->uY - 1;
+            v49 = pButton->uW;
+            pTextColor = TargetColor(0xE1u, 0xCDu, 0x23u);
+            if ( pDialogueWindow->pCurrentPosActiveItem != i )
+              pTextColor = TargetColor(255, 255, 255);
+            training_dialog_window.DrawTitleText(pFontArrus, 0, pButton->uY, pTextColor, pShopOptions[index], 3);
+            //++pCurrentItem;
+            ++index;
+          }
+        }
       }
+    }
+//------------------------------------------------------------------
+    if ( dialog_menu_id == HOUSE_DIALOGUE_TRAININGHALL_TRAIN )
+    {
       if ( !HouseUI_CheckIfPlayerCanInteract() )
       {
-        //v31 = pNPCTopics[122].pText;
-        //v32 = color2;
-        v33 = pFontArrus->CalcTextHeight(pNPCTopics[122].pText, &v65, 0, 0);
-        v65.DrawTitleText(pFontArrus, 0, (212 - v33) / 2 + 101, color2, pNPCTopics[122].pText, 3);
+        v33 = pFontArrus->CalcTextHeight(pNPCTopics[122].pText, &training_dialog_window, 0, 0);
+        training_dialog_window.DrawTitleText(pFontArrus, 0, (212 - v33) / 2 + 101, TargetColor(0xE1u, 0xCDu, 0x23u), pNPCTopics[122].pText, 3);
         pDialogueWindow->pNumPresenceButton = 0;
         return;
       }
-      v34 = pPlayers[uActiveCharacter]->uLevel;
-      if ( v34 < v68 )
+      //v34 = pPlayers[uActiveCharacter]->uLevel;
+      if ( pPlayers[uActiveCharacter]->uLevel < pMaxLevelPerTrainingHallType[(unsigned int)window_SpeakInHouse->ptr_1C - HOUSE_TRAINING_HALL_EMERALD_ISLE] )
       {
         if ( (signed __int64)pPlayers[uActiveCharacter]->uExperience >= v5 )
         {
-          if ( pParty->uNumGold >= v11)
+          if ( pParty->uNumGold >= pPrice)
           {
-            Party::TakeGold(v11);
+            Party::TakeGold(pPrice);
             PlayHouseSound((unsigned int)window_SpeakInHouse->ptr_1C, HouseSound_NotEnoughMoney_TrainingSuccessful);
             ++pPlayers[uActiveCharacter]->uLevel;
             pPlayers[uActiveCharacter]->uSkillPoints += pPlayers[uActiveCharacter]->uLevel / 10 + 5;
             pPlayers[uActiveCharacter]->sHealth = pPlayers[uActiveCharacter]->GetMaxHealth();
             pPlayers[uActiveCharacter]->sMana = pPlayers[uActiveCharacter]->GetMaxMana();
-
             uint max_level_in_party = player_levels[0];
             for (uint _it = 1; _it < 4; ++_it)
             {
               if (player_levels[_it] > max_level_in_party)
                 max_level_in_party = player_levels[_it];
             }
-
             ++player_levels[uActiveCharacter - 1];
             if (player_levels[uActiveCharacter - 1] > max_level_in_party) // if we reach new maximum party level
                                                                           // feature is broken thou, since this array is always zeroed in EnterHouse
             {
-              v40 = _494820_training_time(pParty->uCurrentHour);
-              //v41 = window_SpeakInHouse->ptr_1C;
-              v42 = 60 * (v40 + 4) - pParty->uCurrentMinute;
+              v42 = 60 * (_494820_training_time(pParty->uCurrentHour) + 4) - pParty->uCurrentMinute;
               if ((unsigned int)window_SpeakInHouse->ptr_1C == HOUSE_TRAINING_HALL_94 ||
                   (unsigned int)window_SpeakInHouse->ptr_1C == HOUSE_TRAINING_HALL_95)
                 v42 += 720;
@@ -3396,327 +3135,236 @@
             return;
           }
           ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2);// "You don't have enough gold"
-          v63 = 4;
-LABEL_55:
-          PlayHouseSound((unsigned int)window_SpeakInHouse->ptr_1C, (HouseSoundID)v63);
-//LABEL_56:
-          /*result = pMessageQueue_50CBD0->uNumMessages;
-          if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
-          {
-            pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = UIMSG_Escape;
-            pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 1;
-            result = 3 * pMessageQueue_50CBD0->uNumMessages + 3;
-            *(&pMessageQueue_50CBD0->uNumMessages + result) = 0;
-            ++pMessageQueue_50CBD0->uNumMessages;
-          }
-          return result;*/
+          PlayHouseSound((unsigned int)window_SpeakInHouse->ptr_1C, (HouseSoundID)4);
           pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 1, 0);
           return;
         }
-        sprintfex(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[538], (unsigned int)(v5 - pPlayers[uActiveCharacter]->uExperience), v34 + 1);// 
+        sprintfex(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[538], (unsigned int)(v5 - pPlayers[uActiveCharacter]->uExperience), pPlayers[uActiveCharacter]->uLevel + 1);// 
                                                 // "You need %d more experience to train to level %d"
-        v35 = 0;
-        v62 = 3;
-        v60 = pTmpBuf.data();
-        v58 = color2;
-        v36 = (212 - pFontArrus->CalcTextHeight(pTmpBuf.data(), &v65, 0, 0)) / 2 + 88;
+        v36 = (212 - pFontArrus->CalcTextHeight(pTmpBuf.data(), &training_dialog_window, 0, 0)) / 2 + 88;
       }
       else
       {
         sprintf(pTmpBuf.data(), "%s\n \n%s", pGlobalTXT_LocalizationStrings[536], pGlobalTXT_LocalizationStrings[529]);// 
                                                 // ""With your skills, you should be working here as a teacher.""
                                                 // ""Sorry, but we are unable to train you.""
-        v35 = 0;
-        v62 = 3;
-        v60 = pTmpBuf.data();
-        v58 = color2;
-        v36 = (212 - pFontArrus->CalcTextHeight(pTmpBuf.data(), &v65, 0, 0)) / 2 + 101;
+        v36 = (212 - pFontArrus->CalcTextHeight(pTmpBuf.data(), &training_dialog_window, 0, 0)) / 2 + 101;
       }
-      v65.DrawTitleText(pFontArrus, v35, v36, v58, v60, v62);
-      v63 = 3;
-      goto LABEL_55;
+      training_dialog_window.DrawTitleText(pFontArrus, 0, v36, TargetColor(0xE1u, 0xCDu, 0x23u), pTmpBuf.data(), 3);
+      PlayHouseSound((unsigned int)window_SpeakInHouse->ptr_1C, (HouseSoundID)3);
+      pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 1, 0);
+      return;
     }
-
+  }
+//-------------------------------------------------------------
+  if ( dialog_menu_id == HOUSE_DIALOGUE_LEARN_SKILLS )
+  {
     if (HouseUI_CheckIfPlayerCanInteract())
     {
-      v43 = pDialogueWindow;
-      v72 = 0;
-      pShopOptions[0] = pTmpBuf.data();
-      pShopOptions[1] = pGlobalTXT_LocalizationStrings[160];// "Learn Skills"
-      v44 = pDialogueWindow->pNumPresenceButton;
-      v73 = pDialogueWindow->pStartingPosActiveItem;
-      if ( v73 < v73 + v44 )
+      v14 = (signed __int64)(p2DEvents[(unsigned int)window_SpeakInHouse->ptr_1C - 1].flt_24 * 500.0);
+      pPrice = v14 * (100 - pPlayers[uActiveCharacter]->GetMerchant()) / 100;
+      if ( pPrice < v14 / 3 )
+        pPrice = v14 / 3;
+      index = 0;
+      for ( int i = pDialogueWindow->pStartingPosActiveItem;
+          (signed int)i < pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem; ++i )
       {
-        v45 = pShopOptions.data();
-        do
+        if ( byte_4ED970_skill_learn_ability_by_class_table[pPlayers[uActiveCharacter]->classType][pDialogueWindow->GetControl(i)->msg_param - 36]
+             && !pPlayers[uActiveCharacter]->pActiveSkills[pDialogueWindow->GetControl(i)->msg_param - 36] )
         {
-          if ( v43->GetControl(v73)->msg_param == HOUSE_DIALOGUE_TRAININGHALL_TRAIN )
+          all_text_height += pFontArrus->CalcTextHeight(pSkillNames[pDialogueWindow->GetControl(i)->msg_param - 36], &training_dialog_window, 0, 0);
+          ++index;
+        }
+      }
+      if ( index )
+      {
+        sprintf(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[401], pPrice);// "Skill Cost: %lu"
+        training_dialog_window.DrawTitleText(pFontArrus, 0, 0x92u, 0, pTmpBuf.data(), 3);
+        v73 = (signed int)(149 - all_text_height) / index;
+        if ( v73 > 32 )
+          v73 = 32;
+        v19 = (signed int)(149 - index * v73 - all_text_height) / 2 - v73 / 2 + 162;
+        for ( int i = pDialogueWindow->pStartingPosActiveItem;
+             (signed int)i < pDialogueWindow->pStartingPosActiveItem + pDialogueWindow->pNumPresenceButton; ++i )
+        {
+          pButton = pDialogueWindow->GetControl(i);
+          if ( !byte_4ED970_skill_learn_ability_by_class_table[pPlayers[uActiveCharacter]->classType][pButton->msg_param - 36]
+              || pPlayers[uActiveCharacter]->pActiveSkills[pButton->msg_param - 36] )
           {
-            //v46 = pPlayers[uActiveCharacter]->uLevel;
-            if (pPlayers[uActiveCharacter]->uLevel >= v68)
-              sprintfex(*v45, "%s\n \n%s",
-                        pGlobalTXT_LocalizationStrings[536], pGlobalTXT_LocalizationStrings[529]); //"With your skills, you should be working here as a teacher."    "Sorry, but we are unable to train you."
-            else
-            {
-              if (pPlayers[uActiveCharacter]->uExperience < v5)
-                sprintfex(*v45, pGlobalTXT_LocalizationStrings[538],  // "You need %d more experience to train to level %d"
-                          (uint)(v5 - pPlayers[uActiveCharacter]->uExperience), pPlayers[uActiveCharacter]->uLevel + 1);
-              else
-                sprintfex(*v45, pGlobalTXT_LocalizationStrings[537],  // "Train to level %d for %d gold"
-                          pPlayers[uActiveCharacter]->uLevel + 1, v11);
-            }
+            pButton->uW = 0;
+            pButton->uHeight = 0;
+            pButton->uY = 0;
           }
-          v47 = pFontArrus->CalcTextHeight(*v45, &v65, 0, 0);
-          v43 = pDialogueWindow;
-          v72 += v47;
-          ++v45;
-          ++v73;
+          else
+          {
+            pButton->uY = v73 + v19;
+            pTextHeight = pFontArrus->CalcTextHeight(pSkillNames[pButton->msg_param - 36], &training_dialog_window, 0, 0);
+            pButton->uHeight = pTextHeight;
+            pButton->uW = pButton->uY + pTextHeight - 1;
+            v19 = pButton->uY + pTextHeight - 1;
+            pTextColor = TargetColor(0xE1u, 0xCDu, 0x23u);
+            if ( pDialogueWindow->pCurrentPosActiveItem != i )
+              pTextColor = TargetColor(255, 255, 255);
+            training_dialog_window.DrawTitleText(pFontArrus, 0, pButton->uY, pTextColor, pSkillNames[pButton->msg_param - 36], 3);
+          }
         }
-        while ( v73 < pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem );
       }
-
-      v49 = (2 * (87 - (174 - v72) / 2) - v72) / 2 - (174 - v72) / 2 / 2 + 138;
-      v73 = v43->pStartingPosActiveItem;
-      if (v43->pStartingPosActiveItem < v43->pStartingPosActiveItem + v43->pNumPresenceButton)
+      else
       {
-        int _v3 = 2;
-        v51 = pShopOptions.data();
-        do
-        {
-          v52 = v43->GetControl(v73);
-          v53 = v52;
-          v52->uY = (174 - v72) / 2 + v49;
-          v54 = pFontArrus->CalcTextHeight(*v51, &v65, 0, 0);
-          v55 = v53->uY;
-          v53->uHeight = v54;
-          v56 = v54 + v55 - 1;
-          v53->uW = v56;
-          v49 = v56;
-          v57 = color2;
-          if ( pDialogueWindow->pCurrentPosActiveItem != _v3 )
-            v57 = white;
-          v65.DrawTitleText(pFontArrus, 0, v55, v57, *v51, 3u);
-          v43 = pDialogueWindow;
-          ++_v3;
-          ++v51;
-          ++v73;
-        }
-        while ( v73 < pDialogueWindow->pStartingPosActiveItem + pDialogueWindow->pNumPresenceButton);
+        sprintf(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[544], pPlayers[uActiveCharacter]->pName, pClassNames[pPlayers[uActiveCharacter]->classType]);// 
+                                              // "Seek knowledge elsewhere %s the %s"
+        strcat(pTmpBuf.data(), "\n \n");
+        strcat(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[528]);// "I can offer you nothing further."
+        pTextHeight = pFontArrus->CalcTextHeight(pTmpBuf.data(), &training_dialog_window, 0, 0);
+        training_dialog_window.DrawTitleText(pFontArrus, 0, (174 - pTextHeight) / 2 + 138, TargetColor(0xE1u, 0xCDu, 0x23u), pTmpBuf.data(), 3);
       }
     }
   }
+  return;
 }
 
 //----- (004B6478) --------------------------------------------------------
 void sub_4B6478()
-    {
-  GUIWindow *v0; // ebx@1
-  Player *v1; // edi@1
+{
   unsigned int v2; // eax@1
   signed int v3; // esi@1
-  int v4; // ebx@1
+  int pPrice; // ebx@1
   unsigned int v5; // esi@5
   int v6; // edi@6
   int result; // eax@13
-  GUIWindow *v8; // ebx@17
-  int v9; // eax@17
-  int v10; // ecx@17
-  unsigned int v11; // ecx@18
   int v12; // eax@20
   int v13; // eax@21
-  GUIButton *v14; // esi@27
-  int v15; // ecx@27
+  GUIButton *pButton; // esi@27
   unsigned int v16; // eax@28
-  const char *v17; // ebx@29
-  int v18; // eax@29
-  unsigned int v19; // ecx@29
-  int v20; // eax@29
-  unsigned __int16 v21; // ax@29
+  int pTextHeight; // eax@29
+  unsigned __int16 pTextColor; // ax@29
   unsigned __int16 v22; // ST14_2@36
-  int v23; // eax@36
-  const char *v24; // ST18_4@37
-  unsigned __int16 v25; // ST14_2@37
-  int v26; // eax@37
   int v27; // [sp-4h] [bp-80h]@8
-  GUIWindow v28; // [sp+Ch] [bp-70h]@1
-  GUIWindow *v29; // [sp+60h] [bp-1Ch]@17
-  unsigned int v30; // [sp+64h] [bp-18h]@1
-  int v31; // [sp+68h] [bp-14h]@1
+  GUIWindow dialog_window; // [sp+Ch] [bp-70h]@1
   int v32; // [sp+6Ch] [bp-10h]@1
-  int v33; // [sp+70h] [bp-Ch]@17
   int v34; // [sp+74h] [bp-8h]@17
-  int v35; // [sp+78h] [bp-4h]@17
 
-  v0 = window_SpeakInHouse;
-  memcpy(&v28, window_SpeakInHouse, sizeof(v28));
-  v1 = pPlayers[uActiveCharacter];
-  v28.uFrameX = 483;
-  v28.uFrameWidth = 148;
-  v28.uFrameZ = 334;
-  v30 = TargetColor(0xFFu, 0xFFu, 0xFFu);
-  v31 = TargetColor(0xFFu, 0xFFu, 0x9Bu);
-  v2 = 52 * (unsigned int)v0->ptr_1C;
-  //v32 = (unsigned __int8)(((p2DEvents_minus1___00[v2 / 2] != 18) - 1) & 0x96) + 100;
-  v32 = (unsigned __int8)(((p2DEvents[(unsigned int)v0->ptr_1C - 1].uType != 18) - 1) & 0x96) + 100;
-  //v3 = (signed __int64)((double)v32 * p2DEvents_minus1__20[v2 / 4]);
-  v3 = (signed __int64)((double)v32 * p2DEvents[(unsigned int)v0->ptr_1C - 1].fPriceMultiplier);
-  v4 = v3 * (100 - v1->GetMerchant()) / 100;
-  v32 = v4;
-  if ( v4 < v3 / 3 )
-  {
-    v4 = v3 / 3;
-    v32 = v3 / 3;
-  }
-  if ( dialog_menu_id != HOUSE_DIALOGUE_MAIN)
+  memcpy(&dialog_window, window_SpeakInHouse, sizeof(dialog_window));
+  dialog_window.uFrameX = 483;
+  dialog_window.uFrameWidth = 148;
+  dialog_window.uFrameZ = 334;
+  v2 = 52 * (unsigned int)window_SpeakInHouse->ptr_1C;
+  v32 = (unsigned __int8)(((p2DEvents[(unsigned int)window_SpeakInHouse->ptr_1C - 1].uType != 18) - 1) & 0x96) + 100;
+  v3 = (signed __int64)((double)v32 * p2DEvents[(unsigned int)window_SpeakInHouse->ptr_1C - 1].fPriceMultiplier);
+  pPrice = v3 * (100 - pPlayers[uActiveCharacter]->GetMerchant()) / 100;
+  if ( pPrice < v3 / 3 )
+    pPrice = v3 / 3;
+  if ( dialog_menu_id == HOUSE_DIALOGUE_MAIN)
   {
-    if ( HouseUI_CheckIfPlayerCanInteract() )
+    if ( !(unsigned __int16)_449B57_test_bit((unsigned __int8 *)pPlayers[uActiveCharacter]->_achieved_awards_bits, word_4F0754[2 * (unsigned int)window_SpeakInHouse->ptr_1C]) )
+    {
+      pTextHeight = pFontArrus->CalcTextHeight(pNPCTopics[171].pText, &dialog_window, 0, 0);//
+      dialog_window.DrawTitleText(pFontArrus, 0, (212 - pTextHeight) / 2 + 101, TargetColor(0xFFu, 0xFFu, 0x9Bu), pNPCTopics[171].pText, 3);
+      pDialogueWindow->pNumPresenceButton = 0;
+      return;
+    }
+    if ( !HouseUI_CheckIfPlayerCanInteract() )
+      return;
+    v34 = 0;
+    for ( int i = pDialogueWindow->pStartingPosActiveItem;
+          i < pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem; ++i )
+    {
+      if ( byte_4ED970_skill_learn_ability_by_class_table[pPlayers[uActiveCharacter]->classType / 3][pDialogueWindow->GetControl(i)->msg_param - 36]
+         && !pPlayers[uActiveCharacter]->pActiveSkills[pDialogueWindow->GetControl(i)->msg_param - 36] )
+      {
+        v12 += pFontArrus->CalcTextHeight(pSkillNames[pDialogueWindow->GetControl(i)->msg_param - 36], &dialog_window, 0, 0);
+        ++v34;
+      }
+    }
+    if ( !v34 )
     {
-      v5 = 0;
-
-      __debugbreak();
-      //pSkillAvailabilityPerClass[8 + v58->uClass][4 + v23]
-      // or
-      //byte_4ED970_skill_learn_ability_by_class_table[v58->uClass][v23 - 36]
-      // or
-      //byte_4ED970_skill_learn_ability_by_class_table[v58->uClass - 1][v23 + 1]
-      __debugbreak(); // whacky condition - fix
-      if (false
-      //if ( !*(&byte_4ED94C[37 * v1->uClass / 3] + dword_F8B19C)
-        || (v6 = (int)(&v1->uIntelligence + dialog_menu_id), *(short *)v6) )
+      sprintf(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[544], pPlayers[uActiveCharacter]->pName, pClassNames[pPlayers[uActiveCharacter]->classType]);
+      strcat(pTmpBuf.data(), "\n \n");
+      strcat(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[528]);//Больше ничего не могу предложить.
+      pTextHeight = pFontArrus->CalcTextHeight(pTmpBuf.data(), &dialog_window, 0, 0);
+      dialog_window.DrawTitleText(pFontArrus, 0, (174 - pTextHeight) / 2 + 138, TargetColor(0xFFu, 0xFFu, 0x9Bu), pTmpBuf.data(), 3);
+      return; 
+    }
+    sprintf(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[401], pPrice);//Стоимость навыка: %lu
+    dialog_window.DrawTitleText(pFontArrus, 0, 0x92u, 0, pTmpBuf.data(), 3);
+    v32 = (149 - v12) / v34;
+    if ( (149 - v12) / v34 > 32 )
+      v32 = 32;
+    v34 = (149 - v34 * v32 - v12) / 2 - v32 / 2 + 162;
+    if ( pDialogueWindow->pStartingPosActiveItem < pDialogueWindow->pStartingPosActiveItem + pDialogueWindow->pNumPresenceButton )
+    {
+      for ( int i = pDialogueWindow->pStartingPosActiveItem;
+            i <pDialogueWindow->pNumPresenceButton + pDialogueWindow->pStartingPosActiveItem; ++i )
       {
-        pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
-      }
-      else
-      {
-        if ( pParty->uNumGold < v4 )
+        pButton = pDialogueWindow->GetControl(i);
+        if ( byte_4ED970_skill_learn_ability_by_class_table[pPlayers[uActiveCharacter]->classType / 3][pButton->msg_param - 36] )
         {
-          ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2u);
-          v27 = 4;
+          if ( !pPlayers[uActiveCharacter]->pActiveSkills[pButton->msg_param - 36] )
+          {
+            pButton->uY = v32 + v34;
+            pTextHeight = pFontArrus->CalcTextHeight(pSkillNames[pButton->msg_param - 36], &dialog_window, 0, 0);
+            pButton->uHeight = pTextHeight;
+            pButton->uW = pButton->uY + pTextHeight - 1;
+            v34 = pButton->uY + pTextHeight - 1;
+            pTextColor = TargetColor(0xFFu, 0xFFu, 0x9Bu);
+            if ( pDialogueWindow->pCurrentPosActiveItem != i )
+              pTextColor = TargetColor(0xFFu, 0xFFu, 0xFFu);
+            dialog_window.DrawTitleText(pFontArrus, 0, pButton->uY, pTextColor, pSkillNames[pButton->msg_param - 36], 3);
+          }
         }
         else
         {
-          Party::TakeGold(v4);
-          *(short *)v6 = 1;
-          v27 = 2;
+          pButton->uW = 0;
+          pButton->uHeight = 0;
+          pButton->uY = 0;
         }
-        PlayHouseSound((unsigned int)window_SpeakInHouse->ptr_1C, (HouseSoundID)v27);
       }
     }
+  return;
+  }
+
+  if ( HouseUI_CheckIfPlayerCanInteract() )
+  {
+    v5 = 0;
+    __debugbreak();
+    //pSkillAvailabilityPerClass[8 + v58->uClass][4 + v23]
+    // or
+    //byte_4ED970_skill_learn_ability_by_class_table[v58->uClass][v23 - 36]
+    // or
+    //byte_4ED970_skill_learn_ability_by_class_table[v58->uClass - 1][v23 + 1]
+    __debugbreak(); // whacky condition - fix
+    if (false
+    //if ( !*(&byte_4ED94C[37 * v1->uClass / 3] + dword_F8B19C)
+      || (v6 = (int)(&pPlayers[uActiveCharacter]->uIntelligence + dialog_menu_id), *(short *)v6) )
+    {
+      pAudioPlayer->PlaySound(SOUND_27, 0, 0, -1, 0, 0, 0, 0);
+    }
     else
     {
-      v5 = 0;
-    }
-    /*result = pMessageQueue_50CBD0->uNumMessages;
-    if ( (signed int)pMessageQueue_50CBD0->uNumMessages < 40 )
-    {
-      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].eType = UIMSG_Escape;
-      pMessageQueue_50CBD0->pMessages[pMessageQueue_50CBD0->uNumMessages].param = 1;
-      result = 3 * pMessageQueue_50CBD0->uNumMessages + 3;
-      *(&pMessageQueue_50CBD0->uNumMessages + result) = v5;
-      ++pMessageQueue_50CBD0->uNumMessages;
-    }*/
-    pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 1, v5);
-    return; // void func
-  }
-  if ( !(unsigned __int16)_449B57_test_bit((unsigned __int8 *)v1->_achieved_awards_bits, word_4F0754[2 * (unsigned int)window_SpeakInHouse->ptr_1C]) )
-  {
-    v24 = pNPCTopics[171].pText;
-    v25 = v31;
-    v26 = pFontArrus->CalcTextHeight(pNPCTopics[171].pText, &v28, 0, 0);
-    v28.DrawTitleText(pFontArrus, 0, (212 - v26) / 2 + 101, v25, v24, 3u);
-    pDialogueWindow->pNumPresenceButton = 0;
-    return ;
-  }
-
-  if ( !HouseUI_CheckIfPlayerCanInteract() )
-    return;
-  v8 = pDialogueWindow;
-  v33 = 0;
-  v34 = 0;
-  v29 = pDialogueWindow;
-  v9 = pDialogueWindow->pStartingPosActiveItem;
-  v10 = v9 + pDialogueWindow->pNumPresenceButton;
-  v35 = pDialogueWindow->pStartingPosActiveItem;
-  if ( v9 >= v10 )
-    goto LABEL_40;
-  do
-  {
-    v11 = v8->GetControl(v35)->msg_param - 36;
-    if ( byte_4ED970_skill_learn_ability_by_class_table[v1->classType / 3][v11] && !v1->pActiveSkills[v11] )
-    {
-      v12 = pFontArrus->CalcTextHeight(pSkillNames[v11], &v28, 0, 0);
-      v33 += v12;
-      ++v34;
-    }
-    v13 = v8->pStartingPosActiveItem;
-    ++v35;
-  }
-  while ( v35 < v8->pNumPresenceButton + v13 );
-  if ( !v34 )
-  {
-LABEL_40:
-    sprintf(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[544], v1->pName, pClassNames[v1->classType]);
-    strcat(pTmpBuf.data(), "\n \n");
-    strcat(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[528]);
-    v22 = v31;
-    v23 = pFontArrus->CalcTextHeight(pTmpBuf.data(), &v28, 0, 0);
-    v28.DrawTitleText(pFontArrus, 0, (174 - v23) / 2 + 138, v22, pTmpBuf.data(), 3u);
-    return; 
-  }
-  sprintf(pTmpBuf.data(), pGlobalTXT_LocalizationStrings[401], v32);
-  v28.DrawTitleText(pFontArrus, 0, 0x92u, 0, pTmpBuf.data(), 3u);
-  v32 = (149 - v33) / v34;
-  if ( (149 - v33) / v34 > 32 )
-    v32 = 32;
-
-  v35 = v8->pStartingPosActiveItem;
-  v34 = (149 - v34 * v32 - v33) / 2 - v32 / 2 + 162;
-  if ( v8->pStartingPosActiveItem < v8->pStartingPosActiveItem+ v8->pNumPresenceButton )
-  {
-    v33 = 2;
-    do
-    {
-      v14 = v8->GetControl(v35);
-      v15 = v14->msg_param - 36;
-      if ( byte_4ED970_skill_learn_ability_by_class_table[v1->classType / 3][v15] )
+      if ( pParty->uNumGold < pPrice )
       {
-        v16 = 0;
-        if ( !v1->pActiveSkills[v15] )
-        {
-          v17 = pSkillNames[v15];
-          v14->uY = v32 + v34;
-          v18 = pFontArrus->CalcTextHeight(v17, &v28, 0, 0);
-          v19 = v14->uY;
-          v14->uHeight = v18;
-          v20 = v19 + v18 - 1;
-          v14->uW = v20;
-          v34 = v20;
-          v21 = v31;
-          if ( pDialogueWindow->pCurrentPosActiveItem != v33 )
-            v21 = v30;
-          v28.DrawTitleText(pFontArrus, 0, v19, v21, v17, 3u);
-          goto LABEL_34;
-        }
+        ShowStatusBarString(pGlobalTXT_LocalizationStrings[155], 2);//У вас не хватает золота
+        v27 = 4;
       }
       else
       {
-        v16 = 0;
+        Party::TakeGold(pPrice);
+        *(short *)v6 = 1;
+         v27 = 2;
       }
-      v14->uW = v16;
-      v14->uHeight = v16;
-      v14->uY = v16;
-LABEL_34:
-      v8 = v29;
-      ++v35;
-      ++v33;
+      PlayHouseSound((unsigned int)window_SpeakInHouse->ptr_1C, (HouseSoundID)v27);
     }
-    while ( v35 <v29->pNumPresenceButton + v29->pStartingPosActiveItem );
   }
-  return;
+  else
+  {
+    v5 = 0;
+  }
+  pMessageQueue_50CBD0->AddMessage(UIMSG_Escape, 1, v5);
+  return; // void func
 }
 
 //----- (004B2A74) --------------------------------------------------------
-void SimpleHouseAndBoatsDialog()
+void SimpleHouseDialog()
 {
   char *v2; // eax@3
   unsigned int i; // eax@5
@@ -3739,7 +3387,7 @@
   GUIFont *v47; // ebx@64
   int v48; // esi@64
   GUIWindow w; // [sp+Ch] [bp-110h]@64
-  GUIWindow v52; // [sp+60h] [bp-BCh]@13
+  GUIWindow right_panel_window; // [sp+60h] [bp-BCh]@13
   GUIWindow house_window; // [sp+B4h] [bp-68h]@1
   char *pInString; // [sp+114h] [bp-8h]@12
 
@@ -3788,90 +3436,32 @@
       }
     }
   }
-  memcpy(&v52, pDialogueWindow, sizeof(v52));
-  v52.uFrameX = 483;
-  v52.uFrameWidth = 148;
-  v52.uFrameZ = 334;
-  
-  if ( v52.pStartingPosActiveItem < v52.pStartingPosActiveItem + v52.pNumPresenceButton )
+  //for right panel
+  memcpy(&right_panel_window, pDialogueWindow, sizeof(right_panel_window));
+  right_panel_window.uFrameX = 483;
+  right_panel_window.uFrameWidth = 148;
+  right_panel_window.uFrameZ = 334;
+  for ( int i = right_panel_window.pStartingPosActiveItem;
+            i < right_panel_window.pStartingPosActiveItem + right_panel_window.pNumPresenceButton; ++i )
   {
-    v15 = "";
-    for ( int i = v52.pStartingPosActiveItem; i < v52.pStartingPosActiveItem + v52.pNumPresenceButton; ++i )
+    pButton = right_panel_window.GetControl(i);
+    switch ( pButton->msg_param )
     {
-      pButton = v52.GetControl(i);
-      if ( (signed int)pButton->msg_param > 24 )
-      {
-        if ( pButton->msg_param == 76 )
-        {
-          v15 = pGlobalTXT_LocalizationStrings[406];//Нанять
-          strcpy(pButton->pButtonName, v15);
-          continue;
-        }
-        if ( pButton->msg_param == 77 )
-        {
-          strcpy(pButton->pButtonName, pGlobalTXT_LocalizationStrings[407]);//Подробнее
-          continue;
-        }
-        if ( pButton->msg_param == 79 )
-        {
-          strcpy(pButton->pButtonName, _4B254D_SkillMasteryTeacher((int)v52.ptr_1C));
-          continue;
-        }
-        if ( pButton->msg_param == 82 )
-        {
-          strcpy(pButton->pButtonName, ContractSelectText((int)v52.ptr_1C));
-          continue;
-        }
-        if ( pButton->msg_param == 83 )
+      case 19://evt_A
+        v15 = (char *)pNPCTopics[pNPC->evt_A-1].pTopic;
+        if ( !v15 )
         {
-          v29 = pMonsterStats->pInfos[bountyHunting_monster_id_for_hunting].pName;
-          v31 = *(int *)v29;
-          sprintfex(pTmpBuf.data(), "\f%05d%s\f%05d", TargetColor(0xFFu, 0xFFu, 0x9Bu), v31, TargetColor(0xFFu, 0xFFu, 0xFFu));
-          sprintfex(pTmpBuf2.data(), bountyHunting_text, pTmpBuf.data(), 100 * (unsigned __int8)v29[8]);
-          current_npc_text = pTmpBuf2.data();
-          strcpy(pButton->pButtonName, "");
-          continue;
+          pButton->msg_param = 0;
+          v15 = "";
         }
-        if ( pButton->msg_param != 93 )
-        {
-          strcpy(pButton->pButtonName, "");
-          continue;
-        }
-      }
-      else
-      {
-        if ( pButton->msg_param == 24 )//evt_F
+        strcpy(pButton->pButtonName, v15);
+        continue;
+      case 20://evt_B
+        v15 = (char *)pNPCTopics[pNPC->evt_B-1].pTopic;
+        if ( !v15 )
         {
-          v15 = (char *)pNPCTopics[pNPC->evt_F-1].pTopic;
-          if ( !v15 )
-          {
-            pButton->msg_param = 0;
-            v15 = "";
-          }
-          strcpy(pButton->pButtonName, v15);
-          continue;
-        }
-        v18 = pButton->msg_param - 13;
-        if ( v18 )
-        {
-          if ( pButton->msg_param == 19 )//evt_A
-          {
-            v15 = (char *)pNPCTopics[pNPC->evt_A-1].pTopic;
-            if ( !v15 )
-            {
-              pButton->msg_param = 0;
-              v15 = "";
-            }
-            strcpy(pButton->pButtonName, v15);
-            continue;
-          }
-          if ( pButton->msg_param == 20 )//evt_B
-          {
-            v15 = (char *)pNPCTopics[pNPC->evt_B-1].pTopic;
-            if ( !v15 )
-            {
-              pButton->msg_param = 0;
-              v15 = "";
+          pButton->msg_param = 0;
+          v15 = "";
             }
             if ( uDialogueType != 84 )
             {
@@ -3883,9 +3473,7 @@
             current_npc_text = pTmpBuf2.data();
             strcpy(pButton->pButtonName, v15);
             continue;
-          }
-          if ( pButton->msg_param == 21 )//evt_C
-          {
+          case 21://evt_C
             v15 = (char *)pNPCTopics[pNPC->evt_C-1].pTopic;
             if ( !v15 )
             {
@@ -3894,9 +3482,7 @@
             }
             strcpy(pButton->pButtonName, v15);
             continue;
-          }
-          if ( pButton->msg_param == 22 )//evt_D
-          {
+          case 22://evt_D
             v15 = (char *)pNPCTopics[pNPC->evt_D-1].pTopic;
             if ( !v15 )
             {
@@ -3905,9 +3491,7 @@
             }
             strcpy(pButton->pButtonName, v15);
             continue;
-          }
-          if ( pButton->msg_param == 23 )//evt_E
-          {
+          case 23://evt_E
             v15 = (char *)pNPCTopics[pNPC->evt_E-1].pTopic;
             if ( !v15 )
             {
@@ -3916,21 +3500,59 @@
             }
             strcpy(pButton->pButtonName, v15);
             continue;
-          }
+          case 24://evt_F
+            v15 = (char *)pNPCTopics[pNPC->evt_F-1].pTopic;
+            if ( !v15 )
+            {
+              pButton->msg_param = 0;
+              v15 = "";
+            }
+            strcpy(pButton->pButtonName, v15);
+            continue;
+          case 76:
+            strcpy(pButton->pButtonName, pGlobalTXT_LocalizationStrings[406]);//Нанять
+            continue;
+          case 77:
+            strcpy(pButton->pButtonName, pGlobalTXT_LocalizationStrings[407]);//Подробнее
+            continue;
+          case 79:
+            strcpy(pButton->pButtonName, _4B254D_SkillMasteryTeacher((int)right_panel_window.ptr_1C));
+            continue;
+          case 82:
+            strcpy(pButton->pButtonName, ContractSelectText((int)right_panel_window.ptr_1C));
+            continue;
+          case 83:
+            v29 = pMonsterStats->pInfos[bountyHunting_monster_id_for_hunting].pName;
+            v31 = *(int *)v29;
+            sprintfex(pTmpBuf.data(), "\f%05d%s\f%05d", TargetColor(0xFFu, 0xFFu, 0x9Bu), v31, TargetColor(0xFFu, 0xFFu, 0xFFu));
+            sprintfex(pTmpBuf2.data(), bountyHunting_text, pTmpBuf.data(), 100 * (unsigned __int8)v29[8]);
+            current_npc_text = pTmpBuf2.data();
+            strcpy(pButton->pButtonName, "");
+            continue;
+        }
+        if ( pButton->msg_param < 13 )
+        {
+          strcpy(pButton->pButtonName, pGlobalTXT_LocalizationStrings[122]);//Вступить
+          continue;
+        }
+        if ( pButton->msg_param > 13 && pButton->msg_param < 19 )
+        {
           strcpy(pButton->pButtonName, "");
           continue;
         }
-        strcpy(pButton->pButtonName, pGlobalTXT_LocalizationStrings[122]);//Вступить
-      }
+        if ( pButton->msg_param != 93 )
+        {
+          strcpy(pButton->pButtonName, "");
+          continue;
+        }
     }
-  }
   v34 = 0;
   v36 = pDialogueWindow->pStartingPosActiveItem;
   for ( i = v36 + pDialogueWindow->pNumPresenceButton; (signed int)v36 < (signed int)i; i = pDialogueWindow->pNumPresenceButton
                                                                     + pDialogueWindow->pStartingPosActiveItem )
   {
     v37 = pDialogueWindow->GetControl(v36);
-    v38 = pFontArrus->CalcTextHeight(v37->pButtonName, &v52, 0, 0);
+    v38 = pFontArrus->CalcTextHeight(v37->pButtonName, &right_panel_window, 0, 0);
     v34 += v38;
     ++v36;
   }
@@ -3948,7 +3570,7 @@
       //v42 = v41;
       v43 = pButton->pButtonName;
       pButton->uY = (unsigned int)((char *)pNPC + v40);
-      v44 = pFontArrus->CalcTextHeight(pButton->pButtonName, &v52, 0, 0);
+      v44 = pFontArrus->CalcTextHeight(pButton->pButtonName, &right_panel_window, 0, 0);
       v45 = pButton->uY;
       pButton->uHeight = v44;
       v40 = v45 + v44 - 1;
@@ -3956,7 +3578,7 @@
       v46 = TargetColor(0xE1u, 0xCDu, 0x23u);
       if ( (char *)pDialogueWindow->pCurrentPosActiveItem != pInString )
         v46 = TargetColor(0xFFu, 0xFFu, 0xFFu);
-      v52.DrawTitleText(pFontArrus, 0, v45, v46, v43, 3);
+      right_panel_window.DrawTitleText(pFontArrus, 0, v45, v46, v43, 3);
       ++pInString;
     }
   }
@@ -3987,5 +3609,5 @@
   jail_dialogue_window.uFrameWidth = 148;
   jail_dialogue_window.uFrameZ = 334;
   jail_dialogue_window.DrawTitleText(pFontArrus, 0, (310 - pFontArrus->CalcTextHeight(pGlobalTXT_LocalizationStrings[672], &jail_dialogue_window, 0, 0)) / 2 + 18,
-     TargetColor(0xFFu, 0xFFu, 0x9Bu), pGlobalTXT_LocalizationStrings[672], 3);
+     TargetColor(0xFFu, 0xFFu, 0x9Bu), pGlobalTXT_LocalizationStrings[672], 3);//"За многочисленные преступления и злодеяния вы были приговорены к одному году заключения."
 }
\ No newline at end of file
--- a/UI/UIMainMenu.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/UI/UIMainMenu.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -297,7 +297,7 @@
         pTexture2._allocation_flags = 0;
         pColor1 = TargetColor(0x70u, 0x8Fu, 0xFEu);
         pColor2 = TargetColor(0xECu, 0xE6u, 0x9Cu);
-        pString = (char *)operator new(2 * pSize);
+        pString = (char *)malloc(2 * pSize);
         strncpy(pString, ptr, pSize);
         pString[pSize]=0;
         pFontQuick->_44D2FD_prolly_draw_credits_entry(pFontCChar, 0, a2.uFrameHeight, (signed __int16)pTexture2.uWidth, (signed __int16)pTexture2.uHeight, pColor1, 
--- a/UI/UISaveLoad.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/UI/UISaveLoad.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -11,7 +11,6 @@
 #include "..\GUIWindow.h"
 #include "..\GUIFont.h"
 #include "..\Render.h"
-#include "..\IndoorCamera.h"
 #include "..\LOD.h"
 #include "..\SaveLoad.h"
 #include "..\texts.h"
@@ -80,7 +79,7 @@
       v3 = uTextureID_LS_loadU;
     }
     pRenderer->DrawTextureIndexed(241, 302, pIcons_LOD->GetTexture(v3));
-    pRenderer->DrawTextureIndexed (18, 139, pIcons_LOD->GetTexture(v2));
+    pRenderer->DrawTextureIndexed( 18, 139, pIcons_LOD->GetTexture(v2));
     pRenderer->DrawTextureIndexed(351, 302, pIcons_LOD->GetTexture(uTextureID_x_u));
     v1 = 255;
   }
@@ -148,7 +147,7 @@
     auto ampm = aAMPMNames[HIDWORD(pAMPM2)];
     auto month = aMonthNames[pMonthNum];
     //sprintf(pTmpBuf.data(), "%s %d:%02d%s\n%d %s %d", _d, v17, (int)32, _a, 3, _m, pFilesID);
-    sprintf(pTmpBuf.data(), "%s %d:%02d%s\n%d %s %d", day, pHour, pMinutes, ampm, 7 * v16 + HIDWORD(pOurHour) % 7 + 1, month, pYear);
+    sprintfex(pTmpBuf.data(), "%s %d:%02d%s\n%d %s %d", day, pHour, pMinutes, ampm, 7 * v16 + HIDWORD(pOurHour) % 7 + 1, month, pYear);
     pWindow.DrawTitleText(pFontSmallnum, 0, 0, 0, pTmpBuf.data(), 3u);
     v1 = 255;
   }
--- a/UI/UiGame.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/UI/UiGame.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -501,71 +501,64 @@
     else if (pButton->msg_param == 24)
     {
       __debugbreak(); // learn conditions of this event
-      auto topic = pNPCTopics[pNPC->evt_F - 1].pTopic;//(&dword_721660)[8 * v23];
-      if (!topic)
+      if (!pNPC->evt_F)
+      {
+        pButton->pButtonName[0] = 0;
+        pButton->msg_param = 0;
+      }
+      else
+        strcpy(pButton->pButtonName, pNPCTopics[pNPC->evt_F].pTopic);
+    }
+    else if (pButton->msg_param == 9)
+      strcpy(pButton->pButtonName, GetProfessionActionText(pNPC->uProfession));
+    else if (pButton->msg_param == 19) // Scavenger Hunt
+    {
+      if (!pNPC->evt_A)
       {
         pButton->pButtonName[0] = 0;
         pButton->msg_param = 0;
       }
       else
-        strcpy(pButton->pButtonName, topic);
+        strcpy(pButton->pButtonName, pNPCTopics[pNPC->evt_A].pTopic);
     }
-    else if (pButton->msg_param == 9)
-      strcpy(pButton->pButtonName, GetProfessionActionText(pNPC->uProfession));
-    else if (pButton->msg_param == 19)
+    else if (pButton->msg_param == 20) // Scavenger Hunt
     {
-     // __debugbreak(); // learn conditions of this event Scavenger Hunt
-      auto topic = pNPCTopics[pNPC->evt_A - 1].pTopic;//(&dword_721660)[8 * v23];
-      if (!topic)
+      if (!pNPC->evt_B)
       {
         pButton->pButtonName[0] = 0;
         pButton->msg_param = 0;
       }
-      else strcpy(pButton->pButtonName, topic);
-    }
-    else if (pButton->msg_param == 20)
-    {
-      //__debugbreak(); // learn conditions of this event instruments
-      auto topic = pNPCTopics[pNPC->evt_B - 1].pTopic;//(&dword_721660)[8 * v23];
-      if (!topic)
-      {
-        pButton->pButtonName[0] = 0;
-        pButton->msg_param = 0;
-      }
-      else strcpy(pButton->pButtonName, topic);
+      else strcpy(pButton->pButtonName, pNPCTopics[pNPC->evt_B].pTopic);
     }
     else if (pButton->msg_param == 21)
     {
       //__debugbreak(); // learn conditions of this event
-      auto topic = pNPCTopics[pNPC->evt_C - 1].pTopic;//(&dword_721660)[8 * v23];
-      if (!topic)
+      if (!pNPC->evt_C)
       {
         pButton->pButtonName[0] = 0;
         pButton->msg_param = 0;
       }
-      else strcpy(pButton->pButtonName, topic);
+      else strcpy(pButton->pButtonName, pNPCTopics[pNPC->evt_C].pTopic);
     }
     else if (pButton->msg_param == 22)
     {
       //__debugbreak(); // learn conditions of this event
-      auto topic = pNPCTopics[pNPC->evt_D - 1].pTopic;//(&dword_721660)[8 * v23];
-      if (!topic)
+      if (!pNPC->evt_D)
       {
         pButton->pButtonName[0] = 0;
         pButton->msg_param = 0;
       }
-      else strcpy(pButton->pButtonName, topic);
+      else strcpy(pButton->pButtonName, pNPCTopics[pNPC->evt_D].pTopic);
     }
     else if (pButton->msg_param == 23)
     {
       //__debugbreak(); // learn conditions of this event
-      auto topic = pNPCTopics[pNPC->evt_E - 1].pTopic;//(&dword_721660)[8 * v23];
-      if (!topic)
+      if (!pNPC->evt_E)
       {
         pButton->pButtonName[0] = 0;
         pButton->msg_param = 0;
       }
-      else strcpy(pButton->pButtonName, topic);
+      else strcpy(pButton->pButtonName, pNPCTopics[pNPC->evt_E].pTopic);
     }
     else if (pButton->msg_param == 13)
     {
--- a/Viewport.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/Viewport.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -54,7 +54,7 @@
     this->uScreenHeight = br_y - tl_y + 1;
     this->uScreenCenterX = (signed int)(br_x + tl_x) /2;
     if ( pRenderer->pRenderD3D == 0 )
-        this->uScreenCenterY = this->uScreen_BR_Y - fixpoint_sub0(field_30, uScreenHeight);
+        this->uScreenCenterY = this->uScreen_BR_Y - fixpoint_mul(field_30, uScreenHeight);
     else
         this->uScreenCenterY = uScreenHeight/2;
     SetViewport(this->uScreen_TL_X, this->uScreen_TL_Y, this->uScreen_BR_X, this->uScreen_BR_Y);
--- a/Vis.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/Vis.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -3,11 +3,11 @@
 #include "BSPModel.h"
 #include "Game.h"
 #include "Actor.h"
-#include "IndoorCamera.h"
-#include "OutdoorCamera.h"
+#include "Outdoor_stuff.h"
 #include "Viewport.h"
 #include "Math.h"
 #include "Log.h"
+#include "ErrorHandling.h"
 
 #include "mm7_data.h"
 #include "MM7.h"
@@ -838,14 +838,14 @@
 
   if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
   {
-    if ( pRenderer->pRenderD3D )
+    //if ( pRenderer->pRenderD3D )
       v3 = pGame->pIndoorCameraD3D->fov;
-    else
-      v3 = pIndoorCamera->flt_1C_fov;
+    //else
+    //  v3 = pIndoorCamera->fov_rad;
   }
   else
   {
-    v3 = pOutdoorCamera->int_fov_rad;
+    v3 = pODMRenderParams->int_fov_rad;
   }
   return stru_5C6E00->Atan2(x - pViewport->uScreenCenterX, v3) - stru_5C6E00->uIntegerHalfPi;
 }
@@ -857,14 +857,14 @@
 
   if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
   {
-    if ( pRenderer->pRenderD3D )
+    //if ( pRenderer->pRenderD3D )
       v3 = pGame->pIndoorCameraD3D->fov;
-    else
-      v3 = pIndoorCamera->flt_1C_fov;
+    //else
+    //  v3 = pIndoorCamera->fov_rad;
   }
   else
   {
-    v3 = pOutdoorCamera->int_fov_rad;
+    v3 = pODMRenderParams->int_fov_rad;
   }
   return stru_5C6E00->Atan2(y - pViewport->uScreenCenterY, v3) - stru_5C6E00->uIntegerHalfPi;
 }
@@ -880,27 +880,27 @@
   int outx;
   int outz; // [sp+94h] [bp-Ch]@1
   int outy; // [sp+98h] [bp-8h]@1
+  
+  pRotY = pGame->pIndoorCameraD3D->sRotationY + UnprojectX(fMouseX);
+  pRotX = pGame->pIndoorCameraD3D->sRotationX + UnprojectY(fMouseY);
 
-  pRotY = pIndoorCamera->sRotationY + UnprojectX(fMouseX);
-  pStartR.z = pIndoorCamera->pos.z;
-  pStartR.x = pIndoorCamera->pos.x;
-  pStartR.y = pIndoorCamera->pos.y;
-  pRotX = pIndoorCamera->sRotationX + UnprojectY(fMouseY);
+  pStartR.z = pGame->pIndoorCameraD3D->vPartyPos.z;
+  pStartR.x = pGame->pIndoorCameraD3D->vPartyPos.x;
+  pStartR.y = pGame->pIndoorCameraD3D->vPartyPos.y;
+
+  v11[1].vWorldPosition.x = (double)pGame->pIndoorCameraD3D->vPartyPos.x;
+  v11[1].vWorldPosition.y = (double)pGame->pIndoorCameraD3D->vPartyPos.y;
+  v11[1].vWorldPosition.z = (double)pGame->pIndoorCameraD3D->vPartyPos.z;
+
   pDepth = fixpoint_from_float(fPickDepth);
   Vec3_int_::Rotate(pDepth, pRotY, pRotX, pStartR, &outx, &outy, &outz);
 
-  v11[0].flt_2C = 0.0;
   v11[0].vWorldPosition.x = (double)outx;
   v11[0].vWorldPosition.y = (double)outy;
   v11[0].vWorldPosition.z = (double)outz;
 
-  v11[1].flt_2C = 0.0;
-  v11[1].vWorldPosition.x = (double)pIndoorCamera->pos.x;
-  v11[1].vWorldPosition.y = (double)pIndoorCamera->pos.y;
-  v11[1].vWorldPosition.z = (double)pIndoorCamera->pos.z;
-
-  memcpy(pRay, &v11[1], sizeof(RenderVertexSoft));
-  memcpy(&pRay[1], &v11[0], sizeof(RenderVertexSoft));
+  memcpy(pRay + 0, &v11[1], sizeof(RenderVertexSoft));
+  memcpy(pRay + 1, &v11[0], sizeof(RenderVertexSoft));
 }
 
 //----- (004C2551) --------------------------------------------------------
--- a/_deleted.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/_deleted.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -649,16 +649,16 @@
       }
       if ( *(float *)v9 >= 8.0 )
       {
-        if ( (double)pOutdoorCamera->shading_dist_mist >= *(float *)v9 )
+        if ( (double)pODMRenderParams->shading_dist_mist >= *(float *)v9 )
         {
           *(int *)v2 = 0;
-          v12 = v4 / (*(float *)v9 + 0.0000001) * (double)pOutdoorCamera->int_fov_rad;
+          v12 = v4 / (*(float *)v9 + 0.0000001) * (double)pODMRenderParams->int_fov_rad;
           *(float *)((char *)v2 + (int)v18) = (double)pViewport->uScreenCenterX
                                                - v12 * *(float *)((char *)v2 + (int)v3);
           *(float *)((char *)v2 + (int)v17) = (double)pViewport->uScreenCenterY
                                                - v12 * *(float *)((char *)v2 + (int)v5);
           *(float *)((char *)v2 + (int)v16) = v4
-                                               - v4 / (*(float *)v9 * 1000.0 / (double)pOutdoorCamera->shading_dist_mist);
+                                               - v4 / (*(float *)v9 * 1000.0 / (double)pODMRenderParams->shading_dist_mist);
           *(float *)((char *)v2 + (int)v15) = v4 / (*(float *)v9 + 0.0000001);
           v13 = *(float *)v9 + 6.7553994e15;
           v4 = 1.0;
@@ -963,10 +963,10 @@
   v41 = v8;
   if ( v8 > 0 )
   {
-    if ( (signed int)pOutdoorCamera->uNumSurfs < 1999 )
-    {
-      v7 = pOutdoorCamera->uNumEdges;
-      if ( (signed int)pOutdoorCamera->uNumEdges < 5979 )
+    if ( (signed int)pODMRenderParams->uNumSurfs < 1999 )
+    {
+      v7 = pODMRenderParams->uNumEdges;
+      if ( (signed int)pODMRenderParams->uNumEdges < 5979 )
       {
         v4->uEdgeList1Size = 0;
         v4->uEdgeList2Size = 0;
@@ -985,7 +985,7 @@
           do
           {
             v10 = v48;
-            ++pOutdoorCamera->uNumEdges;
+            ++pODMRenderParams->uNumEdges;
             if ( v48 >= v41 )
               v10 = 0;
             v11 = *v9;
@@ -1089,7 +1089,7 @@
           while ( v48 - 1 < v41 );
         }
         LOBYTE(v7) = v34;
-        if ( pOutdoorCamera->uNumEdges != v34 )
+        if ( pODMRenderParams->uNumEdges != v34 )
         {
           v4->ptr_48 = 0;
           ptr_80C97C_Surfs->field_22 = 0;
@@ -1103,7 +1103,7 @@
           if ( ptr_80C97C_Surfs < &pSurfs[1999] )
           {
             ++ptr_80C97C_Surfs;
-            ++pOutdoorCamera->uNumSurfs;
+            ++pODMRenderParams->uNumSurfs;
           }
           if ( BYTE3(a4) )
             v4->field_108 = 1;
@@ -1158,7 +1158,7 @@
 
   v2 = _this;
   v3 = _this->pParent;
-  v4 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - _this->field_A);
+  v4 = pODMRenderParams->int_fov_rad_inv * (pViewport->uScreenCenterY - _this->field_A);
   v5 = v3->ptr_38;
   v38 = v4;
   v37 = v5->field_14;
@@ -1176,11 +1176,11 @@
   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;
+  v29 = pGame->pIndoorCameraD3D->int_sine_y;
+  v32 = pGame->pIndoorCameraD3D->int_cosine_y;
   a1.field_28 = v2->field_C;
   v11 = v3->field_24;
-  v37 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterX - v10);
+  v37 = pODMRenderParams->int_fov_rad_inv * (pViewport->uScreenCenterX - v10);
   v12 = v3->v_18.y;
   v13 = -v11;
   v36 = v13;
@@ -1254,8 +1254,8 @@
   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);
+  v35 = pODMRenderParams->int_fov_rad_inv;
+  v37 = (signed int)((unsigned __int64)(pODMRenderParams->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);
@@ -1271,7 +1271,7 @@
   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);
+  a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v2, v38, v3, pODMRenderParams->building_gamme, 1u, 1);
   if ( byte_4D864C && BYTE1(pGame->uFlags) & 8 )
     sr_sub_485975(&a1, (stru315 *)&a2);
   else
@@ -1429,7 +1429,7 @@
             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 || (double)pODMRenderParams->shading_dist_mist < *(float *)v9 )
             {
               if ( *(float *)v9 >= 8.0 )
                 v75 = 1;
@@ -1449,7 +1449,7 @@
           }
           v7 = v77;
         }
-        v12 = &array_77EC08[pOutdoorCamera->uNumPolygons];
+        v12 = &array_77EC08[pODMRenderParams->uNumPolygons];
         *(int *)&v12->flags = 0;
         if ( v82 == v7 )
           *(int *)&v12->flags = 65536;
@@ -1482,18 +1482,18 @@
           v16 = pTextureFrameTable->GetFrameTexture(v16, pEventTimer->uTotalGameTimeElapsed);
         v17 = v16;
         result = (BSPModel *)&pBitmaps_LOD->pTextures[v16];
-        v19 = __OFSUB__(pOutdoorCamera->uNumPolygons, 1999);
-        v18 = pOutdoorCamera->uNumPolygons - 1999 < 0;
+        v19 = __OFSUB__(pODMRenderParams->uNumPolygons, 1999);
+        v18 = pODMRenderParams->uNumPolygons - 1999 < 0;
         v12->pTexture = (Texture *)(v17 != -1 ? (int)result : 0);
         if ( !(v18 ^ v19) )
           return result;
-        ++pOutdoorCamera->uNumPolygons;
-        ++pOutdoorCamera->field_44;
+        ++pODMRenderParams->uNumPolygons;
+        ++pODMRenderParams->field_44;
         if ( !ODMFace::IsBackfaceCulled(v3, array_73D150, v12) )
         {
 LABEL_71:
-          --pOutdoorCamera->uNumPolygons;
-          --pOutdoorCamera->field_44;
+          --pODMRenderParams->uNumPolygons;
+          --pODMRenderParams->field_44;
           goto LABEL_72;
         }
         LOBYTE(v20) = v79;
@@ -1581,7 +1581,7 @@
         {
           v36 = sr_4250FE(v26);
           v37 = v36;
-          if ( !v36 || (OutdoorCamera::Project(v36), v38 = sr_4254D2(v37), (v12->uNumVertices = v38) == 0) )
+          if ( !v36 || (ODMRenderParams::Project(v36), v38 = sr_4254D2(v37), (v12->uNumVertices = v38) == 0) )
             goto LABEL_71;
           v12->_48276F_sr();
           v39 = 0;
@@ -1609,7 +1609,7 @@
           {
             v43 = sr_4252E8(v26);
             v44 = v43;
-            if ( !v43 || (OutdoorCamera::Project(v43), v45 = sr_4254D2(v44), (v12->uNumVertices = v45) == 0) )
+            if ( !v43 || (ODMRenderParams::Project(v43), v45 = sr_4254D2(v44), (v12->uNumVertices = v45) == 0) )
               goto LABEL_71;
             v12->_48276F_sr();
             v46 = 0;
@@ -1736,7 +1736,7 @@
       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)
+    a3a = (double)(signed int)(((unsigned __int64)(11 * v12 / (pODMRenderParams->shading_dist_shade << 16)) >> 16) + 20)
         * pOutdoor->fFogDensity;
     v13 = a3a + 6.7553994e15;
     v10 = _43F55F_get_billboard_light_level(a1, LODWORD(v13) + v11);
@@ -1821,10 +1821,10 @@
   char v41; // [sp+30h] [bp-2Ch]@57
 
   v0 = pRenderer->pTargetSurface;
-  v1 = pOutdoorCamera->uNumPolygons;
+  v1 = pODMRenderParams->uNumPolygons;
   a1 = pRenderer->pTargetSurface;
   v2 = array_77EC08.data();
-  v37 = pOutdoorCamera->uNumPolygons;
+  v37 = pODMRenderParams->uNumPolygons;
   if ( !(pParty->uFlags & 2) )
   {
     v1 = uNumElementsIn80AA28;
@@ -1868,7 +1868,7 @@
                   {
                     while ( 1 )
                     {
-                      if ( pOutdoorCamera->outdoor_no_wavy_water )
+                      if ( pODMRenderParams->outdoor_no_wavy_water )
                         sr_sub_48408A_prolly_odm_water_no_waves(v3);
                       else
                         sr_sub_485407_prolly_odm_water_wavy(v3);
@@ -1884,7 +1884,7 @@
                     {
                       v16 = v4->pTexture;
                       v4->pTexture = pBitmaps_LOD->LoadTexturePtr("wtrtyl");
-                      if ( pOutdoorCamera->outdoor_no_wavy_water )
+                      if ( pODMRenderParams->outdoor_no_wavy_water )
                         sr_sub_48408A_prolly_odm_water_no_waves(v3);
                       else
                         sr_sub_485407_prolly_odm_water_wavy(v3);
@@ -2091,10 +2091,10 @@
   }
   if ( pParty->uFlags & 2 )
   {
-    v6 = pOutdoorCamera->uNumPolygons;
+    v6 = pODMRenderParams->uNumPolygons;
     v7 = 0;
     uNumElementsIn80AA28 = 0;
-    if ( pOutdoorCamera->uNumPolygons > 0 )
+    if ( pODMRenderParams->uNumPolygons > 0 )
     {
       v8 = (char *)&array_77EC08[0].flags;
       do
@@ -2114,9 +2114,9 @@
       uNumElementsIn80AA28 = v7;
     }
   }
-  v9 = pOutdoorCamera->uNumSpans;
-  sr_6BE060[0] = pOutdoorCamera->uNumSpans;
-  if (pOutdoorCamera->uNumPolygons >= 1999)
+  v9 = pODMRenderParams->uNumSpans;
+  sr_6BE060[0] = pODMRenderParams->uNumSpans;
+  if (pODMRenderParams->uNumPolygons >= 1999)
     return;
 
   array_77EC08[1999].Create_48607B(&stru_8019C8);
@@ -2137,8 +2137,8 @@
   array_77EC08[1999].v_18.x = v10;
   array_77EC08[1999].v_18.z = stru_5C6E00->Cos(pIndoorCamera->sRotationX);
   array_77EC08[1999].field_24 = 2048 - (pIndoorCamera->pos.z << 16);
-  a1a = (signed __int64)((double)(pIndoorCamera->pos.z * pOutdoorCamera->int_fov_rad)
-                       / ((double)pOutdoorCamera->int_fov_rad + 8192.0)
+  a1a = (signed __int64)((double)(pIndoorCamera->pos.z * pODMRenderParams->int_fov_rad)
+                       / ((double)pODMRenderParams->int_fov_rad + 8192.0)
                        + (double)pViewport->uScreenCenterY);
   cos((double)pIndoorCamera->sRotationX * 0.0030664064);
   sin((double)pIndoorCamera->sRotationX * 0.0030664064);
@@ -2230,7 +2230,7 @@
           if ( v13->field_C >= 0 )
           {
 LABEL_109:
-            if ( pOutdoorCamera->bNoSky )
+            if ( pODMRenderParams->bNoSky )
             {
               const_1_0();
             }
@@ -2325,8 +2325,8 @@
     v8 = v3->ptr_38;
     v42 = ((unsigned __int64)(v3->ptr_38->field_14 * (signed __int64)v7) >> 16) + v8->field_C;
     v40 = ((unsigned __int64)(v8->field_20 * (signed __int64)v7) >> 16) + v3->ptr_38->field_18;
-    v38 = pOutdoorCamera->camera_rotation_y_int_sine;
-    HIDWORD(v35) = pOutdoorCamera->camera_rotation_y_int_cosine;
+    v38 = pGame->pIndoorCameraD3D->int_sine_y;
+    HIDWORD(v35) = pGame->pIndoorCameraD3D->int_cosine_y;
     v45 = v4->field_C;
     v9 = ((unsigned __int64)(v3->v_18.z * (signed __int64)v7) >> 16) + v3->v_18.x;
     v10 = 65536 / SLODWORD(v35) * (pViewport->uScreenCenterX - v4->field_8);
@@ -2551,11 +2551,11 @@
   pDirectionIndicator2 = stru_5C6E00->uDoublePiMask & (stru_5C6E00->uIntegerPi + pDirectionIndicator1);//512
   v124 = ((pIndoorCamera->uMapGridCellX << 16) + 3 * stru_5C6E00->Cos(stru_5C6E00->uDoublePiMask & (stru_5C6E00->uIntegerPi + pDirectionIndicator1))) >> 16;//88
   v123 = ((pIndoorCamera->uMapGridCellZ << 16) + 3 * stru_5C6E00->Sin(pDirectionIndicator2)) >> 16;// 66
-  v120 = pOutdoorCamera->outdoor_grid_band_3 + v124;//+- range X
-  v119 = pOutdoorCamera->outdoor_grid_band_3 + v123;
-  v2 = pOutdoorCamera->uCameraFovInDegrees + 15;//90
-  i = v124 - pOutdoorCamera->outdoor_grid_band_3;
-  v122 = v123 - pOutdoorCamera->outdoor_grid_band_3;
+  v120 = pODMRenderParams->outdoor_grid_band_3 + v124;//+- range X
+  v119 = pODMRenderParams->outdoor_grid_band_3 + v123;
+  v2 = pODMRenderParams->uCameraFovInDegrees + 15;//90
+  i = v124 - pODMRenderParams->outdoor_grid_band_3;
+  v122 = v123 - pODMRenderParams->outdoor_grid_band_3;
 
   if ( v2 > 90 )
     v2 = 90;
@@ -3214,7 +3214,7 @@
     }
   }
   result = v126;
-  pOutdoorCamera->field_40 = v126;
+  pODMRenderParams->field_40 = v126;
   return result;
 }
 //----- (00482E07) --------------------------------------------------------
@@ -3309,7 +3309,7 @@
   v3 = ecx0->pParent;
   v4 = pViewport->uScreenCenterY - ecx0->field_A;
   v77 = pRenderTarget;
-  v5 = pOutdoorCamera->int_fov_rad_inv * v4;
+  v5 = pODMRenderParams->int_fov_rad_inv * v4;
   v6 = v3->ptr_38;
   v76 = ecx0;
   v81 = v5;
@@ -3327,7 +3327,7 @@
   v68 = v3->sTextureDeltaU << 16;
   v69 = v3->sTextureDeltaV << 16;
   v72 = -v3->field_24;
-  v10 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterX - ecx0->field_8);
+  v10 = pODMRenderParams->int_fov_rad_inv * (pViewport->uScreenCenterX - ecx0->field_8);
   v11 = v3->v_18.y;
   v66 = v81 + v3->v_18.x;
   v83 = v10;
@@ -3340,7 +3340,7 @@
     || (LODWORD(v14) = v72 << 16,
         HIDWORD(v14) = v72 >> 16,
         v79 = v14 / v84,
-        v80 = v10 - v85 * pOutdoorCamera->int_fov_rad_inv,
+        v80 = v10 - v85 * pODMRenderParams->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) )
@@ -3406,7 +3406,7 @@
     if ( v79 >= v70 )
     {
       v46 = v76;
-      a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v76, v70, v3, pOutdoorCamera->building_gamme, 0, 1);
+      a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v76, v70, v3, pODMRenderParams->building_gamme, 0, 1);
       v47 = v3->ptr_38;
       v79 = v80;
       v86 = v47->field_10;
@@ -3430,7 +3430,7 @@
       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;
+      v80 += pODMRenderParams->int_fov_rad_inv << v74;
       if ( v78 > 0 )
       {
         do
@@ -3486,10 +3486,10 @@
                                                       v76,
                                                       v84,
                                                       v3,
-                                                      pOutdoorCamera->building_gamme,
+                                                      pODMRenderParams->building_gamme,
                                                       0,
                                                       0);
-          v80 += pOutdoorCamera->int_fov_rad_inv << v74;
+          v80 += pODMRenderParams->int_fov_rad_inv << v74;
           --v78;
         }
         while ( v78 );
@@ -3543,7 +3543,7 @@
     }
     else
     {
-      a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v76, v79, v3, pOutdoorCamera->building_gamme, 1u, 1);
+      a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v76, v79, v3, pODMRenderParams->building_gamme, 1u, 1);
       v28 = v3->ptr_38;
       v85 = v10;
       v86 = v28->field_10;
@@ -3568,7 +3568,7 @@
       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);
+      v80 = v10 - (pODMRenderParams->int_fov_rad_inv << v74);
       if ( v78 > 0 )
       {
         v86 = v78;
@@ -3625,10 +3625,10 @@
                                                       v76,
                                                       v84,
                                                       v3,
-                                                      pOutdoorCamera->building_gamme,
+                                                      pODMRenderParams->building_gamme,
                                                       1u,
                                                       0);
-          v80 -= pOutdoorCamera->int_fov_rad_inv << v74;
+          v80 -= pODMRenderParams->int_fov_rad_inv << v74;
           --v86;
         }
         while ( v86 );
@@ -3761,10 +3761,10 @@
   //signed int band3a; // [sp+48h] [bp+8h]@2
 
   v9 = band2 * 512;
-  pOutdoorCamera->outdoor_grid_band_3 = band3;
+  pODMRenderParams->outdoor_grid_band_3 = band3;
   v10 = band1 * 512;
   v3 = band3 * 512;
-  pOutdoorCamera->uPickDepth = band3 * 512;
+  pODMRenderParams->uPickDepth = band3 * 512;
   //v4 = terrain_76E5C8;                             // v4:  0 -> 65536
   for (uint i = 0; i < 16384; ++i)
   //do
@@ -3822,7 +3822,7 @@
   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 = (double)pODMRenderParams->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),
@@ -3992,7 +3992,7 @@
         || v11->vWorldPosition.z != v103->vWorldPosition.z
         || v103->vWorldPosition.z != v102->vWorldPosition.z )
         break;
-      v17 = &array_77EC08[pOutdoorCamera->uNumPolygons];
+      v17 = &array_77EC08[pODMRenderParams->uNumPolygons];
       v18 = pOutdoor->GetTileTexture(v101, v100);
       v17->uTileBitmapID = v18;
       if ( v18 != -1 )
@@ -4027,9 +4027,9 @@
         {
           v17->dimming_level = 0;
         }
-        if ( pOutdoorCamera->uNumPolygons >= 1999 )
+        if ( pODMRenderParams->uNumPolygons >= 1999 )
           return;
-        ++pOutdoorCamera->uNumPolygons;
+        ++pODMRenderParams->uNumPolygons;
         if ( !_481FC9_terrain(v10, (RenderVertexSoft *)HIDWORD(v101), v102, v17) )
           goto LABEL_104;
         v26 = 1.0 / (v104->vWorldViewPosition.x + 0.0000001);
@@ -4072,7 +4072,7 @@
         }
         else
         {
-          v32 = (double)pOutdoorCamera->shading_dist_mist;
+          v32 = (double)pODMRenderParams->shading_dist_mist;
           if ( v32 >= v104->vWorldViewPosition.x
             && v32 >= *(float *)(HIDWORD(v101) + 12)
             && v32 >= v102->vWorldViewPosition.x
@@ -4095,7 +4095,7 @@
         if ( !v36 )
           goto LABEL_104;
 LABEL_41:
-        OutdoorCamera::Project(v37);
+        ODMRenderParams::Project(v37);
 LABEL_102:
         v33 = sr_4254D2(v37);
         v17->uNumVertices = v33;
@@ -4109,7 +4109,7 @@
       if ( v90 >= v81 )
         return;
     }
-    v38 = &array_77EC08[pOutdoorCamera->uNumPolygons];
+    v38 = &array_77EC08[pODMRenderParams->uNumPolygons];
     v39 = pOutdoor->GetTileTexture(v101, v100);
     v38->uTileBitmapID = v39;
     if ( v39 == -1 )
@@ -4148,9 +4148,9 @@
     }
     if ( v38->dimming_level < 0 )
       v38->dimming_level = 0;
-    if ( pOutdoorCamera->uNumPolygons >= 1999 )
+    if ( pODMRenderParams->uNumPolygons >= 1999 )
       return;
-    ++pOutdoorCamera->uNumPolygons;
+    ++pODMRenderParams->uNumPolygons;
     if ( !_481FC9_terrain((RenderVertexSoft *)HIDWORD(v101), v103, v104, v38) )
       goto LABEL_74;
     v48 = 1.0 / (v104->vWorldViewPosition.x + 0.0000001);
@@ -4187,7 +4187,7 @@
     }
     else
     {
-      v53 = (double)pOutdoorCamera->shading_dist_mist;
+      v53 = (double)pODMRenderParams->shading_dist_mist;
       if ( v53 >= v104->vWorldViewPosition.x
         && v53 >= *(float *)(HIDWORD(v101) + 12)
         && v53 >= v103->vWorldViewPosition.x )
@@ -4200,7 +4200,7 @@
 LABEL_68:
           sr_sub_481DB2(sr_508690, v54, v38);
 LABEL_75:
-          v17 = &array_77EC08[pOutdoorCamera->uNumPolygons];
+          v17 = &array_77EC08[pODMRenderParams->uNumPolygons];
           v57 = pOutdoor->GetTileTexture(v101, v100);
           v17->uTileBitmapID = v57;
           if ( v57 == -1 )
@@ -4238,13 +4238,13 @@
           }
           if ( v17->dimming_level < 0 )
             v17->dimming_level = 0;
-          if ( pOutdoorCamera->uNumPolygons >= 1999 )
+          if ( pODMRenderParams->uNumPolygons >= 1999 )
             return;
-          ++pOutdoorCamera->uNumPolygons;
+          ++pODMRenderParams->uNumPolygons;
           if ( !_481FC9_terrain(v102, v104, v103, v17) )
           {
 LABEL_104:
-            --pOutdoorCamera->uNumPolygons;
+            --pODMRenderParams->uNumPolygons;
             goto LABEL_105;
           }
           v62 = 1.0 / (v104->vWorldViewPosition.x + 0.0000001);
@@ -4276,12 +4276,12 @@
           if ( v104->vWorldViewPosition.x < 8.0 || v103->vWorldViewPosition.x < 8.0 || v102->vWorldViewPosition.x < 8.0 )
           {
             v37 = sr_4250FE(3u);
-            OutdoorCamera::Project(v37);
+            ODMRenderParams::Project(v37);
             if ( !v37 )
               goto LABEL_104;
             goto LABEL_102;
           }
-          v66 = (double)pOutdoorCamera->shading_dist_mist;
+          v66 = (double)pODMRenderParams->shading_dist_mist;
           if ( v66 < v104->vWorldViewPosition.x || v66 < v103->vWorldViewPosition.x || v66 < v102->vWorldViewPosition.x )
           {
             v37 = sr_4252E8(3u);
@@ -4311,7 +4311,7 @@
     v56 = v55;
     if ( v55 )
     {
-      OutdoorCamera::Project(v55);
+      ODMRenderParams::Project(v55);
       v54 = sr_4254D2(v56);
       v38->uNumVertices = v54;
       if ( v54 )
@@ -4321,7 +4321,7 @@
       }
     }
 LABEL_74:
-    --pOutdoorCamera->uNumPolygons;
+    --pODMRenderParams->uNumPolygons;
     goto LABEL_75;
   }
 }
@@ -4690,7 +4690,7 @@
       {
         LODWORD(v17) = v9 << 16;
         HIDWORD(v17) = v9 >> 16;
-        v27 = (double)(signed int)(((unsigned __int64)(v17 / (pOutdoorCamera->shading_dist_shade << 16) * (31 - *a6)) >> 16)
+        v27 = (double)(signed int)(((unsigned __int64)(v17 / (pODMRenderParams->shading_dist_shade << 16) * (31 - *a6)) >> 16)
                                  + *a6)
             * pOutdoor->fFogDensity;
         v18 = v27 + 6.7553994e15;
@@ -6013,10 +6013,10 @@
                     }
                     v13->prolly_tail = v0;
                   }
-                  if ( (signed int)pOutdoorCamera->uNumSpans >= 12499 )
+                  if ( (signed int)pODMRenderParams->uNumSpans >= 12499 )
                     return;
                   ++v0;
-                  ++pOutdoorCamera->uNumSpans;
+                  ++pODMRenderParams->uNumSpans;
                 }
                 v6 = v26;
                 v7->field_20 = (signed __int64)v11;
@@ -6058,10 +6058,10 @@
                     }
                     v17->prolly_tail = v0;
                   }
-                  if ( (signed int)pOutdoorCamera->uNumSpans >= 12499 )
+                  if ( (signed int)pODMRenderParams->uNumSpans >= 12499 )
                     return;
                   ++v0;
-                  ++pOutdoorCamera->uNumSpans;
+                  ++pODMRenderParams->uNumSpans;
                 }
                 v7->pNext->field_20 = (signed __int64)v15;
                 v6 = v26;
@@ -6120,23 +6120,23 @@
 }
 
 //----- (00487355) --------------------------------------------------------
-bool OutdoorCamera::_487355()
+bool ODMRenderParams::ApplyLightmapsSW()
 {
   int v0; // esi@1
   Polygon *v1; // edi@2
   bool result; // eax@3
 
   v0 = 0;
-  if ( pOutdoorCamera->uNumPolygons > 0 )
+  if ( pODMRenderParams->uNumPolygons > 0 )
   {
     v1 = array_77EC08.data();
     do
     {
-      result = pGame->pLightmapBuilder->_45D3C7(v1);
+      result = pGame->pLightmapBuilder->_45D3C7_sw(v1);
       ++v0;
       ++v1;
     }
-    while ( v0 < pOutdoorCamera->uNumPolygons );
+    while ( v0 < pODMRenderParams->uNumPolygons );
   }
   return result;
 }
@@ -6164,7 +6164,7 @@
 
   v14 = (double)pOutdoor->vSunlight.x / 65536.0;
   result = 0;
-  v1 = (unsigned int)&array_77EC08[pOutdoorCamera->uNumPolygons];
+  v1 = (unsigned int)&array_77EC08[pODMRenderParams->uNumPolygons];
   v15 = (double)pOutdoor->vSunlight.y / 65536.0;
   v16 = (double)pOutdoor->vSunlight.z / 65536.0;
   if ( v1 > (unsigned int)array_77EC08.data() )
@@ -6462,10 +6462,10 @@
   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);
+  v8 = pODMRenderParams->int_fov_rad_inv * (pViewport->uScreenCenterX - v4);
+  v9 = pODMRenderParams->int_fov_rad_inv * (pViewport->uScreenCenterY - v3);
   v10 = v5->ptr_38->field_14;
-  v76 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterX - v4);
+  v76 = pODMRenderParams->int_fov_rad_inv * (pViewport->uScreenCenterX - v4);
   v72 = v10;
   v81 = (unsigned __int64)(v10 * (signed __int64)v9) >> 16;
   v11 = v5->ptr_38;
@@ -6532,7 +6532,7 @@
 LABEL_12:
   if ( v21 )
   {
-    a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v61, v20, v5, pOutdoorCamera->building_gamme, 1u, 1);
+    a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v61, v20, v5, pODMRenderParams->building_gamme, 1u, 1);
     a1.field_28 = 16;
     v66 = v74 >> 4;
     v81 = v8;
@@ -6548,7 +6548,7 @@
     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;
+    v73 = v8 - 16 * pODMRenderParams->int_fov_rad_inv;
     v29 = v5->pTexture;
     v30 = (v71 + v27) >> v76;
     v31 = v28 >> v76;
@@ -6609,8 +6609,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;
+        a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v61, X, v5, pODMRenderParams->building_gamme, 1u, 0);
+        v73 -= 16 * pODMRenderParams->int_fov_rad_inv;
         v45 = v74-- == 1;
         a1.field_28 = 16;
         v30 = v43;
@@ -6729,7 +6729,7 @@
 
   v2 = _this;
   v3 = _this->pParent;
-  v4 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - _this->field_A);
+  v4 = pODMRenderParams->int_fov_rad_inv * (pViewport->uScreenCenterY - _this->field_A);
   v5 = v3->ptr_38;
   v44 = v4;
   v42 = v5->field_14;
@@ -6751,7 +6751,7 @@
   a1.field_28 = v2->field_C;
   v12 = pViewport->uScreenCenterX - v11;
   v13 = v3->field_24;
-  v42 = pOutdoorCamera->int_fov_rad_inv * v12;
+  v42 = pODMRenderParams->int_fov_rad_inv * v12;
   v14 = v3->v_18.y;
   v15 = -v13;
   v40 = v15;
@@ -6823,12 +6823,12 @@
     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;
+  v41 = pODMRenderParams->int_fov_rad_inv;
+  v42 = (signed int)((unsigned __int64)(pODMRenderParams->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);
+  a1.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v2, v19, v3, pODMRenderParams->terrain_gamma, 1u, 1);
   LOWORD(v19) = 0;
   v28 = v2->field_A;
   v29 = v2->field_A;
@@ -6905,7 +6905,7 @@
 
   v2 = _this;
   v3 = _this->pParent;
-  v4 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - _this->field_A);
+  v4 = pODMRenderParams->int_fov_rad_inv * (pViewport->uScreenCenterY - _this->field_A);
   v5 = v3->ptr_38;
   v40 = v4;
   v39 = v5->field_14;
@@ -6927,10 +6927,10 @@
   v35.field_28 = v2->field_C;
   v12 = pViewport->uScreenCenterX - v11;
   v13 = v3->field_24;
-  v41 = pOutdoorCamera->int_fov_rad_inv * v12;
+  v41 = pODMRenderParams->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;
+  v15 = ((unsigned __int64)(pODMRenderParams->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;
@@ -6990,12 +6990,12 @@
     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;
+  v38 = pODMRenderParams->int_fov_rad_inv;
+  v39 = (signed int)((unsigned __int64)(pODMRenderParams->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);
+  v35.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&v34, v2, v40, v3, pODMRenderParams->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];
@@ -7121,22 +7121,22 @@
   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);
+  v7 = pODMRenderParams->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);
+  v79 = pODMRenderParams->int_fov_rad_inv * (pViewport->uScreenCenterX - v76);
+  v78 = pODMRenderParams->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;
+  v78 = (unsigned __int64)(v76 * (signed __int64)(pODMRenderParams->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)
+  v11 = ((unsigned __int64)(v76 * (signed __int64)(pODMRenderParams->int_fov_rad_inv * (pViewport->uScreenCenterY - v2))) >> 16)
       + v4->ptr_38->field_18;
-  v78 = pOutdoorCamera->int_fov_rad_inv * (pViewport->uScreenCenterY - v2);
+  v78 = pODMRenderParams->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;
+  v78 = (unsigned __int64)(v76 * (signed __int64)(pODMRenderParams->int_fov_rad_inv * (pViewport->uScreenCenterY - v2))) >> 16;
   v12 = -v4->field_24;
   v63 = v78 + v4->v_18.x;
   v66 = -v4->field_24;
@@ -7179,7 +7179,7 @@
   }
   sr.pTextureLOD = v17;
 LABEL_14:
-  sr.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&sr2, v61, v15, v4, pOutdoorCamera->terrain_gamma, 1u, 1);
+  sr.field_34_palette = (unsigned __int16 *)sr_sub_485E1F(&sr2, v61, v15, v4, pODMRenderParams->terrain_gamma, 1u, 1);
   v18 = v4->ptr_38;
   v78 = v7;
   v79 = v18->field_10;
@@ -7213,7 +7213,7 @@
   sr.field_C = v79 - 1;
   if ( v73 )
   {
-    v25 = v7 - v73 * pOutdoorCamera->int_fov_rad_inv;
+    v25 = v7 - v73 * pODMRenderParams->int_fov_rad_inv;
     v26 = v25;
     v77 = v4->v_18.y;
     v79 = v25;
@@ -7268,12 +7268,12 @@
       else
         sr_sub_4D6FB0(v1);
     }
-    v39 = v79 - (pOutdoorCamera->int_fov_rad_inv << v69);
+    v39 = v79 - (pODMRenderParams->int_fov_rad_inv << v69);
   }
   else
   {
-    v79 = v7 - (pOutdoorCamera->int_fov_rad_inv << v69);
-    v39 = v7 - (pOutdoorCamera->int_fov_rad_inv << v69);
+    v79 = v7 - (pODMRenderParams->int_fov_rad_inv << v69);
+    v39 = v7 - (pODMRenderParams->int_fov_rad_inv << v69);
   }
   sr.field_28 = v68;
   while ( v67 > 0 )
@@ -7324,9 +7324,9 @@
       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_34_palette = (unsigned __int16 *)sr_sub_485E1F(&sr2, v61, v73, v4, pODMRenderParams->terrain_gamma, 1u, 0);
     sr.field_28 = v68;
-    v39 -= pOutdoorCamera->int_fov_rad_inv << v69;
+    v39 -= pODMRenderParams->int_fov_rad_inv << v69;
   }
   if ( !v62 )
     return 1;
@@ -7448,8 +7448,8 @@
   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);
+  v7 = pODMRenderParams->int_fov_rad_inv * (pViewport->uScreenCenterX - v3);
+  v8 = pODMRenderParams->int_fov_rad_inv * (pViewport->uScreenCenterY - v2);
   a1a.pDepthBuffer = (unsigned int *)&pRenderer->pActiveZBuffer[v3 + 640 * v2];
   v9 = v5->ptr_38;
   v47 = (Span *)v7;
@@ -7518,7 +7518,7 @@
 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_34_palette = (unsigned __int16 *)sr_sub_485E1F(&a2, v43, v18, v5, pODMRenderParams->terrain_gamma, 1u, 1);
   a1a.field_28 = 16;
   v43 = (Span *)(v46 >> 4);
   X = v7;
@@ -7544,10 +7544,10 @@
   v34 = v49 - v29->uWidthLn2;
   a1a.field_8 = (v33 << 16) - 65536;
   X = 2 * pMiscTimer->uTotalGameTimeElapsed;
-  v45 = pOutdoorCamera->int_fov_rad_inv;
+  v45 = pODMRenderParams->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;
+  i = (unsigned __int64)(pODMRenderParams->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;
@@ -7610,11 +7610,11 @@
   pPixels = pRenderTarget;
   v4 = a1->pParent;
   v13 = -v4->field_24;
-  X = ((unsigned __int64)(pOutdoorCamera->int_fov_rad_inv
+  X = ((unsigned __int64)(pODMRenderParams->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
+                        * (signed __int64)(pODMRenderParams->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)) )
@@ -7626,10 +7626,10 @@
   }
   else
   {
-    v7 = pOutdoorCamera->shading_dist_mist << 16;
-    v8 = pOutdoorCamera->shading_dist_mist << 16;
-  }
-  v9 = sr_sub_47C178(v8, v4, pOutdoorCamera->terrain_gamma, a4);
+    v7 = pODMRenderParams->shading_dist_mist << 16;
+    v8 = pODMRenderParams->shading_dist_mist << 16;
+  }
+  v9 = sr_sub_47C178(v8, v4, pODMRenderParams->terrain_gamma, a4);
   fill_pixels_fast(*((short *)v9 + v4->pTexture->uDecompressedSize), pPixels, v3->field_C);
   HIWORD(v10) = HIWORD(v7);
   LOWORD(v10) = 0;
@@ -7667,7 +7667,7 @@
   char *v26; // [sp+2Ch] [bp-4h]@5
 
   v1 = uVertexID;
-  v2 = (double)pOutdoorCamera->shading_dist_mist;
+  v2 = (double)pODMRenderParams->shading_dist_mist;
   memcpy(&array_50AC10[uVertexID], array_50AC10, sizeof(array_50AC10[uVertexID]));
   v22 = 0;
   v18 = array_50AC10[0].vWorldViewPosition.x <= v2;
@@ -8709,7 +8709,7 @@
         if ( v8->vWorldPosition.y != pVertices->vWorldPosition.y || pVertices->vWorldPosition.y != pVertices2->vWorldPosition.y 
              || pVertices2->vWorldPosition.y != v101->vWorldPosition.y )
           break;
-        pTile = &array_77EC08[pOutdoorCamera->uNumPolygons];
+        pTile = &array_77EC08[pODMRenderParams->uNumPolygons];
         pTile->uTileBitmapID = pOutdoor->GetTileTexture(sX, sY);
         if ( pTile->uTileBitmapID != -1 )
         {
@@ -8729,16 +8729,16 @@
                             (((float)pOutdoor->vSunlight.y / 65536.0) * norm->y) -
                             (((float)pOutdoor->vSunlight.z / 65536.0) * norm->z)) * 20.0;
           //v25 = thisf + 6.7553994e15;
-          //v27 = pOutdoorCamera->uNumPolygons > 1999;
-          //v26 = pOutdoorCamera->uNumPolygons - 1999 < 0;
+          //v27 = pODMRenderParams->uNumPolygons > 1999;
+          //v26 = pODMRenderParams->uNumPolygons - 1999 < 0;
           pTile->dimming_level = floorf(thisf + 0.5f);
-          if ( pOutdoorCamera->uNumPolygons >= 1999 )
+          if ( pODMRenderParams->uNumPolygons >= 1999 )
             return;
-          ++pOutdoorCamera->uNumPolygons;
+          ++pODMRenderParams->uNumPolygons;
           //if ( !_481FC9_terrain(v8, pVertices, v101, v16) )//Ritor1: It's temporary
           //goto LABEL_126;
           //{
-            //--pOutdoorCamera->uNumPolygons;
+            //--pODMRenderParams->uNumPolygons;
             //goto LABEL_162;
           //}
           __debugbreak(); // warning C4700: uninitialized local variable 'v102' used
@@ -8780,7 +8780,7 @@
           }
           this_3 = v102->vWorldViewPosition.x < 8.0 || pVertices->vWorldViewPosition.x < 8.0
               || v101->vWorldViewPosition.x < 8.0 || pVertices2->vWorldViewPosition.x < 8.0;
-          v3a = (double)pOutdoorCamera->shading_dist_mist;
+          v3a = (double)pODMRenderParams->shading_dist_mist;
           v108 = v3a < v102->vWorldViewPosition.x || v3a < pVertices->vWorldViewPosition.x
               || v3a < v101->vWorldViewPosition.x || v3a < pVertices2->vWorldViewPosition.x;
           v33 = 0;
@@ -8806,13 +8806,13 @@
             {
               v36 = sr_424CD7(v34);
               pTile->uNumVertices = v36;
-              OutdoorCamera::Project(v36);
+              ODMRenderParams::Project(v36);
             }
             if ( v108 )
             {
               v36 = sr_424EE0_MakeFanFromTriangle(v34);
               pTile->uNumVertices = v36;
-              OutdoorCamera::Project(v36);
+              ODMRenderParams::Project(v36);
             }
           }
           //v37 = *(int *)&v16->flags;
@@ -8845,7 +8845,7 @@
         if ( ++v88 >= v84 )
           return;
       }
-      v40 = &array_77EC08[pOutdoorCamera->uNumPolygons];
+      v40 = &array_77EC08[pODMRenderParams->uNumPolygons];
       v40->uTileBitmapID = pOutdoor->GetTileTexture(sX, sY);
       if ( v40->uTileBitmapID == -1 )
         goto LABEL_162;
@@ -8873,13 +8873,13 @@
       v40->dimming_level = LOBYTE(v50);
       if ( LOBYTE(v50) < 0 )
         v40->dimming_level = 0;
-      if ( pOutdoorCamera->uNumPolygons >= 1999 )
+      if ( pODMRenderParams->uNumPolygons >= 1999 )
         return;
-      ++pOutdoorCamera->uNumPolygons;
+      ++pODMRenderParams->uNumPolygons;
       if ( !_481FC9_terrain(pVertices, pVertices2, v8, v40) ) // Ritor1: It's temporary
         //goto LABEL_77;
         {
-          --pOutdoorCamera->uNumPolygons;
+          --pODMRenderParams->uNumPolygons;
           goto LABEL_112;
         }
       memcpy(&array_50AC10[0], v102, 0x30u);
@@ -8917,14 +8917,14 @@
         if ( pGame->pIndoorCameraD3D->_4371C3(array_50AC10, &uNumVertices, 0) == 1 && !uNumVertices )
         {
 //LABEL_77:
-          --pOutdoorCamera->uNumPolygons;
+          --pODMRenderParams->uNumPolygons;
           goto LABEL_112;
         }
         thisb->ViewTransform(array_50AC10, uNumVertices);
         thisb->Project(array_50AC10, uNumVertices, 0);
       }
       this_3a = v102->vWorldViewPosition.x < 8.0 || pVertices->vWorldViewPosition.x < 8.0 || pVertices2->vWorldViewPosition.x < 8.0;
-      v54 = (double)pOutdoorCamera->shading_dist_mist;
+      v54 = (double)pODMRenderParams->shading_dist_mist;
       v108 = v54 < v102->vWorldViewPosition.x || v54 < pVertices->vWorldViewPosition.x || v54 < pVertices2->vWorldViewPosition.x;
       pVertices = 0;
       v96->std__vector_000004_size = 0;
@@ -8957,7 +8957,7 @@
           v56 = sr_424EE0_MakeFanFromTriangle(v55);
         }
         v40->uNumVertices = v56;
-        OutdoorCamera::Project(v56);
+        ODMRenderParams::Project(v56);
       }
 LABEL_105:
       v57 = *(int *)&v40->flags;
@@ -8980,8 +8980,8 @@
         pRenderer->DrawTerrainPolygon(v40->uNumVertices, v40, pBitmaps_LOD->pHardwareTextures[v58], 0, v81);
       }
 LABEL_112:
-      v59 = &array_77EC08[pOutdoorCamera->uNumPolygons];
-      //a8 = (RenderVertexSoft *)&array_77EC08[pOutdoorCamera->uNumPolygons];
+      v59 = &array_77EC08[pODMRenderParams->uNumPolygons];
+      //a8 = (RenderVertexSoft *)&array_77EC08[pODMRenderParams->uNumPolygons];
       v59->uTileBitmapID = pOutdoor->GetTileTexture(sX, sY);
       if ( v59->uTileBitmapID  == -1 )
         goto LABEL_162;
@@ -9002,13 +9002,13 @@
       v59->dimming_level = floorf(thish + 0.5f);
       if ( v59->dimming_level < 0 )
         v59->dimming_level = 0;
-      if ( pOutdoorCamera->uNumPolygons >= 1999 )
+      if ( pODMRenderParams->uNumPolygons >= 1999 )
         return;
-      ++pOutdoorCamera->uNumPolygons;
+      ++pODMRenderParams->uNumPolygons;
       if ( !_481FC9_terrain(v101, v102, pVertices2, v59) )
       {
 //LABEL_126:
-        --pOutdoorCamera->uNumPolygons;
+        --pODMRenderParams->uNumPolygons;
         goto LABEL_162;
       }
       memcpy(&array_50AC10[0], v102, 0x30u);
@@ -9040,7 +9040,7 @@
         if ( pGame->pIndoorCameraD3D->_4371C3(array_50AC10, (unsigned int *)&v100, 0) == 1 && !v100 )
           //goto LABEL_126;
         {
-          --pOutdoorCamera->uNumPolygons;
+          --pODMRenderParams->uNumPolygons;
           goto LABEL_162;
         }
         thisc->ViewTransform(array_50AC10, v100);
@@ -9048,7 +9048,7 @@
       }
       this_3b = v102->vWorldViewPosition.x < 8.0 || pVertices2->vWorldViewPosition.x < 8.0
            || v101->vWorldViewPosition.x < 8.0;
-      v69 = (double)pOutdoorCamera->shading_dist_mist;
+      v69 = (double)pODMRenderParams->shading_dist_mist;
       v108 = v69 < v102->vWorldViewPosition.x || v69 < pVertices2->vWorldViewPosition.x || v69 < v101->vWorldViewPosition.x;
       v70 = 0;
       v96->std__vector_000004_size = 0;
@@ -9107,7 +9107,7 @@
         v73 = sr_424EE0_MakeFanFromTriangle(v72);
       }
       v71->uNumVertices = v73;
-      OutdoorCamera::Project(v73);
+      ODMRenderParams::Project(v73);
       goto LABEL_154;
     }
   }
@@ -10177,78 +10177,78 @@
   stru_F8AD28.uDefaultAmbientLightLevel = v2->field_22;
   if ( pBLVRenderParams->sPartyRotX )
   {
-    v74 = (unsigned __int64)(stru_F8AD28.plane_4.vNormal.y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
-    v74 = ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.x * (signed __int64)pBLVRenderParams->sCosineY) >> 16) - v74;
-    X = (unsigned __int64)(stru_F8AD28.plane_4.vNormal.z * (signed __int64)pBLVRenderParams->sSineNegX) >> 16;
-    stru_F8AD28.rotated_normal.x = ((unsigned __int64)(v74 * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16) - X;
+    v74 = (unsigned __int64)(stru_F8AD28.plane_4.vNormal.y * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
+    v74 = ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.x * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16) - v74;
+    X = (unsigned __int64)(stru_F8AD28.plane_4.vNormal.z * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16;
+    stru_F8AD28.rotated_normal.x = ((unsigned __int64)(v74 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16) - X;
     stru_F8AD28.rotated_normal.y = ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.x
-                                                     * (signed __int64)pBLVRenderParams->sSineY) >> 16)
+                                                     * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16)
                                  + ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.y
-                                                     * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
-    stru_F8AD28.rotated_normal.z = ((unsigned __int64)(v74 * (signed __int64)pBLVRenderParams->sSineNegX) >> 16)
+                                                     * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16);
+    stru_F8AD28.rotated_normal.z = ((unsigned __int64)(v74 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16)
                                  + ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.z
-                                                     * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16);
-    v70 = (unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
-    v74 = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pBLVRenderParams->sCosineY) >> 16) - v70;
-    v70 = (unsigned __int64)(stru_F8AD28.vec_14.z * (signed __int64)pBLVRenderParams->sSineNegX) >> 16;
-    stru_F8AD28.vec_60.y = ((unsigned __int64)(v74 * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16) - v70;
-    stru_F8AD28.vec_60.z = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
-                         + ((unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
-    stru_F8AD28.field_6C = ((unsigned __int64)(v74 * (signed __int64)pBLVRenderParams->sSineNegX) >> 16)
-                         + ((unsigned __int64)(stru_F8AD28.vec_14.z * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16);
-    v70 = (unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
-    v74 = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pBLVRenderParams->sCosineY) >> 16) - v70;
-    X = (unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pBLVRenderParams->sSineY) >> 16;
-    v72 = (unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pBLVRenderParams->sCosineY) >> 16;
-    v70 = (unsigned __int64)(stru_F8AD28.vec_20.z * (signed __int64)pBLVRenderParams->sSineNegX) >> 16;
-    stru_F8AD28.vec_70.x = ((unsigned __int64)(v74 * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16) - v70;
-    stru_F8AD28.vec_70.y = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
-                         + ((unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
-    stru_F8AD28.vec_70.z = ((unsigned __int64)(v74 * (signed __int64)pBLVRenderParams->sSineNegX) >> 16)
-                         + ((unsigned __int64)(stru_F8AD28.vec_20.z * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16);
-    v74 = pBLVRenderParams->sSineY * pBLVRenderParams->vPartyPos.y
-        - pBLVRenderParams->sCosineY * pBLVRenderParams->vPartyPos.x;
-    v11 = -(pBLVRenderParams->sCosineY * pBLVRenderParams->vPartyPos.y
-          + pBLVRenderParams->sSineY * pBLVRenderParams->vPartyPos.x);
+                                                     * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16);
+    v70 = (unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
+    v74 = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16) - v70;
+    v70 = (unsigned __int64)(stru_F8AD28.vec_14.z * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16;
+    stru_F8AD28.vec_60.y = ((unsigned __int64)(v74 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16) - v70;
+    stru_F8AD28.vec_60.z = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16);
+    stru_F8AD28.field_6C = ((unsigned __int64)(v74 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_14.z * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16);
+    v70 = (unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
+    v74 = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16) - v70;
+    X = (unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
+    v72 = (unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16;
+    v70 = (unsigned __int64)(stru_F8AD28.vec_20.z * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16;
+    stru_F8AD28.vec_70.x = ((unsigned __int64)(v74 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16) - v70;
+    stru_F8AD28.vec_70.y = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16);
+    stru_F8AD28.vec_70.z = ((unsigned __int64)(v74 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_20.z * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16);
+    v74 = pGame->pIndoorCameraD3D->int_sine_y * pBLVRenderParams->vPartyPos.y
+        - pGame->pIndoorCameraD3D->int_cosine_y * pBLVRenderParams->vPartyPos.x;
+    v11 = -(pGame->pIndoorCameraD3D->int_cosine_y * pBLVRenderParams->vPartyPos.y
+          + pGame->pIndoorCameraD3D->int_sine_y * pBLVRenderParams->vPartyPos.x);
     v73 = -65536 * pBLVRenderParams->vPartyPos.z;
-    v70 = (unsigned __int64)(-65536 * pBLVRenderParams->vPartyPos.z * (signed __int64)pBLVRenderParams->sSineNegX) >> 16;
-    v12 = ((unsigned __int64)(v74 * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16) - v70;
-    v69 = (unsigned __int64)(v74 * (signed __int64)pBLVRenderParams->sSineNegX) >> 16;
+    v70 = (unsigned __int64)(-65536 * pBLVRenderParams->vPartyPos.z * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16;
+    v12 = ((unsigned __int64)(v74 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16) - v70;
+    v69 = (unsigned __int64)(v74 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16;
     v13 = pBLVRenderParams->vPartyPos.y;
-    v70 = ((unsigned __int64)(v74 * (signed __int64)pBLVRenderParams->sSineNegX) >> 16)
-        + ((unsigned __int64)(-65536 * pBLVRenderParams->vPartyPos.z * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16);
+    v70 = ((unsigned __int64)(v74 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16)
+        + ((unsigned __int64)(-65536 * pBLVRenderParams->vPartyPos.z * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16);
     v14 = pBLVRenderParams->vPartyPos.x;
   }
   else
   {
-    v70 = (unsigned __int64)(stru_F8AD28.plane_4.vNormal.y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
+    v70 = (unsigned __int64)(stru_F8AD28.plane_4.vNormal.y * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
     stru_F8AD28.rotated_normal.x = ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.x
-                                                     * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+                                                     * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16)
                                  - v70;
     stru_F8AD28.rotated_normal.z = stru_F8AD28.plane_4.vNormal.z;
     stru_F8AD28.rotated_normal.y = ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.x
-                                                     * (signed __int64)pBLVRenderParams->sSineY) >> 16)
+                                                     * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16)
                                  + ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.y
-                                                     * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
-    v70 = (unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
-    stru_F8AD28.vec_60.y = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+                                                     * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16);
+    v70 = (unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
+    stru_F8AD28.vec_60.y = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16)
                          - v70;
     stru_F8AD28.field_6C = stru_F8AD28.vec_14.z;
-    stru_F8AD28.vec_60.z = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
-                         + ((unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
-    v70 = (unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pBLVRenderParams->sSineY) >> 16;
-    stru_F8AD28.vec_70.x = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+    stru_F8AD28.vec_60.z = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16);
+    v70 = (unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
+    stru_F8AD28.vec_70.x = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16)
                          - v70;
-    v69 = (unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pBLVRenderParams->sSineY) >> 16;
+    v69 = (unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16;
     v14 = pBLVRenderParams->vPartyPos.x;
     stru_F8AD28.vec_70.z = stru_F8AD28.vec_20.z;
     v13 = pBLVRenderParams->vPartyPos.y;
-    stru_F8AD28.vec_70.y = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
-                         + ((unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
-    v12 = pBLVRenderParams->sSineY * pBLVRenderParams->vPartyPos.y
-        - pBLVRenderParams->sCosineY * pBLVRenderParams->vPartyPos.x;
-    v11 = -(pBLVRenderParams->sCosineY * pBLVRenderParams->vPartyPos.y
-          + pBLVRenderParams->sSineY * pBLVRenderParams->vPartyPos.x);
+    stru_F8AD28.vec_70.y = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16);
+    v12 = pGame->pIndoorCameraD3D->int_sine_y * pBLVRenderParams->vPartyPos.y
+        - pGame->pIndoorCameraD3D->int_cosine_y * pBLVRenderParams->vPartyPos.x;
+    v11 = -(pGame->pIndoorCameraD3D->int_cosine_y * pBLVRenderParams->vPartyPos.y
+          + pGame->pIndoorCameraD3D->int_sine_y * pBLVRenderParams->vPartyPos.x);
     v70 = -65536 * pBLVRenderParams->vPartyPos.z;
   }
   stru_F8AD28.field_7C = stru_F8AD28.rotated_normal.x;
@@ -10603,74 +10603,74 @@
   stru_F8AD28.uDefaultAmbientLightLevel = 0;
   if ( pBLVRenderParams->sPartyRotX )
   {
-    v0 = ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.x * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
-       - ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.y * (signed __int64)pBLVRenderParams->sSineY) >> 16);
-    stru_F8AD28.rotated_normal.x = ((unsigned __int64)(v0 * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16)
+    v0 = ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.x * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16)
+       - ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.y * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16);
+    stru_F8AD28.rotated_normal.x = ((unsigned __int64)(v0 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16)
                                  - ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.z
-                                                     * (signed __int64)pBLVRenderParams->sSineNegX) >> 16);
+                                                     * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16);
     stru_F8AD28.rotated_normal.y = ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.x
-                                                     * (signed __int64)pBLVRenderParams->sSineY) >> 16)
+                                                     * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16)
                                  + ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.y
-                                                     * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
-    stru_F8AD28.rotated_normal.z = ((unsigned __int64)(v0 * (signed __int64)pBLVRenderParams->sSineNegX) >> 16)
+                                                     * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16);
+    stru_F8AD28.rotated_normal.z = ((unsigned __int64)(v0 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16)
                                  + ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.z
-                                                     * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16);
-    v1 = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
-       - ((unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pBLVRenderParams->sSineY) >> 16);
-    stru_F8AD28.vec_60.y = ((unsigned __int64)(v1 * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16)
-                         - ((unsigned __int64)(stru_F8AD28.vec_14.z * (signed __int64)pBLVRenderParams->sSineNegX) >> 16);
-    stru_F8AD28.vec_60.z = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
-                         + ((unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
-    stru_F8AD28.field_6C = ((unsigned __int64)(v1 * (signed __int64)pBLVRenderParams->sSineNegX) >> 16)
-                         + ((unsigned __int64)(stru_F8AD28.vec_14.z * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16);
-    v2 = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
-       - ((unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pBLVRenderParams->sSineY) >> 16);
-    stru_F8AD28.vec_70.x = ((unsigned __int64)(v2 * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16)
-                         - ((unsigned __int64)(stru_F8AD28.vec_20.z * (signed __int64)pBLVRenderParams->sSineNegX) >> 16);
-    stru_F8AD28.vec_70.y = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
-                         + ((unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
-    stru_F8AD28.vec_70.z = ((unsigned __int64)(v2 * (signed __int64)pBLVRenderParams->sSineNegX) >> 16)
-                         + ((unsigned __int64)(stru_F8AD28.vec_20.z * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16);
-    v3 = -(pBLVRenderParams->sCosineY * pBLVRenderParams->vPartyPos.y
-         + pBLVRenderParams->sSineY * pBLVRenderParams->vPartyPos.x);
-    v4 = pBLVRenderParams->sSineY * pBLVRenderParams->vPartyPos.y
-       - pBLVRenderParams->sCosineY * pBLVRenderParams->vPartyPos.x;
-    v5 = ((unsigned __int64)(v4 * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16)
-       - ((unsigned __int64)(-65536 * pBLVRenderParams->vPartyPos.z * (signed __int64)pBLVRenderParams->sSineNegX) >> 16);
+                                                     * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16);
+    v1 = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16)
+       - ((unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16);
+    stru_F8AD28.vec_60.y = ((unsigned __int64)(v1 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16)
+                         - ((unsigned __int64)(stru_F8AD28.vec_14.z * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16);
+    stru_F8AD28.vec_60.z = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16);
+    stru_F8AD28.field_6C = ((unsigned __int64)(v1 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_14.z * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16);
+    v2 = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16)
+       - ((unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16);
+    stru_F8AD28.vec_70.x = ((unsigned __int64)(v2 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16)
+                         - ((unsigned __int64)(stru_F8AD28.vec_20.z * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16);
+    stru_F8AD28.vec_70.y = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16);
+    stru_F8AD28.vec_70.z = ((unsigned __int64)(v2 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_20.z * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16);
+    v3 = -(pGame->pIndoorCameraD3D->int_cosine_y * pBLVRenderParams->vPartyPos.y
+         + pGame->pIndoorCameraD3D->int_sine_y * pBLVRenderParams->vPartyPos.x);
+    v4 = pGame->pIndoorCameraD3D->int_sine_y * pBLVRenderParams->vPartyPos.y
+       - pGame->pIndoorCameraD3D->int_cosine_y * pBLVRenderParams->vPartyPos.x;
+    v5 = ((unsigned __int64)(v4 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16)
+       - ((unsigned __int64)(-65536 * pBLVRenderParams->vPartyPos.z * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16);
     v6 = pBLVRenderParams->vPartyPos.z;
-    v7 = ((unsigned __int64)(-65536 * pBLVRenderParams->vPartyPos.z * (signed __int64)pBLVRenderParams->sCosineNegX) >> 16)
-       + ((unsigned __int64)(v4 * (signed __int64)pBLVRenderParams->sSineNegX) >> 16);
+    v7 = ((unsigned __int64)(-65536 * pBLVRenderParams->vPartyPos.z * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_x) >> 16)
+       + ((unsigned __int64)(v4 * (signed __int64)pGame->pIndoorCameraD3D->int_sine_x) >> 16);
     v8 = pBLVRenderParams->vPartyPos.y;
     v9 = pBLVRenderParams->vPartyPos.x;
   }
   else
   {
     stru_F8AD28.rotated_normal.x = ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.x
-                                                     * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
+                                                     * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16)
                                  - ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.y
-                                                     * (signed __int64)pBLVRenderParams->sSineY) >> 16);
+                                                     * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16);
     stru_F8AD28.rotated_normal.z = stru_F8AD28.plane_4.vNormal.z;
     stru_F8AD28.rotated_normal.y = ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.x
-                                                     * (signed __int64)pBLVRenderParams->sSineY) >> 16)
+                                                     * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16)
                                  + ((unsigned __int64)(stru_F8AD28.plane_4.vNormal.y
-                                                     * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
-    stru_F8AD28.vec_60.y = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
-                         - ((unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pBLVRenderParams->sSineY) >> 16);
+                                                     * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16);
+    stru_F8AD28.vec_60.y = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16)
+                         - ((unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16);
     stru_F8AD28.field_6C = stru_F8AD28.vec_14.z;
-    stru_F8AD28.vec_60.z = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
-                         + ((unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
-    stru_F8AD28.vec_70.x = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pBLVRenderParams->sCosineY) >> 16)
-                         - ((unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pBLVRenderParams->sSineY) >> 16);
+    stru_F8AD28.vec_60.z = ((unsigned __int64)(stru_F8AD28.vec_14.x * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_14.y * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16);
+    stru_F8AD28.vec_70.x = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16)
+                         - ((unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16);
     v8 = pBLVRenderParams->vPartyPos.y;
-    stru_F8AD28.vec_70.y = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pBLVRenderParams->sSineY) >> 16)
-                         + ((unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pBLVRenderParams->sCosineY) >> 16);
+    stru_F8AD28.vec_70.y = ((unsigned __int64)(stru_F8AD28.vec_20.x * (signed __int64)pGame->pIndoorCameraD3D->int_sine_y) >> 16)
+                         + ((unsigned __int64)(stru_F8AD28.vec_20.y * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16);
     stru_F8AD28.vec_70.z = stru_F8AD28.vec_20.z;
     v9 = pBLVRenderParams->vPartyPos.x;
-    v5 = pBLVRenderParams->sSineY * pBLVRenderParams->vPartyPos.y
-       - pBLVRenderParams->sCosineY * pBLVRenderParams->vPartyPos.x;
+    v5 = pGame->pIndoorCameraD3D->int_sine_y * pBLVRenderParams->vPartyPos.y
+       - pGame->pIndoorCameraD3D->int_cosine_y * pBLVRenderParams->vPartyPos.x;
     v6 = pBLVRenderParams->vPartyPos.z;
-    v3 = -(pBLVRenderParams->sCosineY * pBLVRenderParams->vPartyPos.y
-         + pBLVRenderParams->sSineY * pBLVRenderParams->vPartyPos.x);
+    v3 = -(pGame->pIndoorCameraD3D->int_cosine_y * pBLVRenderParams->vPartyPos.y
+         + pGame->pIndoorCameraD3D->int_sine_y * pBLVRenderParams->vPartyPos.x);
     v7 = -65536 * pBLVRenderParams->vPartyPos.z;
   }
   stru_F8AD28.field_7C = stru_F8AD28.rotated_normal.x;
@@ -10856,8 +10856,8 @@
               v45 = v14->field_4 >> 3;
               v44 = v16 >> 3;
               v17 = (signed int)((unsigned __int64)(SLODWORD(pBLVRenderParams->field_44) * (signed __int64)v14->field_28) >> 16) >> 3;
-              v52 = (unsigned __int64)(v17 * (signed __int64)-pBLVRenderParams->sSineY) >> 16;
-              v53 = (unsigned __int64)(v17 * (signed __int64)pBLVRenderParams->sCosineY) >> 16;
+              v52 = (unsigned __int64)(v17 * (signed __int64)-pGame->pIndoorCameraD3D->int_sine_y) >> 16;
+              v53 = (unsigned __int64)(v17 * (signed __int64)pGame->pIndoorCameraD3D->int_cosine_y) >> 16;
               v18 = v14->field_28;
               v19 = *(__int16 *)((char *)stru_F8A590.viewport_left_side + v13);
               LOWORD(v18) = 0;
@@ -12279,7 +12279,7 @@
 //----- (00481EB7) --------------------------------------------------------
 void ResetPolygons()
 {
-  for (auto i = 0; i < pOutdoorCamera->uNumPolygons; ++i)
+  for (auto i = 0; i < pODMRenderParams->uNumPolygons; ++i)
   {
     array_77EC08[i].prolly_head = nullptr;
     array_77EC08[i].prolly_tail = nullptr;
@@ -12400,7 +12400,7 @@
   while ( v2 );
 }
 //----- (00486A28) --------------------------------------------------------
-void OutdoorCamera::AllocSoftwareDrawBuffers()
+void ODMRenderParams::AllocSoftwareDrawBuffers()
 {
   if ( !this || !pSpans )
   {
@@ -12416,7 +12416,7 @@
   }
 }
 //----- (00486AFC) --------------------------------------------------------
-void OutdoorCamera::ReleaseSoftwareDrawBuffers()
+void ODMRenderParams::ReleaseSoftwareDrawBuffers()
 {
   free(pSpans);
   free(pEdges);
@@ -12431,7 +12431,7 @@
 bool OutdoorLocation::Release2()
 {
   Release();
-  pOutdoorCamera->ReleaseSoftwareDrawBuffers();
+  pODMRenderParams->ReleaseSoftwareDrawBuffers();
   return true;
 }
 
@@ -12769,6 +12769,446 @@
 
 
 
+
+
+//----- (0045D3C7) --------------------------------------------------------
+bool LightmapBuilder::_45D3C7_sw(struct Polygon *a1)
+{
+  LightmapBuilder *v2; // ebx@1
+  struct Polygon *result; // eax@1
+  float v4; // ecx@2
+  Span *i; // edi@5
+
+  v2 = this;
+  result = (struct Polygon *)a1->prolly_head;
+  if ( result && (v4 = result->field_4, *(int *)&v4) != 0 && *(unsigned int *)(LODWORD(v4) + 60) )
+  {
+    for ( i = a1->prolly_head; ; i = i->pNext )
+    {
+      result = i->pParent;
+      if ( result->field_108 )
+        result = (struct Polygon *)_45D426_sw(
+                              i,
+                              a1->pEdgeList1,
+                              a1->uEdgeList1Size,
+                              (Edge *)a1->pEdgeList2,
+                              a1->uEdgeList2Size);
+      if ( a1->prolly_tail == i )
+        break;
+    }
+    LOBYTE(result) = 1;
+  }
+  else
+  {
+    LOBYTE(result) = 0;
+  }
+  return (bool)result;
+}
+
+//----- (0045D426) --------------------------------------------------------
+int LightmapBuilder::_45D426_sw(Span *a1, Edge **a2, unsigned int a3, Edge *a4, int a5)
+{
+  int v6; // edi@1
+  signed int v7; // ebx@3
+  signed int v8; // ecx@3
+  Span *v9; // esi@3
+  double v10; // st7@4
+  Edge *v11; // edx@5
+  double v12; // st7@11
+  int v13; // edx@12
+  int v14; // ebx@17
+  Edge *v15; // edi@17
+  float v16; // ST04_4@17
+  float v17; // ST04_4@17
+  double v18; // st7@17
+  int result; // eax@19
+  //double v20; // ST14_8@20
+  //double v21; // ST14_8@20
+  double v22; // st7@20
+  int v23; // ecx@20
+  double v24; // st6@20
+  double v25; // st7@23
+  double v26; // st7@28
+  __int16 v27; // fps@28
+  char v28; // c0@28
+  char v29; // c2@28
+  char v30; // c3@28
+  double v31; // st7@29
+  double v32; // st7@30
+  __int16 v33; // fps@30
+  char v34; // c0@30
+  char v35; // c2@30
+  char v36; // c3@30
+  LightmapBuilder *this_4; // [sp+14h] [bp-8h]@1
+  signed int v38; // [sp+18h] [bp-4h]@3
+  float a1a; // [sp+24h] [bp+8h]@20
+  float a2a; // [sp+28h] [bp+Ch]@17
+  float a3a; // [sp+2Ch] [bp+10h]@17
+  float a5a; // [sp+34h] [bp+18h]@20
+  float a5b; // [sp+34h] [bp+18h]@20
+
+  v6 = 0;
+  this_4 = this;
+  if ( a5 && a3 )
+  {
+    v7 = -1;
+    v8 = 0;
+    v9 = a1;
+    v38 = -1;
+    if ( (signed int)a3 > 0 )
+    {
+      v10 = (double)a1->field_A;
+      while ( 1 )
+      {
+        v11 = a2[v8];
+        if ( v10 >= v11->field_2C )
+        {
+          if ( v10 <= v11->field_30 )
+            break;
+        }
+        ++v8;
+        if ( v8 >= (signed int)a3 )
+          goto LABEL_10;
+      }
+      v38 = v8;
+    }
+LABEL_10:
+    if ( a5 > 0 )
+    {
+      v12 = (double)a1->field_A;
+      while ( 1 )
+      {
+        v13 = *((unsigned int *)&a4->field_0 + v6);
+        if ( v12 >= *(float *)(v13 + 44) )
+        {
+          if ( v12 <= *(float *)(v13 + 48) )
+            break;
+        }
+        ++v6;
+        if ( v6 >= a5 )
+          goto LABEL_17;
+      }
+      v7 = v6;
+    }
+LABEL_17:
+    v14 = *((unsigned int *)&a4->field_0 + v7);
+    v15 = a2[v38];
+    v16 = (double)a1->field_A;
+    a3a = _45D643_sw(a2[v38], v16);
+    v17 = (double)a1->field_A;
+    v18 = _45D643_sw((Edge *)v14, v17);
+    a2a = v18;
+    if ( byte_4D864C && BYTE1(pGame->uFlags) & 0x80 )
+    {
+      HIWORD(result) = HIWORD(a3a);
+      a1->field_14 = v18;
+      a1->field_10 = a3a;
+    }
+    else
+    {
+      a5a = ((double)a1->field_A - v15->field_2C) * v15->field_4 + v15->field_24 - 0.5;
+      //v20 = a5a + 6.7553994e15;
+      //a5b = (double)SLODWORD(v20);
+      a5b = (double)floorf(a5a + 0.5f);
+      a1a = ((double)a1->field_A - *(float *)(v14 + 44)) * *(float *)(v14 + 4) + *(float *)(v14 + 36) + 0.5;
+      //v21 = a1a + 6.7553994e15;
+      //v22 = (double)SLODWORD(v21);
+      v22 = (double)floorf(a1a + 0.5f);
+      result = v9->field_8;
+      v23 = v9->field_C;
+      v24 = -((a3a - a2a) / (v22 - a5b));
+      v9->field_10 = ((double)result - a5b) * v24 + a3a;
+      v9->field_14 = a2a - (v22 - (double)(result + v23)) * v24;
+    }
+    if ( v9->field_10 < 0.0 || v9->field_10 <= 1.0 )
+    {
+      if ( v9->field_10 >= 0.0 )
+        v25 = v9->field_10;
+      else
+        v25 = 0.0;
+    }
+    else
+    {
+      v25 = 1.0;
+    }
+    v9->field_10 = v25;
+      __debugbreak(); // warning C4700: uninitialized local variable 'v27' used
+    if ( v9->field_14 < 0.0
+      || (v26 = v9->field_14,
+          //UNDEF(v27),
+          v28 = 1.0 < v26,
+          v29 = 0,
+          v30 = 1.0 == v26,
+          BYTE1(result) = HIBYTE(v27),
+          v26 <= 1.0) )
+    {
+      v32 = v9->field_14;
+      //UNDEF(v33);
+      v34 = 0.0 < v32;
+      v35 = 0;
+      v36 = 0.0 == v32;
+      __debugbreak(); // warning C4700: uninitialized local variable 'v33' used
+      BYTE1(result) = HIBYTE(v33);
+      if ( v32 >= 0.0 )
+        v31 = v9->field_14;
+      else
+        v31 = 0.0;
+    }
+    else
+    {
+      v31 = 1.0;
+    }
+    v9->field_14 = v31;
+    LOBYTE(result) = 1;
+  }
+  else
+  {
+    LOBYTE(result) = 0;
+  }
+  return result;
+}
+
+//----- (0045D643) --------------------------------------------------------
+double LightmapBuilder::_45D643_sw(Edge *a1, float a2)
+{
+  double result; // st7@1
+
+  result = (a1->field_1C - a1->field_20) * -1.0 / (a1->field_30 - a1->field_2C) * (a2 - a1->field_2C) + a1->field_1C;
+  if ( result < 0.0 || result <= 1.0 )
+  {
+    if ( result < 0.0 )
+      result = 0.0;
+  }
+  else
+  {
+    result = 1.0;
+  }
+  return result;
+}
+
+
+//  143
+#pragma pack(push, 1)
+struct Span
+{
+  Span *pNext;
+  struct Polygon *pParent;
+  __int16 field_8;
+  __int16 field_A;
+  __int16 field_C;
+  __int16 field_E;
+  float field_10;
+  float field_14;
+};
+#pragma pack(pop)
+
+
+
+//  144
+#pragma pack(push, 1)
+struct Surf
+{
+  float field_0;
+  float field_4;
+  float field_8;
+  float field_C;
+  float field_10;
+  Surf *pNext;
+  Surf *pPrev;
+  struct Polygon *pParent;
+  __int16 field_20;
+  __int16 field_22;
+};
+#pragma pack(pop)
+extern Surf stru_80C980;
+
+
+
+
+//  145
+#pragma pack(push, 1)
+struct Edge
+{
+  float field_0;
+  float field_4;
+  int field_8;
+  Surf *pSurf;
+  Edge *pNext;
+  Edge *pPrev;
+  Edge *ptr_18;
+  float field_1C;
+  float field_20;
+  float field_24;
+  float field_28;
+  float field_2C;
+  float field_30;
+};
+#pragma pack(pop)
+extern Edge defaultEdge; // weak
+
+extern Edge stru_80C9A4;
+extern Edge stru_80C9D8;
+
+
+
+#define INDOOR_CAMERA_DRAW_SW_OUTLINES 1
+#define INDOOR_CAMERA_DRAW_D3D_OUTLINES 2
+#define INDOOR_CAMERA_DRAW_TERRAIN_OUTLINES 4
+//  157
+#pragma pack(push, 1)
+struct IndoorCamera
+{
+  //----- (0042391F) --------------------------------------------------------
+  IndoorCamera()
+  {
+    sRotationX = 0;
+    sRotationY = 0;
+    fov_rad = 2000.0f;
+    fov_rad_inv = 32.768002f;
+
+    flags = 0;
+  }
+  void Initialize(int degFov, unsigned int uViewportWidth, unsigned int uViewportHeight);
+  void Initialize2();
+  float ViewTransform_ODM(struct RenderVertexSoft *a1);
+
+
+  Vec3_int_ pos;
+  unsigned int uMapGridCellX;
+  unsigned int uMapGridCellZ;
+  int sRotationX;
+  int sRotationY;
+  float fov_rad;
+  float fov_rad_inv;
+  int field_24;
+  int field_28;
+  float fRotationYSine;
+  float fRotationYCosine;
+  float fRotationXSine;
+  float fRotationXCosine;
+  int _int_sine;
+  int _int_cosine;
+  int _int_sine_2;
+  int _int_cosine_2;
+  int flags;  // & INDOOR_CAMERA_DRAW_D3D_OUTLINES:  render terrain outlines in d3d
+};
+#pragma pack(pop)
+
+
+
+extern IndoorCamera *pIndoorCamera; // idb
+
+
+IndoorCamera *pIndoorCamera; // idb
+
+
+
+
+
+//----- (00481CCE) --------------------------------------------------------
+float IndoorCamera::ViewTransform_ODM(RenderVertexSoft *a1)
+{
+  float result; // eax@1
+  double vCamToVertexZ; // st7@1
+  double v3; // st6@1
+  double v4; // st5@1
+  double v5; // st4@1
+  float v6; // ST04_4@3
+  float v7; // [sp+0h] [bp-14h]@1
+  float v8; // [sp+8h] [bp-Ch]@1
+  float vCamToVertexX; // [sp+Ch] [bp-8h]@1
+  float vCamToVertexY; // [sp+10h] [bp-4h]@1
+
+  v8 = fRotationXCosine;
+  result = fRotationXSine;
+  v7 = fRotationXSine;
+  vCamToVertexX = a1->vWorldPosition.x - (double)pos.x;
+  vCamToVertexY = a1->vWorldPosition.y - (double)pos.y;
+  vCamToVertexZ = a1->vWorldPosition.z - (double)pos.z;
+  v3 = fRotationYCosine;
+  v4 = fRotationYSine;
+  v5 = vCamToVertexY * fRotationYSine + fRotationYCosine * vCamToVertexX;
+  if ( sRotationX )
+  {
+    v6 = vCamToVertexY * fRotationYSine + fRotationYCosine * vCamToVertexX;
+    a1->vWorldViewPosition.x = v5 * fRotationXCosine + fRotationXSine * vCamToVertexZ;
+    a1->vWorldViewPosition.y = v3 * vCamToVertexY - v4 * vCamToVertexX;
+    a1->vWorldViewPosition.z = v8 * vCamToVertexZ - v6 * v7;
+  }
+  else
+  {
+    a1->vWorldViewPosition.x = vCamToVertexY * fRotationYSine + fRotationYCosine * vCamToVertexX;
+    a1->vWorldViewPosition.y = v3 * vCamToVertexY - v4 * vCamToVertexX;
+    a1->vWorldViewPosition.z = vCamToVertexZ;
+  }
+  return result;
+}
+
+
+
+//----- (0042394D) --------------------------------------------------------
+void IndoorCamera::Initialize(int degFov, unsigned int uViewportWidth, unsigned int uViewportHeight)
+{
+  IndoorCamera *v4; // esi@1
+  double v5; // st7@1
+
+  v4 = this;
+  v5 = (double)(signed int)(signed __int64)((double)(signed int)uViewportWidth
+                                          * 0.5
+                                          / tan((double)(degFov >> 1) * 0.01745329)
+                                          + 0.5);
+  v4->fov_rad = v5;
+  v4->fov_rad_inv = 65536.0 / v5;
+}
+
+//----- (004239A7) --------------------------------------------------------
+void IndoorCamera::Initialize2()
+{
+  //IndoorCamera *v1; // esi@1
+  double v2; // st7@4
+  //double v3; // st7@6
+  //int v4; // eax@6
+  //int v5; // eax@6
+  //int v6; // ST04_4@6
+  //int v7; // eax@6
+  //int v8; // ST04_4@6
+
+  //v1 = this;
+  fRotationYSine = sin((3.141592653589793 + 3.141592653589793) * (double)sRotationY * 0.00048828125);
+  fRotationYCosine = cos((3.141592653589793 + 3.141592653589793) * (double)sRotationY * 0.00048828125);
+  if ( byte_4D864C && pGame->uFlags & 0x80 || uCurrentlyLoadedLevelType == LEVEL_Indoor)
+  {
+    fRotationXSine = sin((3.141592653589793 + 3.141592653589793) * (double)-sRotationX * 0.00048828125);
+    v2 = (3.141592653589793 + 3.141592653589793) * (double)-sRotationX;
+  }
+  else
+  {
+    fRotationXSine = sin((3.141592653589793 + 3.141592653589793) * (double)sRotationX * 0.00048828125);
+    v2 = (3.141592653589793 + 3.141592653589793) * (double)sRotationX;
+  }
+  //v3 = cos(v2 * 0.00048828125);
+  //v4 = sRotationY;
+  fRotationXCosine = cos(v2 * 0.00048828125);
+  //v5 = stru_5C6E00->SinCos(sRotationY - stru_5C6E00->uIntegerHalfPi);
+  //v6 = sRotationY;
+  _int_sine = stru_5C6E00->Sin(sRotationY);
+  _int_cosine = stru_5C6E00->Cos(sRotationY);
+  //v7 = stru_5C6E00->SinCos(sRotationX - stru_5C6E00->uIntegerHalfPi);
+  //v8 = sRotationX;
+  _int_sine_2 = stru_5C6E00->Sin(sRotationX);
+  _int_cosine_2 = stru_5C6E00->Cos(sRotationX);
+}
+//----- (0048600E) --------------------------------------------------------
+void ODMRenderParams::RotationToInts()
+{
+  camera_rotation_y_int_sine   = stru_5C6E00->Sin(pGame->pIndoorCameraD3D->sRotationY);
+  camera_rotation_y_int_cosine = stru_5C6E00->Cos(pGame->pIndoorCameraD3D->sRotationY);
+  camera_rotation_x_int_sine   = stru_5C6E00->Sin(pGame->pIndoorCameraD3D->sRotationX);
+  camera_rotation_x_int_cosine = stru_5C6E00->Cos(pGame->pIndoorCameraD3D->sRotationX);
+}
+
+
+
 const wchar_t *UIMessage2String(UIMessageType msg)
 {
   #define CASE(xxx) case xxx: swprintf(b, wcslen(L"%03X/%s"), L"%03X/%s", msg, L#xxx); return b;
--- a/mm7_1.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/mm7_1.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -52,7 +52,7 @@
   return ((__int64)a1 << 16) / a2;
 }
 
-__int64 fixpoint_mul(int a1, int a2)
+__int64 fixpoint_sub_unknown(int a1, int a2)
 {
   return (((__int64)a1 << 16) * a2) >> 16;
 }
@@ -61,24 +61,16 @@
 //----- (0042EBBE) --------------------------------------------------------
 //----- (004453C0) mm6-----------------------------------------------------
 //----- (004A1760) mm6_chinese---------------------------------------------
-__int64 fixpoint_sub0(int a1, int a2)
+__int64 fixpoint_mul(int a1, int a2)
 {
   return ((__int64)a1 * (__int64)a2) >> 16;
 }
-__int64 fixpoint_sub2(int a1, int a2)
-{
-  signed __int64 v3; // qtt@1
-
-  LODWORD(v3) = a1 << 16;
-  HIDWORD(v3) = a1 >> 16;
-  return v3 / a2;
-}
 
 __int64 fixpoint_dot(int x1, int x2, int y1, int y2, int z1, int z2)
 {
-  return fixpoint_sub0(x1, x2) +
-         fixpoint_sub0(y1, y2) +
-         fixpoint_sub0(z1, z2);
+  return fixpoint_mul(x1, x2) +
+         fixpoint_mul(y1, y2) +
+         fixpoint_mul(z1, z2);
 }
 
 //----- (0041D20D) --------------------------------------------------------
--- a/mm7_2.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/mm7_2.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -12,7 +12,6 @@
 #include "VideoPlayer.h"
 #include "Sprites.h"
 #include "BSPModel.h"
-#include "OutdoorCamera.h"
 
 #include "LightmapBuilder.h"
 #include "DecalBuilder.h"
@@ -31,7 +30,7 @@
 #include "Party.h"
 #include "AudioPlayer.h"
 #include "Outdoor.h"
-#include "IndoorCamera.h"
+#include "Outdoor_stuff.h"
 #include "Overlays.h"
 #include "Arcomage.h"
 #include "LOD.h"
@@ -1344,15 +1343,15 @@
     v6->pMonsterInfo.uExp = 0;
     v6->uMovementSpeed = v9;
     v10 = rand() % 2048;
-    //v11 = pParty->vPosition.x + fixpoint_sub0(stru_5C6E00->Cos(v10), v19);
+    //v11 = pParty->vPosition.x + fixpoint_mul(stru_5C6E00->Cos(v10), v19);
     uFaceID = stru_5C6E00->Sin(v10);
     //v12 = pParty->vPosition.y;
-    //v13 = fixpoint_sub0(uFaceID, v19);
-    //v14 = pParty->vPosition.y + fixpoint_sub0(uFaceID, v19);
+    //v13 = fixpoint_mul(uFaceID, v19);
+    //v14 = pParty->vPosition.y + fixpoint_mul(uFaceID, v19);
     //LOWORD(v12) = v22;
-    v6->vInitialPosition.x = pParty->vPosition.x + fixpoint_sub0(stru_5C6E00->Cos(v10), v19);
+    v6->vInitialPosition.x = pParty->vPosition.x + fixpoint_mul(stru_5C6E00->Cos(v10), v19);
     v6->vPosition.x = v6->vInitialPosition.x;
-    v6->vInitialPosition.y = pParty->vPosition.y + fixpoint_sub0(uFaceID, v19);
+    v6->vInitialPosition.y = pParty->vPosition.y + fixpoint_mul(uFaceID, v19);
     v6->vPosition.y = v6->vInitialPosition.y;
     v6->vInitialPosition.z = pParty->vPosition.z;
     v6->vPosition.z = v6->vInitialPosition.z;
@@ -2874,10 +2873,10 @@
 }
 
 //----- (004610AA) --------------------------------------------------------
-void __fastcall PrepareToLoadODM(unsigned int bLoading, OutdoorCamera *a2)
+void __fastcall PrepareToLoadODM(unsigned int bLoading, ODMRenderParams *a2)
 {
   unsigned int v2; // edi@1
-  OutdoorCamera *v3; // esi@1
+  ODMRenderParams *v3; // esi@1
 
   v2 = bLoading;
   v3 = a2;
@@ -2893,7 +2892,7 @@
 // 6BE35C: using guessed type int uLevel_StartingPointType;
 
 //----- (00461103) --------------------------------------------------------
-void  _461103_load_level_sub()
+void _461103_load_level_sub()
 {
   //GUIProgressBar *v0; // ebx@1
   //signed int v1; // ebp@1
@@ -3050,13 +3049,13 @@
   init_event_triggers();
 
   pGameLoadingUI_ProgressBar->Progress();
-
-  pIndoorCamera->pos.y = 0;
-  pIndoorCamera->pos.x = 0;
-  pIndoorCamera->pos.z = 100;
-  pIndoorCamera->sRotationY = 0;
-  pIndoorCamera->sRotationX = 0;
-  viewparams->bRedrawGameUI = 1;
+  
+  pGame->pIndoorCameraD3D->vPartyPos.x = 0;
+  pGame->pIndoorCameraD3D->vPartyPos.y = 0;
+  pGame->pIndoorCameraD3D->vPartyPos.z = 100;
+  pGame->pIndoorCameraD3D->sRotationX = 0;
+  pGame->pIndoorCameraD3D->sRotationY = 0;
+  viewparams->bRedrawGameUI = true;
   uLevel_StartingPointType = MapStartPoint_Party;
   pSprites_LOD->_461397();
   pPaletteManager->LockTestAll();
@@ -3822,9 +3821,9 @@
   pViewport->SetScreen(viewparams->uSomeX, viewparams->uSomeY, viewparams->uSomeZ, viewparams->uSomeW);
   pViewport->_4C02F8((signed __int64)(flt_6BE3A0 * 65536.0));
 
-  pIndoorCamera = new IndoorCamera;
-  pIndoorCamera->Initialize(65, viewparams->uScreen_BttmR_X - viewparams->uScreen_topL_X + 1,
-                                viewparams->uScreen_BttmR_Y - viewparams->uScreen_topL_Y + 1);
+  //pIndoorCamera = new IndoorCamera;
+  //pIndoorCamera->Initialize(65, viewparams->uScreen_BttmR_X - viewparams->uScreen_topL_X + 1,
+  //                              viewparams->uScreen_BttmR_Y - viewparams->uScreen_topL_Y + 1);
 
   InitializeTurnBasedAnimations(&stru_50C198);
   pBitmaps_LOD->_inlined_sub1();
@@ -5023,7 +5022,7 @@
   assert(sizeof(BLVLightMM7) == 0x10);
   assert(sizeof(BLVDoor) == 0x50);
   assert(sizeof(IndoorLocation) == 0x690);
-  assert(sizeof(OutdoorCamera) == 0x74);
+  //assert(sizeof(ODMRenderParams) == 0x74);
   assert(sizeof(Mouse) == 0x114);
   assert(sizeof(Particle_sw) == 0x68);
   assert(sizeof(Particle) == 0x68);
@@ -5037,7 +5036,7 @@
   assert(sizeof(stru6) == 0x5F8);
   assert(sizeof(IndoorCameraD3D_Vec3) == 0x10);
   assert(sizeof(IndoorCameraD3D_Vec4) == 0x18); //should be 14 (10 vec3 + 4 vdtor)  but 18 coz of his +4 from own vdtor, but it is odd since vdtor already present from vec3
-  assert(sizeof(IndoorCameraD3D) == 0x1A1384);
+  //assert(sizeof(IndoorCameraD3D) == 0x1A1384);
   assert(sizeof(StationaryLight) == 0xC);
   assert(sizeof(LightsStack_StationaryLight_) == 0x12C8);
   assert(sizeof(MobileLight) == 0x12);
@@ -5050,7 +5049,7 @@
   assert(sizeof(BspRenderer) == 0x53740);
   assert(sizeof(PaletteManager) == 0x267AF0);
   assert(sizeof(ViewingParams) == 0x26C);
-  assert(sizeof(IndoorCamera) == 0x50);
+  //assert(sizeof(IndoorCamera) == 0x50);
   assert(sizeof(Bloodsplat) == 0x28);
   assert(sizeof(BloodsplatContainer) == 0xA0C);
   assert(sizeof(TrailParticle) == 0x18);
@@ -5362,7 +5361,7 @@
     while ( v9 < v2 );
   }
 
-  pOutdoorCamera = new OutdoorCamera;
+  pODMRenderParams = new ODMRenderParams;
   outdoor_day_top_r      = GetPrivateProfileIntW(L"outdoor", L"RGBDayTop.r", 81, pIniFilename);
   outdoor_day_top_g      = GetPrivateProfileIntW(L"outdoor", L"RGBDayTop.g", 121, pIniFilename);
   outdoor_day_top_b      = GetPrivateProfileIntW(L"outdoor", L"RGBDayTop.b", 236, pIniFilename);
@@ -5375,24 +5374,24 @@
   outdoor_night_bottom_r = GetPrivateProfileIntW(L"outdoor", L"RGBNightBottom.r", 11, pIniFilename);
   outdoor_night_bottom_g = GetPrivateProfileIntW(L"outdoor", L"RGBNightBottom.g", 41, pIniFilename);
   outdoor_night_bottom_b = GetPrivateProfileIntW(L"outdoor", L"RGBNightBottom.b", 129, pIniFilename);
-  pOutdoorCamera->outdoor_no_mist = GetPrivateProfileIntW(L"debug", L"noMist", 0, pIniFilename);
-  pOutdoorCamera->bNoSky          = GetPrivateProfileIntW(L"outdoor", L"nosky", 0, pIniFilename);
-  pOutdoorCamera->bDoNotRenderDecorations = GetPrivateProfileIntW(L"render", L"nodecorations", 0, pIniFilename);
-  pOutdoorCamera->outdoor_no_wavy_water   = GetPrivateProfileIntW(L"outdoor", L"nowavywater", 0, pIniFilename);
+  pODMRenderParams->outdoor_no_mist = GetPrivateProfileIntW(L"debug", L"noMist", 0, pIniFilename);
+  pODMRenderParams->bNoSky          = GetPrivateProfileIntW(L"outdoor", L"nosky", 0, pIniFilename);
+  pODMRenderParams->bDoNotRenderDecorations = GetPrivateProfileIntW(L"render", L"nodecorations", 0, pIniFilename);
+  pODMRenderParams->outdoor_no_wavy_water   = GetPrivateProfileIntW(L"outdoor", L"nowavywater", 0, pIniFilename);
   outdoor_grid_band_1 = GetPrivateProfileIntW(L"outdoor", L"gridband1", 10, pIniFilename);
   outdoor_grid_band_2 = GetPrivateProfileIntW(L"outdoor", L"gridband2", 15, pIniFilename);
   outdoor_grid_band_3 = GetPrivateProfileIntW(L"outdoor", L"gridband3", 25, pIniFilename);
-  pOutdoorCamera->terrain_gamma  = GetPrivateProfileIntW(L"outdoor", L"ter_gamma", 0, pIniFilename);
-  pOutdoorCamera->building_gamme = GetPrivateProfileIntW(L"outdoor", L"bld_gamma", 0, pIniFilename);
+  pODMRenderParams->terrain_gamma  = GetPrivateProfileIntW(L"outdoor", L"ter_gamma", 0, pIniFilename);
+  pODMRenderParams->building_gamme = GetPrivateProfileIntW(L"outdoor", L"bld_gamma", 0, pIniFilename);
   mipmapping_terrain_mm1  = GetPrivateProfileIntW(L"mipmapping", L"ter_mm1", 2048, pIniFilename);
   mipmapping_terrain_mm2  = GetPrivateProfileIntW(L"mipmapping", L"ter_mm2", 4096, pIniFilename);
   mipmapping_terrain_mm3  = GetPrivateProfileIntW(L"mipmapping", L"ter_mm3", 8192, pIniFilename);
   mipmapping_building_mm1 = GetPrivateProfileIntW(L"mipmapping", L"bld_mm1", 1024, pIniFilename);
   mipmapping_building_mm2 = GetPrivateProfileIntW(L"mipmapping", L"bld_mm2", 2048, pIniFilename);
   mipmapping_building_mm3 = GetPrivateProfileIntW(L"mipmapping", L"bld_mm3", 4096, pIniFilename);
-  pOutdoorCamera->shading_dist_shade     = GetPrivateProfileIntW(L"shading", L"dist_shade", 2048, pIniFilename);
-  pOutdoorCamera->shading_dist_shademist = GetPrivateProfileIntW(L"shading", L"dist_shademist", 4096, pIniFilename);
-  pOutdoorCamera->shading_dist_mist      = GetPrivateProfileIntW(L"shading", L"dist_mist", 8192, pIniFilename);
+  pODMRenderParams->shading_dist_shade     = GetPrivateProfileIntW(L"shading", L"dist_shade", 2048, pIniFilename);
+  pODMRenderParams->shading_dist_shademist = GetPrivateProfileIntW(L"shading", L"dist_shademist", 4096, pIniFilename);
+  pODMRenderParams->shading_dist_mist      = GetPrivateProfileIntW(L"shading", L"dist_mist", 8192, pIniFilename);
 
   wchar_t pDefaultSkyTextureW[1024];
   GetPrivateProfileStringW(L"textures", L"sky", L"plansky1", pDefaultSkyTextureW, 0x10u, pIniFilename);
@@ -5452,25 +5451,25 @@
       outdoor_grid_band_1 = 10;
       outdoor_grid_band_2 = 15;
       outdoor_grid_band_3 = 20;
-      pOutdoorCamera->shading_dist_mist = 8192;
-      pOutdoorCamera->bNoSky = false;
+      pODMRenderParams->shading_dist_mist = 8192;
+      pODMRenderParams->bNoSky = false;
       LOBYTE(viewparams->field_20) = 0;
     }
     mipmapping_terrain_mm1 = 1024;
     mipmapping_terrain_mm2 = 2048;
     mipmapping_building_mm1 = 1024;
     mipmapping_building_mm2 = 2048;
-    pOutdoorCamera->shading_dist_shade = 2048;
-    pOutdoorCamera->terrain_gamma = 0;
-    pOutdoorCamera->building_gamme = 0;
+    pODMRenderParams->shading_dist_shade = 2048;
+    pODMRenderParams->terrain_gamma = 0;
+    pODMRenderParams->building_gamme = 0;
     mipmapping_terrain_mm3 = 4096;
     mipmapping_building_mm3 = 4096;
-    pOutdoorCamera->shading_dist_shademist = 4096;
-    pOutdoorCamera->outdoor_no_wavy_water = 0;
+    pODMRenderParams->shading_dist_shademist = 4096;
+    pODMRenderParams->outdoor_no_wavy_water = 0;
     //_47F4D3_initialize_terrain_bezier_stuff(outdoor_grid_band_1, outdoor_grid_band_2, outdoor_grid_band_3);
     {
-      pOutdoorCamera->outdoor_grid_band_3 = outdoor_grid_band_3;
-      pOutdoorCamera->uPickDepth = outdoor_grid_band_3 * 512;
+      pODMRenderParams->outdoor_grid_band_3 = outdoor_grid_band_3;
+      pODMRenderParams->uPickDepth = outdoor_grid_band_3 * 512;
     }
   }
   else
@@ -5485,7 +5484,7 @@
 
   pViewport->SetScreen(viewparams->uScreen_topL_X, viewparams->uScreen_topL_Y, viewparams->uScreen_BttmR_X, viewparams->uScreen_BttmR_Y);
   if ( uCurrentlyLoadedLevelType == LEVEL_Outdoor )
-    pOutdoorCamera->_485F64();
+    pODMRenderParams->Initialize();
 }
 
 //----- (00466C40) --------------------------------------------------------
--- a/mm7_3.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/mm7_3.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -7,7 +7,6 @@
 #include "mm7_data.h"
 #include "Sprites.h"
 #include "BSPModel.h"
-#include "OutdoorCamera.h"
 #include "LightmapBuilder.h"
 #include "DecalBuilder.h"
 #include "ParticleEngine.h"
@@ -24,7 +23,6 @@
 #include "AudioPlayer.h"
 #include "Outdoor.h"
 #include "Outdoor_stuff.h"
-#include "IndoorCamera.h"
 #include "Overlays.h"
 #include "LOD.h"
 #include "Actor.h"
@@ -796,22 +794,22 @@
   else
     v7 = pEventTimer->dt_in_some_format;
 
-  v8 = fixpoint_sub0(v7, speed) - v2->field_70; // speed * dt - something
+  v8 = fixpoint_mul(v7, speed) - v2->field_70; // speed * dt - something
   v2->field_6C = v8;
   if ( v8 > 0 )
   {
-    v10 = fixpoint_sub0(v8, v2->direction.x) + v2->normal.x;
+    v10 = fixpoint_mul(v8, v2->direction.x) + v2->normal.x;
     v2->field_4C = v10;
     v2->normal2.x = v10;
-    v11 = fixpoint_sub0(v2->field_6C, v2->direction.y) + v2->normal.y;
+    v11 = fixpoint_mul(v2->field_6C, v2->direction.y) + v2->normal.y;
     v2->field_50 = v11;
     v2->normal2.y = v11;
-    v2->normal2.z = fixpoint_sub0(v2->field_6C, v2->direction.z) + v2->normal.z;
+    v2->normal2.z = fixpoint_mul(v2->field_6C, v2->direction.z) + v2->normal.z;
     v12 = v2->position.z;
     v13 = v2->normal.x;
     v14 = v2->normal2.x;
     v15 = v2->prolly_normal_d;
-    v16 = v12 + fixpoint_sub0(v2->field_6C, v2->direction.z);
+    v16 = v12 + fixpoint_mul(v2->field_6C, v2->direction.z);
     v28 = v16;
     v2->field_54 = v16;
     v17 = v13;
@@ -993,21 +991,21 @@
       if ( v8 > 1000 )
         v8 = 1000;
 
-      v0->vVelocity.x = fixpoint_sub0(stru_5C6E00->Cos(v0->uYawAngle), v8);
-      v0->vVelocity.y = fixpoint_sub0(stru_5C6E00->Sin(v0->uYawAngle), v8);
+      v0->vVelocity.x = fixpoint_mul(stru_5C6E00->Cos(v0->uYawAngle), v8);
+      v0->vVelocity.y = fixpoint_mul(stru_5C6E00->Sin(v0->uYawAngle), v8);
       if ( uIsFlying )
       {
-        v0->vVelocity.z = fixpoint_sub0(stru_5C6E00->Sin(v0->uPitchAngle), v8);
+        v0->vVelocity.z = fixpoint_mul(stru_5C6E00->Sin(v0->uPitchAngle), v8);
       }
       //v7 = v68;
     }
     else
     {
-      v0->vVelocity.x = fixpoint_sub0(55000, v0->vVelocity.x);
-      v0->vVelocity.y = fixpoint_sub0(55000, v0->vVelocity.y);
+      v0->vVelocity.x = fixpoint_mul(55000, v0->vVelocity.x);
+      v0->vVelocity.y = fixpoint_mul(55000, v0->vVelocity.y);
       if ( uIsFlying )
       {
-        v0->vVelocity.z = fixpoint_sub0(55000, v0->vVelocity.z);
+        v0->vVelocity.z = fixpoint_mul(55000, v0->vVelocity.z);
       }
     }
     if ( v0->vPosition.z < v5 )
@@ -1030,9 +1028,9 @@
         v0->vVelocity.z += -8 * LOWORD(pEventTimer->uTimeElapsed) * v20;
         int v73 = abs(v62.x * v0->vVelocity.x + v62.z * v0->vVelocity.z + v62.y * v0->vVelocity.y) >> 16;
         //v72b = v21;
-        v0->vVelocity.x += fixpoint_sub0(v73, v62.x);
-        v0->vVelocity.y += fixpoint_sub0(v73, v62.y);
-        v0->vVelocity.z += fixpoint_sub0(v73, v62.z);
+        v0->vVelocity.x += fixpoint_mul(v73, v62.x);
+        v0->vVelocity.y += fixpoint_mul(v73, v62.y);
+        v0->vVelocity.z += fixpoint_mul(v73, v62.z);
         //v17 = 0;
       }
     }
@@ -1099,7 +1097,7 @@
       }
       v71 = i > 1;
       if ( stru_721530.field_7C < stru_721530.field_6C )
-        v70 = fixpoint_sub0(stru_721530.field_7C, stru_721530.direction.z);
+        v70 = fixpoint_mul(stru_721530.field_7C, stru_721530.direction.z);
       //v34 = 0;
       v35 = stru_721530.normal2.z - stru_721530.prolly_normal_d - 1;
       v36 = ODM_GetFloorLevel(stru_721530.normal2.x,
@@ -1132,12 +1130,12 @@
         v0->vPosition.z = LOWORD(stru_721530.normal2.z) - LOWORD(stru_721530.prolly_normal_d) - 1;
         break;
       }
-      //v72b = fixpoint_sub0(stru_721530.field_7C, stru_721530.field_58.x);
-      v0->vPosition.x += fixpoint_sub0(stru_721530.field_7C, stru_721530.direction.x);
+      //v72b = fixpoint_mul(stru_721530.field_7C, stru_721530.field_58.x);
+      v0->vPosition.x += fixpoint_mul(stru_721530.field_7C, stru_721530.direction.x);
       //v72b = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.y) >> 16;
-      v0->vPosition.y += fixpoint_sub0(stru_721530.field_7C, stru_721530.direction.y);
+      v0->vPosition.y += fixpoint_mul(stru_721530.field_7C, stru_721530.direction.y);
       //v72b = (unsigned __int64)(stru_721530.field_7C * (signed __int64)stru_721530.field_58.z) >> 16;
-      v0->vPosition.z += fixpoint_sub0(stru_721530.field_7C, stru_721530.direction.z);
+      v0->vPosition.z += fixpoint_mul(stru_721530.field_7C, stru_721530.direction.z);
       v38 = stru_721530.uFaceID;
       stru_721530.field_70 += stru_721530.field_7C;
 	  v39 = PID_ID(v38);
@@ -1195,8 +1193,8 @@
                   v0->vPosition.x - pLevelDecorations[v39].vPosition.x,
                   v0->vPosition.y - pLevelDecorations[v39].vPosition.y);
           v49 = v48;
-          v0->vVelocity.x = fixpoint_sub0(stru_5C6E00->Cos(v48), v47);
-          v0->vVelocity.y = fixpoint_sub0(stru_5C6E00->Sin(v48), v47);
+          v0->vVelocity.x = fixpoint_mul(stru_5C6E00->Cos(v48), v47);
+          v0->vVelocity.y = fixpoint_mul(stru_5C6E00->Sin(v48), v47);
           break;
         case OBJECT_BModel:
           v40 = &pOutdoor->pBModels[v38 >> 9];
@@ -1223,9 +1221,9 @@
               if ( (stru_721530.speed >> 3) > v72b )
                 v72b = stru_721530.speed >> 3;
 
-              v0->vVelocity.x += fixpoint_sub0(v72b, v41->pFacePlane.vNormal.x);
-              v0->vVelocity.y += fixpoint_sub0(v72b, v41->pFacePlane.vNormal.y);
-              v0->vVelocity.z += fixpoint_sub0(v72b, v41->pFacePlane.vNormal.z);
+              v0->vVelocity.x += fixpoint_mul(v72b, v41->pFacePlane.vNormal.x);
+              v0->vVelocity.y += fixpoint_mul(v72b, v41->pFacePlane.vNormal.y);
+              v0->vVelocity.z += fixpoint_mul(v72b, v41->pFacePlane.vNormal.z);
               if ( v42 != 4 )
               {
                 v45 = v0->vPosition.z;
@@ -1247,9 +1245,9 @@
           break;
       }
 
-      v0->vVelocity.x = fixpoint_sub0(58500, v0->vVelocity.x);
-      v0->vVelocity.y = fixpoint_sub0(58500, v0->vVelocity.y);
-      v0->vVelocity.z = fixpoint_sub0(58500, v0->vVelocity.z);
+      v0->vVelocity.x = fixpoint_mul(58500, v0->vVelocity.x);
+      v0->vVelocity.y = fixpoint_mul(58500, v0->vVelocity.y);
+      v0->vVelocity.z = fixpoint_mul(58500, v0->vVelocity.z);
 
       ++v69;
       if ( v69 >= 100 )
@@ -1698,37 +1696,37 @@
         break;
 
       case PARTY_StrafeLeft:
-        v2 -= fixpoint_sub0(stru_5C6E00->Sin(angle), v81 * fWalkSpeedMultiplier / 2);
-        v1 += fixpoint_sub0(stru_5C6E00->Cos(angle), v81 * fWalkSpeedMultiplier / 2);
+        v2 -= fixpoint_mul(stru_5C6E00->Sin(angle), v81 * fWalkSpeedMultiplier / 2);
+        v1 += fixpoint_mul(stru_5C6E00->Cos(angle), v81 * fWalkSpeedMultiplier / 2);
         v78 = 1;
         break;
       case PARTY_StrafeRight:
-        v2 += fixpoint_sub0(stru_5C6E00->Sin(angle), v81 * fWalkSpeedMultiplier / 2);
-        v1 -= fixpoint_sub0(stru_5C6E00->Cos(angle), v81 * fWalkSpeedMultiplier / 2);
+        v2 += fixpoint_mul(stru_5C6E00->Sin(angle), v81 * fWalkSpeedMultiplier / 2);
+        v1 -= fixpoint_mul(stru_5C6E00->Cos(angle), v81 * fWalkSpeedMultiplier / 2);
         v78 = 1;
         break;
       case PARTY_WalkForward:
-        v2 += fixpoint_sub0(stru_5C6E00->Cos(angle), 5 * v81 * fWalkSpeedMultiplier);
-        v1 += fixpoint_sub0(stru_5C6E00->Sin(angle), 5 * v81 * fWalkSpeedMultiplier);
+        v2 += fixpoint_mul(stru_5C6E00->Cos(angle), 5 * v81 * fWalkSpeedMultiplier);
+        v1 += fixpoint_mul(stru_5C6E00->Sin(angle), 5 * v81 * fWalkSpeedMultiplier);
         v78 = 1;
         break;
       case PARTY_WalkBackward:
-        v2 -= fixpoint_sub0(stru_5C6E00->Cos(angle), v81 * fBackwardWalkSpeedMultiplier);
-        v1 -= fixpoint_sub0(stru_5C6E00->Sin(angle), v81 * fBackwardWalkSpeedMultiplier);
+        v2 -= fixpoint_mul(stru_5C6E00->Cos(angle), v81 * fBackwardWalkSpeedMultiplier);
+        v1 -= fixpoint_mul(stru_5C6E00->Sin(angle), v81 * fBackwardWalkSpeedMultiplier);
         v78 = 1;
         break;
       case PARTY_RunForward:
-        v2 += fixpoint_sub0(stru_5C6E00->Cos(angle), 2 * v81 * fWalkSpeedMultiplier);
-        v1 += fixpoint_sub0(stru_5C6E00->Sin(angle), 2 * v81 * fWalkSpeedMultiplier);
+        v2 += fixpoint_mul(stru_5C6E00->Cos(angle), 2 * v81 * fWalkSpeedMultiplier);
+        v1 += fixpoint_mul(stru_5C6E00->Sin(angle), 2 * v81 * fWalkSpeedMultiplier);
         v72 = 1;
         break;
       case PARTY_RunBackward:
         //v32 = stru_5C6E00->SinCos(angle);
         //v33 = (double)v81;
         //v88 = (double)v81;
-        v2 -= fixpoint_sub0(stru_5C6E00->Cos(angle), v81 * fBackwardWalkSpeedMultiplier);
+        v2 -= fixpoint_mul(stru_5C6E00->Cos(angle), v81 * fBackwardWalkSpeedMultiplier);
         //v34 = stru_5C6E00->SinCos(angle - stru_5C6E00->uIntegerHalfPi);
-        v1 -= fixpoint_sub0(stru_5C6E00->Sin(angle), v81 * fBackwardWalkSpeedMultiplier);
+        v1 -= fixpoint_mul(stru_5C6E00->Sin(angle), v81 * fBackwardWalkSpeedMultiplier);
         v72 = 1;
         break;
       case PARTY_LookUp:
@@ -2695,10 +2693,10 @@
     }
     else
     {
-      _angle_x = pX + fixpoint_sub0(stru_721530.field_7C, stru_721530.direction.x);
-      _angle_y = pY + fixpoint_sub0(stru_721530.field_7C, stru_721530.direction.y);
-      pModel = (BSPModel *)fixpoint_sub0(stru_721530.field_7C, stru_721530.direction.z);
-      v40 = fixpoint_sub0(stru_721530.field_7C, stru_721530.direction.z) + pZ;
+      _angle_x = pX + fixpoint_mul(stru_721530.field_7C, stru_721530.direction.x);
+      _angle_y = pY + fixpoint_mul(stru_721530.field_7C, stru_721530.direction.y);
+      pModel = (BSPModel *)fixpoint_mul(stru_721530.field_7C, stru_721530.direction.z);
+      v40 = fixpoint_mul(stru_721530.field_7C, stru_721530.direction.z) + pZ;
     }
     v122 = v40;
     ODM_GetFloorLevel(_angle_x, _angle_y, v40, pParty->uPartyHeight, &is_on_water, &bmodel_standing_on_pid, 0);
@@ -4024,7 +4022,7 @@
   float v13; // ST24_4@13
   int v14; // esi@13
   char *v15; // esi@15
-  signed int v16; // eax@16
+  //signed int v16; // eax@16
   __int16 v17; // fps@16
   unsigned __int8 v18; // c2@16
   unsigned __int8 v19; // c3@16
@@ -4063,41 +4061,41 @@
         v4 = *(float *)(v3 - 4);
         LODWORD(v37) = *(int *)v3;
         LODWORD(v36) = *(int *)(v3 + 4);
-        if ( pBLVRenderParams->sPartyRotX )
+        if (pGame->pIndoorCameraD3D->sRotationX)
         {
-          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;
-          }
+          v5 = v4 - (double)pGame->pIndoorCameraD3D->vPartyPos.x;
+          v6 = v37 - (double)pGame->pIndoorCameraD3D->vPartyPos.y;
+          //if ( pRenderer->pRenderD3D )
+          //{
+            v41 = pGame->pIndoorCameraD3D->fRotationYSine * v6 + pGame->pIndoorCameraD3D->fRotationYCosine * v5;
+            v7 = pGame->pIndoorCameraD3D->fRotationYSine * v5 - pGame->pIndoorCameraD3D->fRotationYCosine * 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;
+          v9 = v36 - (double)pGame->pIndoorCameraD3D->vPartyPos.z;
+          v10 = pGame->pIndoorCameraD3D->fRotationXCosine * v41 - pGame->pIndoorCameraD3D->fRotationXSine * v9;
           v11 = v8;
-          v12 = pBLVRenderParams->fCosineNegX * v9 + pBLVRenderParams->fSineNegX * v41;
+          v12 = pGame->pIndoorCameraD3D->fRotationXCosine * v9 + pGame->pIndoorCameraD3D->fRotationXSine * 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;
-          }
+          v42 = v4 - (double)pGame->pIndoorCameraD3D->vPartyPos.x;
+          v39 = v37 - (double)pGame->pIndoorCameraD3D->vPartyPos.y;
+          //if ( pRenderer->pRenderD3D )
+          //{
+            v10 = pGame->pIndoorCameraD3D->fRotationYSine * v39 + pGame->pIndoorCameraD3D->fRotationYCosine * v42;
+            v11 = pGame->pIndoorCameraD3D->fRotationYSine * v42 - pGame->pIndoorCameraD3D->fRotationYCosine * v39;
+          /*}
           else
           {
             v10 = pBLVRenderParams->fCosineY * v42 - pBLVRenderParams->fSineY * v39;
             v11 = pBLVRenderParams->fSineY * v42 + pBLVRenderParams->fCosineY * v39;
-          }
-          v12 = v36 - (double)pBLVRenderParams->vPartyPos.z;
+          }*/
+          v12 = v36 - (double)pGame->pIndoorCameraD3D->vPartyPos.z;
         }
         v13 = v12;
         ++v2;
@@ -4117,29 +4115,29 @@
     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);
+      v40 = (double)stru_5C6E00->Cos(pGame->pIndoorCameraD3D->sRotationX) * 0.0000152587890625;
+      v32 = (double)stru_5C6E00->Sin(pGame->pIndoorCameraD3D->sRotationX) * 0.0000152587890625;
+      v34 = (double)stru_5C6E00->Cos(pGame->pIndoorCameraD3D->sRotationY) * 0.0000152587890625;
+      v33 = (double)stru_5C6E00->Sin(pGame->pIndoorCameraD3D->sRotationY) * 0.0000152587890625;
+      //v16 = stru_5C6E00->Sin(pODMRenderParams->rotation_y);
       LODWORD(v38) = *(int *)v15;
-      v33 = (double)v16 * 0.0000152587890625;
       //UNDEF(v17);
-      v20 = *((float *)v15 - 1) - (double)pIndoorCamera->pos.x;
+      v20 = *((float *)v15 - 1) - (double)pGame->pIndoorCameraD3D->vPartyPos.x;
       //if ( v19 | v18 )
-	  if(pIndoorCamera->pos.x == 0)
+	  if (pGame->pIndoorCameraD3D->vPartyPos.x == 0)
       {
         v27 = v20;
         LODWORD(v35) = *((int *)v15 + 1);
-        v28 = v38 - (double)pIndoorCamera->pos.y;
+        v28 = v38 - (double)pGame->pIndoorCameraD3D->vPartyPos.y;
         v25 = v33 * v28 + v34 * v27;
         v26 = v34 * v28 - v33 * v27;
       }
       else
       {
         v21 = v20;
-        v22 = v38 - (double)pIndoorCamera->pos.y;
+        v22 = v38 - (double)pGame->pIndoorCameraD3D->vPartyPos.y;
         v23 = v33 * v22 + v34 * v21;
-        v24 = *((float *)v15 + 1) - (double)pIndoorCamera->pos.z;
+        v24 = *((float *)v15 + 1) - (double)pGame->pIndoorCameraD3D->vPartyPos.z;
         v25 = v32 * v24 + v40 * v23;
         v26 = v34 * v22 - v33 * v21;
         v35 = v40 * v24 - v32 * v23;
@@ -4179,11 +4177,11 @@
   if ( uCurrentlyLoadedLevelType == LEVEL_Indoor )
   {
     v10 = 16192.0;
-    v3 = (double)pBLVRenderParams->field_40 * 0.000015258789;
+    v3 = (double)pBLVRenderParams->fov_rad_fixpoint * 0.000015258789;
   }
   else
   {
-    v10 = (double)pOutdoorCamera->shading_dist_mist;
+    v10 = (double)pODMRenderParams->shading_dist_mist;
     v3 = 8.0;
   }
   v4 = a1->uNumVertices;
@@ -4238,7 +4236,7 @@
   {
 	for(int i = 0; i < a1->uNumVertices; i++)
     {
-		v6 = (double)pBLVRenderParams->field_40 * 0.000015258789 / a1->field_B4[i*4];
+		v6 = (double)pBLVRenderParams->fov_rad_fixpoint * 0.000015258789 / a1->field_B4[i*4];
 		if ( pRenderer->pRenderD3D )
 		{
 			pGame->pIndoorCameraD3D->Project(
@@ -4269,7 +4267,7 @@
   {
 	for(int i = 0; i < a1->uNumVertices; i++)
     {
-		v12 = (double)pOutdoorCamera->int_fov_rad / a1->field_B4[i*4];
+		v12 = (double)pODMRenderParams->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];
@@ -4292,16 +4290,16 @@
   BSPModel *v2; // ebx@4
   int v3; // eax@6
   ODMFace *pFace; // esi@6
-  Vec3_int_ *v5; // ecx@8
+  //Vec3_int_ *v5; // ecx@8
   int v6; // eax@8
   struct Polygon *v7; // ebx@8
-  LightmapBuilder *v8; // eax@8
+  //LightmapBuilder *v8; // eax@8
   int v9; // ecx@8
-  char v10; // zf@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 v13; // eax@14
+  //unsigned int v14; // eax@18
   unsigned int v15; // eax@22
   unsigned int v16; // edi@22
   int v17; // eax@24
@@ -4338,7 +4336,7 @@
   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
+  //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
@@ -4390,53 +4388,44 @@
       if (pFace->Invisible())
         goto LABEL_85;
       //v5 = (int)*(v2 - 1);
-	  v5 = v2->pVertices.pVertices;
       v6 = pFace->pVertexIDs[0];
       v53 = 0;
-      v7 = &array_77EC08[pOutdoorCamera->uNumPolygons];
-	  //v8 = *(LightmapBuilder **)(v5 + 12 * v6 + 8);
-      v8 = (LightmapBuilder *)v5[v6].z;
+      v7 = &array_77EC08[pODMRenderParams->uNumPolygons];
       v7->flags = 0;
       v7->field_32 = 0;
-      pLightmapBuilder = v8;
+      pLightmapBuilder = (LightmapBuilder *)v2->pVertices.pVertices[v6].z;
       v9 = pFace->uTextureID;
-      v10 = (BYTE1(pFace->uAttributes) & 0x40) == 0;
-      v48 = pFace->uTextureID;
-      if ( !v10 )
+      if (pFace->uAttributes & FACE_TEXTURE_FRAME)
       {
-        v48 = pTextureFrameTable->GetFrameTexture(v9, pEventTimer->uTotalGameTimeElapsed);
-        v9 = v48;
+        v9 = pTextureFrameTable->GetFrameTexture(v9, pEventTimer->uTotalGameTimeElapsed);
       }
       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 )
+      if (pFace->uAttributes & FACE_FLUID)
         *(int *)&v7->flags |= 2u;
-      if ( BYTE2(pFace->uAttributes) & 0x40 )
+      if (pFace->uAttributes & FACE_DO_NOT_LIGHT )
         HIBYTE(v7->flags) |= 4u;
-      v13 = pFace->uAttributes;
-      if ( v13 & 4 )
+      if ( pFace->uAttributes & 4 )
       {
         HIBYTE(v7->flags) |= 4u;
       }
       else
       {
-        if ( v13 & 0x20 )
+        if ( pFace->uAttributes & 0x20 )
           HIBYTE(v7->flags) |= 8u;
       }
-      v14 = pFace->uAttributes;
-      if ( BYTE1(v14) & 8 )
+      if (pFace->uAttributes & 0x0800)
       {
         *(int *)&v7->flags |= 0x2000u;
       }
       else
       {
-        if ( v14 & 0x40 )
+        if (pFace->uAttributes & FACE_DONT_CACHE_TEXTURE)
           HIBYTE(v7->flags) |= 0x10u;
       }
       v15 = GetTickCount();
@@ -4520,12 +4509,11 @@
           ++v20;
 		  ++v20b;
 		  ++v20c;
-          v10 = v51-- == 1;
           v52 = v22;
           //*((float *)v19 - 4) = (double)v22 * v44;
 		  (v19-1)->v = (double)v22 * v44;
         }
-        while ( !v10 );
+        while ( !(v51-- == 1) );
         //v23 = (char *)&array_73D150[0].vWorldViewPosition;
 		v23 = array_73D150;
         v51 = uNumVertices;
@@ -4537,7 +4525,7 @@
             ++v53;
           //v47->ViewTransform((RenderVertexSoft *)(v23 - 12), 1u);
 		  pGame->pIndoorCameraD3D->ViewTransform(v23, 1u);
-		  if ( v23->vWorldViewPosition.x < 8.0 || (double)pOutdoorCamera->shading_dist_mist < v23->vWorldViewPosition.x )
+		  if ( v23->vWorldViewPosition.x < 8.0 || (double)pODMRenderParams->shading_dist_mist < v23->vWorldViewPosition.x )
           {
             if ( v23->vWorldViewPosition.x >= 8.0 )
               v49 = 1;
@@ -4576,10 +4564,10 @@
         v7->dimming_level = 0;
       if ( v7->dimming_level > 31 )
         v7->dimming_level = 31;
-      if ( pOutdoorCamera->uNumPolygons >= 1999 + 5000)
+      if ( pODMRenderParams->uNumPolygons >= 1999 + 5000)
         return result;
-      ++pOutdoorCamera->uNumPolygons;
-      ++pOutdoorCamera->field_44;
+      ++pODMRenderParams->uNumPolygons;
+      ++pODMRenderParams->field_44;
       if ( ODMFace::IsBackfaceCulled(pFace, array_73D150, v7) )
       {
         LOBYTE(v25) = (char)v54;
@@ -4656,7 +4644,7 @@
 LABEL_76:
           v7->uNumVertices = v32;
           uNumVertices = v32;
-          OutdoorCamera::Project(v32);
+          ODM_Project(v32);
         }
         if ( uNumVertices )
         {
@@ -4671,14 +4659,14 @@
           }
           else
           {
-            v40 = (int)pBitmaps_LOD->pHardwareTextures[v48];
+            v40 = (int)pBitmaps_LOD->pHardwareTextures[v9];
           }
           pRenderer->DrawPolygon(uNumVertices, v7, pFace, (IDirect3DTexture2 *)v40);
         }
         goto LABEL_85;
       }
-      --pOutdoorCamera->uNumPolygons;
-      --pOutdoorCamera->field_44;
+      --pODMRenderParams->uNumPolygons;
+      --pODMRenderParams->field_44;
 LABEL_85:
       v54 = (Vec3_int_ *)((char *)v54 + 1);
       v2 = v56;
@@ -4719,18 +4707,18 @@
   //int v22; // [sp+28h] [bp-4h]@3
 
   //v16 = unused;
-  angle = (signed int)(pOutdoorCamera->uCameraFovInDegrees << 11) / 360 >> 1;
+  angle = (signed int)(pODMRenderParams->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);
+  v3 = v2->vBoundingCenter.x - pGame->pIndoorCameraD3D->vPartyPos.x;
+  v4 = v2->vBoundingCenter.y - pGame->pIndoorCameraD3D->vPartyPos.y;
+  v5 = stru_5C6E00->Cos(pGame->pIndoorCameraD3D->sRotationY);
+  v21 = stru_5C6E00->Sin(pGame->pIndoorCameraD3D->sRotationY);
+  v18 = stru_5C6E00->Cos(pGame->pIndoorCameraD3D->sRotationX);
+  stru_5C6E00->Sin(pGame->pIndoorCameraD3D->sRotationX);
   v6 = v5;
   v17 = v3 * v5 + v4 * v21;
-  if ( pIndoorCamera->sRotationX )
+  if (pGame->pIndoorCameraD3D->sRotationX)
     v17 = (unsigned __int64)(v17 * (signed __int64)v18) >> 16;
   v19 = v4 * v6 - v3 * v21;
   v7 = abs(v4);
@@ -4747,7 +4735,7 @@
   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 ( v9 <= pODMRenderParams->shading_dist_mist + 2048 )
   {
     //if ( abs(v12) > *(int *)((char *)&pOutdoor->pBModels->sBoundingRadius + v10) + 512 )
 	if ( abs(v12) > pOutdoor->pBModels[uModelID].sBoundingRadius + 512 )
@@ -5136,7 +5124,7 @@
   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_x = 3.141592f * (pODMRenderParams->uCameraFovInDegrees + 0) / 360.0f;
   float fov_y = fov_x / aspect;
 
   float ray_dx = fov_x / (float)pViewport->uScreenWidth,
@@ -5320,11 +5308,11 @@
     return;
   }
 
-  v30 = ((double)(pOutdoorCamera->int_fov_rad * pIndoorCamera->pos.z)
-        / ((double)pOutdoorCamera->int_fov_rad + 8192.0) + pViewport->uScreenCenterY);//184 изменяется при подъёме на высоту
-  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);//61 / 184 / 310 изменяется при наклоне камеры
+  v30 = ((double)(pODMRenderParams->int_fov_rad * pGame->pIndoorCameraD3D->vPartyPos.z)
+        / ((double)pODMRenderParams->int_fov_rad + 8192.0) + pViewport->uScreenCenterY);//184 изменяется при подъёме на высоту
+  v38 = pViewport->uScreenCenterY - pODMRenderParams->int_fov_rad /
+       (pODMRenderParams->shading_dist_mist *  cos(pGame->pIndoorCameraD3D->sRotationX * 0.003066406352445483) + 0.0000001000000011686097) *
+       (pODMRenderParams->shading_dist_mist * -sin(pGame->pIndoorCameraD3D->sRotationX * 0.003066406352445483) - pGame->pIndoorCameraD3D->vPartyPos.z);//61 / 184 / 310 изменяется при наклоне камеры
 
   pSkyPolygon.Create_48607B(&stru_8019C8);
   pSkyPolygon.ptr_38->_48694B_frustum_sky();//maybe creating skydome(возможно создание купола неба)
@@ -5337,9 +5325,9 @@
   pSkyPolygon.uNumVertices = 4;//количество вершин
 
   //centering(центруем)--наклон камеры ----------------------------------------//
-  pSkyPolygon.v_18.x = -stru_5C6E00->Sin(pIndoorCamera->sRotationX + 16);//-3216, вверх: -28020, вниз: 22078
+  pSkyPolygon.v_18.x = -stru_5C6E00->Sin(pGame->pIndoorCameraD3D->sRotationX + 16);//-3216, вверх: -28020, вниз: 22078
   pSkyPolygon.v_18.y = 0;
-  pSkyPolygon.v_18.z = -stru_5C6E00->Cos(pIndoorCamera->sRotationX + 16);//-65457, вверх: -59244, вниз: -61705
+  pSkyPolygon.v_18.z = -stru_5C6E00->Cos(pGame->pIndoorCameraD3D->sRotationX + 16);//-65457, вверх: -59244, вниз: -61705
   //---------------------------------------------------------------------------//
 
   pSkyPolygon.field_24 = 0x2000000;
@@ -5456,16 +5444,16 @@
 
     pShading = fixpoint_div(v34, v38);
     if ( pShading < 0 )
-      pShading = pOutdoorCamera->shading_dist_mist;
+      pShading = pODMRenderParams->shading_dist_mist;
 
     v37 += ((unsigned __int64)(pSkyPolygon.ptr_38->field_10 * v13) >> 16);
     screen_center_x += ((unsigned __int64)(pSkyPolygon.ptr_38->field_1C * v13) >> 16);
-    v35 = 224 * pMiscTimer->uTotalGameTimeElapsed + fixpoint_sub0(v37, pShading) / 8;
-    screen_center_x = 224 * pMiscTimer->uTotalGameTimeElapsed + fixpoint_sub0(screen_center_x, pShading) / 8;
-
-    //array_50AC10[i].vWorldViewPosition.x = pOutdoorCamera->shading_dist_mist;
+    v35 = 224 * pMiscTimer->uTotalGameTimeElapsed + fixpoint_mul(v37, pShading) / 8;
+    screen_center_x = 224 * pMiscTimer->uTotalGameTimeElapsed + fixpoint_mul(screen_center_x, pShading) / 8;
+
+    //array_50AC10[i].vWorldViewPosition.x = pODMRenderParams->shading_dist_mist;
     //array_50AC10[i].vWorldPosition.x = v36 / (pSky.pTexture->uTextureHeight * 65536.0);
-    //array_50AC10[i].vWorldPosition.y = 1.0 / (pOutdoorCamera->shading_dist_mist >> 16);
+    //array_50AC10[i].vWorldPosition.y = 1.0 / (pODMRenderParams->shading_dist_mist >> 16);
     //array_50AC10[i].vWorldPosition.z = v35 / (pSky.pTexture->uTextureWidth * 65536.0);
     //array_50AC10[i]._rhw = 1.0f / (pShading >> 16);
     //array_50AC10[i].u = (double)v35 / (65536.0 * pSkyPolygon.pTexture->uTextureWidth);
@@ -5488,7 +5476,7 @@
 }
 
 //----- (0047A384) --------------------------------------------------------
-void ODM_LoadAndInitialize(const char *pLevelFilename, OutdoorCamera *thisa)
+void ODM_LoadAndInitialize(const char *pLevelFilename, ODMRenderParams *thisa)
 {
   int v2; // ebx@3
   unsigned int v3; // eax@3
@@ -5505,10 +5493,10 @@
 
   pFilename = pLevelFilename;
   //thisa->AllocSoftwareDrawBuffers();
-  pOutdoorCamera->_485F64();
+  pODMRenderParams->Initialize();
   pWeather->bRenderSnow = false;
   pRenderer->ClearZBuffer(0, 479);
-  thisa = (OutdoorCamera *)1;
+  thisa = (ODMRenderParams *)1;
   GetAlertStatus();
   if ( qword_A750D8 )
     qword_A750D8 = 0;
@@ -5539,7 +5527,7 @@
   //v5 = 0;
   if ( !v2 )
     thisa = 0;
-  if ( thisa == (OutdoorCamera *)1 )
+  if ( thisa == (ODMRenderParams *)1 )
   {
     //v13 = 0;
     for (uint i = 0; i < pOutdoor->uNumSpawnPoints; ++i)
@@ -5570,19 +5558,32 @@
   strcpy(Source, &pFilename[v7]);
   strcpy(pOutdoor->pLevelFilename, Source);
   pWeather->Initialize();
-  pIndoorCamera->sRotationY = pParty->sRotationY;
-  pIndoorCamera->sRotationX = pParty->sRotationX;
-  pOutdoorCamera->RotationToInts();
+  pGame->pIndoorCameraD3D->sRotationY = pParty->sRotationY;
+  pGame->pIndoorCameraD3D->sRotationX = pParty->sRotationX;
+  //pODMRenderParams->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;
+
+  float fov_rad;
+  float fov_rad_inv;
+  //----- (0042394D) --------------------------------------------------------
+  //void IndoorCamera::Initialize(int degFov, unsigned int uViewportWidth, unsigned int uViewportHeight)
+  {
+    //pIndoorCamera->Initialize(65, viewparams->uScreen_BttmR_X - viewparams->uScreen_topL_X + 1,
+    //                              viewparams->uScreen_BttmR_Y - viewparams->uScreen_topL_Y + 1);
+
+    int uViewportWidth = viewparams->uScreen_BttmR_X - viewparams->uScreen_topL_X + 1;
+
+    extern float _calc_fov(int viewport_width, int angle_degree);
+    fov_rad = _calc_fov(uViewportWidth, 65);
+    fov_rad_inv = 65536.0 / fov_rad;
+  }
+  pODMRenderParams->int_fov_rad = (signed __int64)fov_rad;
+  pODMRenderParams->int_fov_rad_inv = (signed __int64)fov_rad_inv;
 
   for (int i = 0; i < 20000; ++i)
   {
     array_77EC08[i].ptr_38 = &stru_8019C8;
-    
-    array_77EC08[i].prolly_head = nullptr;
-    array_77EC08[i].prolly_tail = nullptr;
+
     array_77EC08[i].ptr_48 = nullptr;
   }
 
@@ -5806,7 +5807,7 @@
 
     float fog_density_mult = 216.0f;
     if (a4)
-      fog_density_mult += distance / (double)pOutdoorCamera->shading_dist_shade * 32.0;
+      fog_density_mult += distance / (double)pODMRenderParams->shading_dist_shade * 32.0;
 
     v6 = v11 + floorf(pOutdoor->fFogDensity * fog_density_mult + 0.5f);
     /*if ( a4 )
@@ -5817,7 +5818,7 @@
     }
     else
     {
-      //a3a = (distance / (double)pOutdoorCamera->shading_dist_shade * 32.0 + 216.0) * pOutdoor->fFogDensity;
+      //a3a = (distance / (double)pODMRenderParams->shading_dist_shade * 32.0 + 216.0) * pOutdoor->fFogDensity;
       //v13 = a3a + 6.7553994e15;
       //a4a = floorf(a3a + 0.5f);//LODWORD(v13);
     }
@@ -5891,15 +5892,15 @@
 
 
 //----- (00481ED9) --------------------------------------------------------
-void  sub_481ED9_MessWithOutdoorCamera()
+void  sub_481ED9_MessWithODMRenderParams()
 {
   stru_8019C8._48616B_frustum_odm(65536, 0, 0, 0, 65536, 0);
-  pOutdoorCamera->uNumPolygons = 0;
-  pOutdoorCamera->uNumEdges = 0;
-  pOutdoorCamera->uNumSpans = 0;
-  pOutdoorCamera->uNumSurfs = 0;
-  pOutdoorCamera->uNumBillboards = 0;
-  pOutdoorCamera->field_44 = 0;
+  pODMRenderParams->uNumPolygons = 0;
+  //pODMRenderParams->uNumEdges = 0;
+  //pODMRenderParams->uNumSpans = 0;
+  //pODMRenderParams->uNumSurfs = 0;
+  pODMRenderParams->uNumBillboards = 0;
+  pODMRenderParams->field_44 = 0;
 }
 
 //----- (004823F4) --------------------------------------------------------
@@ -6064,7 +6065,7 @@
       v15 = grid_x2 - a1;
       v13 = grid_z1 - a2;
     }
-    return v14 + v8 + fixpoint_sub0(v13, (v10 - v8) * 128) + fixpoint_sub0(v15, (v9 - v8) * 128);
+    return v14 + v8 + fixpoint_mul(v13, (v10 - v8) * 128) + fixpoint_mul(v15, (v9 - v8) * 128);
   }
   else
     return y_x1z1;
@@ -6142,55 +6143,55 @@
   //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;
+  v25 = pGame->pIndoorCameraD3D->int_cosine_x;
+  v7 = pGame->pIndoorCameraD3D->int_sine_y;
+  v27 = pGame->pIndoorCameraD3D->int_sine_x;
   //v8 = -pIndoorCamera->pos.y;
-  v9 = pOutdoorCamera->camera_rotation_y_int_cosine;
+  v9 = pGame->pIndoorCameraD3D->int_cosine_y;
   //v26 = -pIndoorCamera->pos.z;
-  v11 = pOutdoorCamera->camera_rotation_y_int_cosine * -pIndoorCamera->pos.x + pOutdoorCamera->camera_rotation_y_int_sine * -pIndoorCamera->pos.y;
-  v24 = pOutdoorCamera->camera_rotation_y_int_cosine * -pIndoorCamera->pos.y - pOutdoorCamera->camera_rotation_y_int_sine * -pIndoorCamera->pos.x;
-  if ( pIndoorCamera->sRotationX )
-  {
-    this->field_0_party_dir_x = fixpoint_sub0(v11, pOutdoorCamera->camera_rotation_x_int_cosine) +
-                                fixpoint_sub0((-pIndoorCamera->pos.z) << 16, pOutdoorCamera->camera_rotation_x_int_sine);
+  v11 = pGame->pIndoorCameraD3D->int_cosine_y * -pGame->pIndoorCameraD3D->vPartyPos.x + pGame->pIndoorCameraD3D->int_sine_y * -pGame->pIndoorCameraD3D->vPartyPos.y;
+  v24 = pGame->pIndoorCameraD3D->int_cosine_y * -pGame->pIndoorCameraD3D->vPartyPos.y - pGame->pIndoorCameraD3D->int_sine_y * -pGame->pIndoorCameraD3D->vPartyPos.x;
+  if (pGame->pIndoorCameraD3D->sRotationX)
+  {
+    this->field_0_party_dir_x = fixpoint_mul(v11, pGame->pIndoorCameraD3D->int_cosine_x) +
+                                fixpoint_mul((-pGame->pIndoorCameraD3D->vPartyPos.z) << 16, pGame->pIndoorCameraD3D->int_sine_x);
     this->field_4_party_dir_y = v24;
-    this->field_8_party_dir_z = fixpoint_sub0((-pIndoorCamera->pos.z) << 16, v25) - fixpoint_sub0(v11, v27);
+    this->field_8_party_dir_z = fixpoint_mul((-pGame->pIndoorCameraD3D->vPartyPos.z) << 16, v25) - fixpoint_mul(v11, v27);
   }
   else
   {
     this->field_0_party_dir_x = v11;
     this->field_4_party_dir_y = v24;
-    this->field_8_party_dir_z = (-pIndoorCamera->pos.z) << 16;
-  }
-
-  if (pIndoorCamera->sRotationX)
-  {
-    v17 = fixpoint_sub0(a2, v9) + fixpoint_sub0(a3, v7);
-
-    this->field_C = fixpoint_sub0(v17, v25) + fixpoint_sub0(a4, v27);
-    this->field_10 = fixpoint_sub0(a3, v9) - fixpoint_sub0(a2, v7);
-    this->field_14 = fixpoint_sub0(a4, v25) - fixpoint_sub0(v17, v27);
+    this->field_8_party_dir_z = (-pGame->pIndoorCameraD3D->vPartyPos.z) << 16;
+  }
+
+  if (pGame->pIndoorCameraD3D->sRotationX)
+  {
+    v17 = fixpoint_mul(a2, v9) + fixpoint_mul(a3, v7);
+
+    this->field_C = fixpoint_mul(v17, v25) + fixpoint_mul(a4, v27);
+    this->field_10 = fixpoint_mul(a3, v9) - fixpoint_mul(a2, v7);
+    this->field_14 = fixpoint_mul(a4, v25) - fixpoint_mul(v17, v27);
   }
   else
   {
-    this->field_C = fixpoint_sub0(a2, v9) + fixpoint_sub0(a3, v7);
-    this->field_10 = fixpoint_sub0(a3, v9) - fixpoint_sub0(a2, v7);
+    this->field_C = fixpoint_mul(a2, v9) + fixpoint_mul(a3, v7);
+    this->field_10 = fixpoint_mul(a3, v9) - fixpoint_mul(a2, v7);
     this->field_14 = a4;
   }
 
-  if (pIndoorCamera->sRotationX)
-  {
-    v19 = fixpoint_sub0(a5, v9) + fixpoint_sub0(a6, v7);
-
-    this->field_18 = fixpoint_sub0(v19, v25) + fixpoint_sub0(a7, v27);
-    this->field_1C = fixpoint_sub0(a6, v9) - fixpoint_sub0(a5, v7);
-    this->field_20 = fixpoint_sub0(a7, v25) - fixpoint_sub0(v19, v27);
+  if (pGame->pIndoorCameraD3D->sRotationX)
+  {
+    v19 = fixpoint_mul(a5, v9) + fixpoint_mul(a6, v7);
+
+    this->field_18 = fixpoint_mul(v19, v25) + fixpoint_mul(a7, v27);
+    this->field_1C = fixpoint_mul(a6, v9) - fixpoint_mul(a5, v7);
+    this->field_20 = fixpoint_mul(a7, v25) - fixpoint_mul(v19, v27);
   }
   else
   {
-    this->field_18 = fixpoint_sub0(a5, v9) + fixpoint_sub0(a6, v7);
-    this->field_1C = fixpoint_sub0(a6, v9) - fixpoint_sub0(a5, v7);
+    this->field_18 = fixpoint_mul(a5, v9) + fixpoint_mul(a6, v7);
+    this->field_1C = fixpoint_mul(a6, v9) - fixpoint_mul(a5, v7);
     this->field_20 = a7;
   }
 
@@ -6452,14 +6453,14 @@
 						p2DEvents[i].uType = BuildingType_DarkGuild;
 						break;
 						}
-					if ( !_strnicmp(test_string, "ele", 3) )
+					if ( !_strnicmp(test_string, "ele", 3) ) // "Element Guild" from mm6
 						{
-						p2DEvents[i].uType = BuildingType_14;
+						p2DEvents[i].uType = BuildingType_ElementalGuild;
 						break;
 						}
 					if ( !_strnicmp(test_string, "sel", 3) )
 						{
-						p2DEvents[i].uType = BuildingType_15;
+						p2DEvents[i].uType = BuildingType_SelfGuild;
 						break;
 						}
 					if ( !_strnicmp(test_string, "mir", 3) )
@@ -6467,7 +6468,7 @@
 						p2DEvents[i].uType = BuildingType_16;
 						break;
 						}
-					if ( !_strnicmp(test_string, "mer", 3) )
+					if ( !_strnicmp(test_string, "mer", 3) ) // "Merc Guild" from mm6
 						{
 						p2DEvents[i].uType = BuildingType_TownHall;
 						break;
@@ -7348,7 +7349,7 @@
 
   v1 = 1.0 / (v->vWorldViewPosition.x + 0.0000001);
   v->_rhw = v1;
-  v2 = v1 * (double)pOutdoorCamera->int_fov_rad;
+  v2 = v1 * (double)pODMRenderParams->int_fov_rad;
   v->vWorldViewProjX = (double)pViewport->uScreenCenterX - v2 * v->vWorldViewPosition.y;
   v->vWorldViewProjY = (double)pViewport->uScreenCenterY - v2 * v->vWorldViewPosition.z;
 }
--- a/mm7_4.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/mm7_4.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -7,7 +7,6 @@
 #include "VideoPlayer.h"
 #include "Sprites.h"
 #include "BSPModel.h"
-#include "OutdoorCamera.h"
 #include "Mouse.h"
 #include "stru6.h"
 
@@ -21,7 +20,6 @@
 #include "AudioPlayer.h"
 #include "Outdoor.h"
 #include "Outdoor_stuff.h"
-#include "IndoorCamera.h"
 #include "LOD.h"
 #include "Actor.h"
 #include "Events.h"
@@ -365,7 +363,7 @@
                       if ( v9 > 0 )
                       {
                         v10 = v1->vPosition.z;
-                        v11 = stru_721530.normal.z + fixpoint_sub0(stru_721530.direction.z, v9);
+                        v11 = stru_721530.normal.z + fixpoint_mul(stru_721530.direction.z, v9);
                         if ( v11 >= v10 )
                         {
                           if ( v11 <= v18 + v10 )
@@ -434,6 +432,11 @@
   return (left << 16) | right;
 }
 
+int fixpoint_from_int(int lhv, int rhv)
+{
+  return (lhv << 16) | rhv;
+}
+
 //----- (00491E3A) --------------------------------------------------------
 void sub_491E3A()
 {
--- a/mm7_5.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/mm7_5.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -8,7 +8,6 @@
 #include "Sprites.h"
 #include "MapInfo.h"
 #include "BSPModel.h"
-#include "OutdoorCamera.h"
 #include "LightmapBuilder.h"
 #include "DecalBuilder.h"
 #include "Mouse.h"
@@ -1746,7 +1745,7 @@
             }
             if ( !_stricmp(pCurrentMapName, "out15.odm") || !_stricmp(pCurrentMapName, "d47.blv") )
               bNoNPCHiring = 1;
-            PrepareToLoadODM(1u, (OutdoorCamera *)1);
+            PrepareToLoadODM(1u, (ODMRenderParams *)1);
             pAudioPlayer->SetMapEAX();
             bDialogueUI_InitializeActor_NPC_ID = 0;
             OnMapLoad();
@@ -3585,15 +3584,6 @@
   }
 }
 
-//----- (00436427) --------------------------------------------------------
-double  get_shading_dist_mist()
-{
-  if (uCurrentlyLoadedLevelType == LEVEL_Outdoor)
-    return (double)pOutdoorCamera->shading_dist_mist;
-  else
-    return 16192.0;
-}
-
 //----- (0043648F) --------------------------------------------------------
 void Vec3_short__to_RenderVertexSoft(RenderVertexSoft *_this, Vec3_short_ *a2)
 {
@@ -4486,9 +4476,9 @@
 		continue;
 	}
 	  
-	v32 = fixpoint_sub0(v29->pFacePlane_old.vNormal.x,v49);
-	v33 = fixpoint_sub0(v29->pFacePlane_old.vNormal.z,v47);
-	v34 = fixpoint_sub0(v29->pFacePlane_old.vNormal.y,v48);
+	v32 = fixpoint_mul(v29->pFacePlane_old.vNormal.x,v49);
+	v33 = fixpoint_mul(v29->pFacePlane_old.vNormal.z,v47);
+	v34 = fixpoint_mul(v29->pFacePlane_old.vNormal.y,v48);
 	v59 = v32 + v33 + v34;
 	if ( v59 )
 	{
@@ -4514,7 +4504,7 @@
 		if( abs(v38) >> 14 > abs(v59) )
 			continue;
 
-		v58 = fixpoint_sub2(v38,v59);
+		v58 = fixpoint_div(v38,v59);
 
 		if( v58 < 0 )
 		{
@@ -4522,9 +4512,9 @@
 		}
 
 		if(!sub_4075DB(
-				obj1_x + ((fixpoint_sub0(v49,v58) + 32768) >> 16),
-				obj1_y + ((fixpoint_sub0(v48,v58) + 32768) >> 16),
-				obj1_z + ((fixpoint_sub0(v47,v58) + 32768) >> 16),
+				obj1_x + ((fixpoint_mul(v49,v58) + 32768) >> 16),
+				obj1_y + ((fixpoint_mul(v48,v58) + 32768) >> 16),
+				obj1_z + ((fixpoint_mul(v47,v58) + 32768) >> 16),
 				v29) )
 		{
 			continue;
@@ -4647,8 +4637,8 @@
           //                + 32768) >> 16) >= a4a) )
 		  else
 		  {
-			v25 = fixpoint_sub2(dword_4F5D98_xs[i + 1] - dword_4F5D98_xs[i], dword_4F5CC8_ys[i + 1] - dword_4F5CC8_ys[i]);
-			if( dword_4F5D98_xs[i] + (fixpoint_sub0(v25, (v8 - dword_4F5CC8_ys[i]) << 16) + 32768 >> 16) >= a4a)
+			v25 = fixpoint_div(dword_4F5D98_xs[i + 1] - dword_4F5D98_xs[i], dword_4F5CC8_ys[i + 1] - dword_4F5CC8_ys[i]);
+			if( dword_4F5D98_xs[i] + (fixpoint_mul(v25, (v8 - dword_4F5CC8_ys[i]) << 16) + 32768 >> 16) >= a4a)
 				++a3a;
 		  }
       }
--- a/mm7_6.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/mm7_6.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -9,7 +9,6 @@
 #include "Weather.h"
 #include "Sprites.h"
 #include "BSPModel.h"
-#include "OutdoorCamera.h"
 #include "Mouse.h"
 #include "Keyboard.h"
 #include "stru6.h"
@@ -76,7 +75,7 @@
   char *v28; // [sp+30h] [bp-4h]@4
 
   v1 = uVertexID;
-  v2 = (double)pOutdoorCamera->shading_dist_mist;
+  v2 = (double)pODMRenderParams->shading_dist_mist;
   memcpy(&array_50AC10[uVertexID], array_50AC10, sizeof(array_50AC10[uVertexID]));
   v3 = 0;
   v22 = 0;
--- a/mm7_data.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/mm7_data.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -1013,8 +1013,6 @@
 std::array<char, 54> party_has_equipment;
 std::array<char, 17> byte_5111F6;
 
-int _unused000; // weak
-
 std::array<std::array<unsigned __int16, 137>, 117> pOdmMinimap;
 unsigned int uNumBlueFacesInBLVMinimap;
 std::array<unsigned __int16, 50> pBlueFacesInBLVMinimapIDs;
--- a/mm7_data.h	Wed Sep 18 06:30:53 2013 +0200
+++ b/mm7_data.h	Wed Sep 18 06:32:15 2013 +0200
@@ -3,16 +3,12 @@
 #include "VectorTypes.h"
 #include "OSAPI.h"
 #include <array>
+
 typedef char _UNKNOWN;
-
-
-
 typedef unsigned int uint;
 
 
 
-#define COERCE_UNSIGNED_INT64(a) (__debugbreak(), a)
-
 
 
 
@@ -663,7 +659,6 @@
 extern std::array<unsigned int, 16> papredoll_dbrds;
 
 extern int bRingsShownInCharScreen; // weak
-extern int _unused000; // weak
 
 extern std::array<std::array<unsigned __int16, 137>, 117> pOdmMinimap;
 extern unsigned int uNumBlueFacesInBLVMinimap;
@@ -1146,7 +1141,7 @@
 bool  ShouldLoadTexturesForRaceAndGender(unsigned int _this);
 void WetsuitOn(unsigned int uPlayerID); // idb
 void WetsuitOff(unsigned int uPlayerID);
-void __fastcall PrepareDrawLists_BLV(struct IndoorLocation_drawstru *_this);
+void __fastcall PrepareDrawLists_BLV();
 void FindBillboardsLightLevels_BLV();
 int __fastcall _43F55F_get_billboard_light_level(struct RenderBillboard *a1, int uBaseLightLevel);
 int __fastcall _43F5C8_get_point_light_level_with_respect_to_lights(unsigned int uBaseLightLevel, int uSectorID, float x, float y, float z);
@@ -1156,7 +1151,6 @@
 void PrepareItemsRenderList_BLV();
 void AddBspNodeToRenderList(unsigned int node_id);
 void __fastcall sub_4406BC(unsigned int node_id, unsigned int uFirstNode); // idb
-void __fastcall sub_440BED(struct IndoorLocation_drawstru *_this);
 bool sub_44100D();
 __int16 __fastcall sub_441A4E(int a1);
 void DrawBook_Map_sub(unsigned int tl_x, unsigned int tl_y, unsigned int br_x, int br_y, int _48074); // idb
@@ -1181,7 +1175,7 @@
 bool Initialize_GamesLOD_NewLOD();
 void SaveNewGame();
 void PrepareToLoadBLV(unsigned int bLoading);
-void __fastcall PrepareToLoadODM(unsigned int bLoading, struct OutdoorCamera *a2);
+void __fastcall PrepareToLoadODM(unsigned int bLoading, struct ODMRenderParams *a2);
 void _461103_load_level_sub();
 void MainMenu_Loop();
 char sub_4637E0_is_there_popup_onscreen();
@@ -1215,7 +1209,7 @@
 void __fastcall ClickNPCTopic(signed int uMessageParam);
 char * _4B254D_SkillMasteryTeacher(int _this);
 const char *ContractSelectText(int pEventCode);
-void SimpleHouseAndBoatsDialog();
+void SimpleHouseDialog();
 void CreateButtonInColumn(int a1, unsigned int a2);
 void FillAviableSkillsToTeach(int _this);
 void sub_4B3E1E();
@@ -1236,7 +1230,7 @@
 bool __fastcall MerchandiseTest(ItemGen *item, int _2da_idx);
 void UIShop_Buy_Identify_Repair();
 bool __fastcall IsBModelVisible(unsigned int uModelID, int *unused);
-void ODM_LoadAndInitialize(const char *pLevelFilename, struct OutdoorCamera *thisa);
+void ODM_LoadAndInitialize(const char *pLevelFilename, struct ODMRenderParams *thisa);
 unsigned int GetLevelFogColor();
 int __fastcall sub_47C3D7_get_fog_related_stuff(int a1, int a2, float a3);
 int __fastcall GetActorTintColor(int max_dim, int min_dim, float distance, int a4, struct RenderBillboard *a5);
@@ -1244,7 +1238,7 @@
 unsigned int WorldPosToGridCellZ(int); // weak
 int GridCellToWorldPosX(int); // weak
 int GridCellToWorldPosZ(int); // weak
-void sub_481ED9_MessWithOutdoorCamera();
+void sub_481ED9_MessWithODMRenderParams();
 bool IsTerrainSlopeTooHigh(int pos_x, int pos_y);
 int __fastcall GetTerrainHeightsAroundParty2(int a1, int a2, int *a3, int a4);
 void sub_487DA9();
@@ -1373,7 +1367,7 @@
   for ( int i=0; i < count; i++ )
     *p++ = value;
 }
-inline void __fastcall j_memset32(int a2, void *a1, unsigned int a3) {memset32(a1, a2, a3);}
+//inline void __fastcall j_memset32(int a2, void *a1, unsigned int a3) {memset32(a1, a2, a3);}
 
 
 #define ErrD3D(hr) do {extern void ErrHR(HRESULT, const char *, const char *, const char *, int); ErrHR(hr, "Direct3D", __FUNCTION__, __FILE__, __LINE__);} while(0)
--- a/stru10.cpp	Wed Sep 18 06:30:53 2013 +0200
+++ b/stru10.cpp	Wed Sep 18 06:32:15 2013 +0200
@@ -668,9 +668,9 @@
   RenderVertexSoft v25; // [sp+10h] [bp-90h]@20
   memcpy(&v25, pOutBounding, sizeof(RenderVertexSoft));
 
-  float _dp = (v25.vWorldPosition.x - pBLVRenderParams->vPartyPos.x) * a1.x +
-              (v25.vWorldPosition.y - pBLVRenderParams->vPartyPos.y) * a1.y +
-              (v25.vWorldPosition.z - pBLVRenderParams->vPartyPos.z) * a1.z;
+  float _dp = (v25.vWorldPosition.x - pGame->pIndoorCameraD3D->vPartyPos.x) * a1.x +
+              (v25.vWorldPosition.y - pGame->pIndoorCameraD3D->vPartyPos.y) * a1.y +
+              (v25.vWorldPosition.z - pGame->pIndoorCameraD3D->vPartyPos.z) * a1.z;
   if (fabs(_dp) < 1e-6f)
   {
     memcpy(&v25, &pOutBounding[1], sizeof(RenderVertexSoft));
@@ -784,9 +784,9 @@
 char stru10::_49C720(RenderVertexSoft *pFaceBounding, IndoorCameraD3D_Vec4 *pPortalDataFrustum)
 {
   Vec3_float_ pRayStart; // [sp+4h] [bp-34h]@1
-  pRayStart.x = (double)pBLVRenderParams->vPartyPos.x;
-  pRayStart.y = (double)pBLVRenderParams->vPartyPos.y;
-  pRayStart.z = (double)pBLVRenderParams->vPartyPos.z;
+  pRayStart.x = (double)pGame->pIndoorCameraD3D->vPartyPos.x;
+  pRayStart.y = (double)pGame->pIndoorCameraD3D->vPartyPos.y;
+  pRayStart.z = (double)pGame->pIndoorCameraD3D->vPartyPos.z;
 
   if (FindFaceNormal(&pFaceBounding[0], &pFaceBounding[1], &pRayStart, &pPortalDataFrustum[0]) &&
       FindFaceNormal(&pFaceBounding[1], &pFaceBounding[2], &pRayStart, &pPortalDataFrustum[1]) &&