changeset 638:ccf8b4815a1f

GetActorTintColor fixed Outdoor sunlight works on terrain & bmodels (not sure about billboards though)
author Nomad
date Mon, 11 Mar 2013 21:43:26 +0200
parents d7b14091e434
children 4f2837124c69 2c906e6c6926
files DecalBuilder.cpp DecalBuilder.h Game.cpp Game.h Indoor.h LightmapBuilder.cpp Outdoor.cpp Outdoor.h Outdoor_stuff.h Render.cpp mm7_2.cpp mm7_3.cpp mm7_data.h
diffstat 13 files changed, 179 insertions(+), 159 deletions(-) [+]
line wrap: on
line diff
--- a/DecalBuilder.cpp	Mon Mar 11 17:07:51 2013 +0200
+++ b/DecalBuilder.cpp	Mon Mar 11 21:43:26 2013 +0200
@@ -107,7 +107,7 @@
 }
 
 //----- (0049B540) --------------------------------------------------------
-char DecalBuilder::ApplyDecals(int a2, char a3, stru154 *a4, int a5, RenderVertexSoft *a6, IndoorCameraD3D_Vec4 *a7, char a8, unsigned int uSectorID)
+char DecalBuilder::ApplyDecals(int light_level, char a3, stru154 *a4, int a5, RenderVertexSoft *a6, IndoorCameraD3D_Vec4 *a7, char a8, unsigned int uSectorID)
 {
   char *v9; // eax@3
   signed int v10; // ecx@3
@@ -148,6 +148,7 @@
 
   __debugbreak();
 
+  auto a2 = light_level;
   auto a9 = uSectorID;
 
   thisa = this;
--- a/DecalBuilder.h	Mon Mar 11 17:07:51 2013 +0200
+++ b/DecalBuilder.h	Mon Mar 11 21:43:26 2013 +0200
@@ -91,7 +91,7 @@
 
   bool AddBloodsplat(float x, float y, float z, float r, float g, float b, float radius, int a8, int a9);
   void Reset(unsigned int bPreserveBloodsplats);
-  char ApplyDecals(int a2, char a3, struct stru154 *a4, int a5, struct RenderVertexSoft *a6, struct IndoorCameraD3D_Vec4 *a7, char a8, unsigned int uSectorID);
+  char ApplyDecals(int light_level, char a3, struct stru154 *a4, int a5, struct RenderVertexSoft *a6, struct IndoorCameraD3D_Vec4 *a7, char a8, unsigned int uSectorID);
   char _49B790_build_decal_geometry(int a2, char a3, int a4, int a5, int a6, unsigned int uColorMultiplier, struct RenderVertexSoft *a8, struct stru314 *a9, signed int a10, struct RenderVertexSoft *a11, char uClipFlags);
   bool ApplyBloodsplatDecals_IndoorFace(unsigned int uFaceID);
   char ApplyDecals_OutdoorFace(ODMFace *pFace);
--- a/Game.cpp	Mon Mar 11 17:07:51 2013 +0200
+++ b/Game.cpp	Mon Mar 11 21:43:26 2013 +0200
@@ -659,9 +659,10 @@
 
 
 //----- (0044EDE4) --------------------------------------------------------
-bool Game::AlterGamma(BLVFace *pFace, unsigned int *pColor)
+bool Game::AlterGamma_BLV(BLVFace *pFace, unsigned int *pColor)
 {
-  if (pGame->uFlags2 & 2 && pFace->uAttributes & 2)
+  if (uFlags2 & GAME_FLAGS_2_SATURATE_LIGHTMAPS &&
+      pFace->uAttributes & FACE_CAN_SATURATE_COLOR)
   {
     *pColor = ReplaceHSV(*pColor, 1.0, fSaturation, -1.0);
     return true;
@@ -671,11 +672,12 @@
 }
 
 //----- (0044EE30) --------------------------------------------------------
-bool Game::_44EE30(ODMFace *a2, int a3)
+bool Game::AlterGamma_ODM(ODMFace *pFace, unsigned int *pColor)
 {
-  if (uFlags2 & 0x2 && a2->uAttributes & 0x02)
+  if (uFlags2 & GAME_FLAGS_2_SATURATE_LIGHTMAPS &&
+      pFace->uAttributes & FACE_CAN_SATURATE_COLOR)
   {
-    *(int *)a3 = ReplaceHSV(*(int *)a3, 1.0, fSaturation, -1.0);
+    *pColor = ReplaceHSV(*pColor, 1.0, fSaturation, -1.0);
     return true;
   }
   else
--- a/Game.h	Mon Mar 11 17:07:51 2013 +0200
+++ b/Game.h	Mon Mar 11 21:43:26 2013 +0200
@@ -97,8 +97,8 @@
   void OutlineSelection();
   signed int _44EC23(struct stru148 *a2, int *a3, signed int a4);
   signed int _44ED0A(struct BLVFace *a2, int *a3, signed int a4);
-  bool AlterGamma(struct BLVFace *pFace, unsigned int *pColor);
-  bool _44EE30(struct ODMFace *a2, int a3);
+  bool AlterGamma_BLV(struct BLVFace *pFace, unsigned int *pColor);
+  bool AlterGamma_ODM(struct ODMFace *pFace, unsigned int *pColor);
   bool draw_debug_outlines();
   bool _44EEA7();
   bool _44F07B();
--- a/Indoor.h	Mon Mar 11 17:07:51 2013 +0200
+++ b/Indoor.h	Mon Mar 11 21:43:26 2013 +0200
@@ -250,17 +250,17 @@
 #pragma pack(pop)
 
 
-#define FACE_TWO_SIDED        0x00000001 // portal/two-sided
-// 0x02  color is saturated against lights
-#define FACE_TEXTURE_ANIMATED 0x00000010 // like wavy water
-#define FACE_INVISIBLE        0x00002000
-#define FACE_TEXTURE_FRAME    0x00004000 // Texture ID is a frameset from TextureFrameTable, otherwise BitmapID
-#define FACE_OUTLINED         0x00010000 // outline face edges
-#define FACE_TEXTURE_FLOW     0x00040000 // The texture moves slowly. For horizontal facets only.
-#define FACE_DO_NOT_LIGHT     0x00400000
-#define FACE_CLICKABLE        0x02000000 // Event can be triggered by clicking on the facet.
-#define FACE_PRESSURE_PLATE   0x04000000 // Event can be triggered by stepping on the facet.
-#define FACE_ETHEREAL         0x20000000 // Untouchable. You can pass through it.
+#define FACE_TWO_SIDED          0x00000001 // portal/two-sided
+#define FACE_CAN_SATURATE_COLOR 0x00000002
+#define FACE_TEXTURE_ANIMATED   0x00000010 // like wavy water
+#define FACE_INVISIBLE          0x00002000
+#define FACE_TEXTURE_FRAME      0x00004000 // Texture ID is a frameset from TextureFrameTable, otherwise BitmapID
+#define FACE_OUTLINED           0x00010000 // outline face edges
+#define FACE_TEXTURE_FLOW       0x00040000 // The texture moves slowly. For horizontal facets only.
+#define FACE_DO_NOT_LIGHT       0x00400000
+#define FACE_CLICKABLE          0x02000000 // Event can be triggered by clicking on the facet.
+#define FACE_PRESSURE_PLATE     0x04000000 // Event can be triggered by stepping on the facet.
+#define FACE_ETHEREAL           0x20000000 // Untouchable. You can pass through it.
 
 /*   93 */
 #pragma pack(push, 1)
--- a/LightmapBuilder.cpp	Mon Mar 11 17:07:51 2013 +0200
+++ b/LightmapBuilder.cpp	Mon Mar 11 21:43:26 2013 +0200
@@ -1075,7 +1075,7 @@
  int i;
 
   v10 = 0;
-  stru_F8AD28.uCurrentAmbientLightLevel = pOutdoor->field_CBC_terrain_triangles_shade_type;
+  stru_F8AD28.uCurrentAmbientLightLevel = pOutdoor->max_terrain_dimming_level;
   for (i = 0; i < pMobileLightsStack->uNumLightsActive; ++i)
   {
       if ( v10 >= 20 )
--- a/Outdoor.cpp	Mon Mar 11 17:07:51 2013 +0200
+++ b/Outdoor.cpp	Mon Mar 11 21:43:26 2013 +0200
@@ -459,32 +459,32 @@
   unsigned int result; // eax@1
   OutdoorLocation *v2; // esi@1
   unsigned int v3; // edi@3
-  int v4; // ebx@3
+  //int v4; // ebx@3
   int v5; // eax@3
-  int v6; // eax@3
-  int v7; // ecx@3
+  //int v6; // eax@3
+  //int v7; // ecx@3
   double v8; // st7@4
 
   result = pParty->uCurrentHour;
   v2 = this;
-  if ( pParty->uCurrentHour >= 5 && pParty->uCurrentHour < 0x15 )
+  if ( pParty->uCurrentHour >= 5 && pParty->uCurrentHour < 21 )
   {
     v3 = pParty->uCurrentMinute + 60 * (pParty->uCurrentHour - 5);
-    v4 = (signed int)(v3 * stru_5C6E00->uIntegerPi) / 960;
+    //v4 = (signed int)(v3 * stru_5C6E00->uIntegerPi) / 960;
     v5 = stru_5C6E00->Cos((signed int)(v3 * stru_5C6E00->uIntegerPi) / 960);
-    v2->field_D1C = 0;
-    v2->field_D18 = v5;
-    v6 = stru_5C6E00->Sin(v4);
-    v7 = v2->field_D18;
-    v2->field_D20 = v6;
-    v2->vSunlight.x = -v7;
-    v2->vSunlight.y = -v2->field_D1C;
-    v2->vSunlight.z = -v6;
+    v2->inv_sunlight_y = 0;
+    v2->inv_sunlight_x = v5;
+    //v6 = stru_5C6E00->Sin(v4);
+    //v7 = v2->field_D18;
+    v2->inv_sunlight_z = stru_5C6E00->Sin((signed int)(v3 * stru_5C6E00->uIntegerPi) / 960);
+    v2->vSunlight.x = -v2->inv_sunlight_x;
+    v2->vSunlight.y = -v2->inv_sunlight_y;
+    v2->vSunlight.z = -v2->inv_sunlight_z;
     if ( (signed int)v3 >= 480 )
       v8 = (double)(signed int)(960 - v3);
     else
       v8 = (double)(signed int)v3;
-    v2->field_CBC_terrain_triangles_shade_type = (signed __int64)(20.0 - v8 * 0.002083333333333333 * 20.0);
+    v2->max_terrain_dimming_level = (signed __int64)(20.0 - v8 / 480.0 * 20.0);
     result = pParty->uCurrentMinute;
     v2->uLastSunlightUpdateMinute = pParty->uCurrentMinute;
   }
--- a/Outdoor.h	Mon Mar 11 17:07:51 2013 +0200
+++ b/Outdoor.h	Mon Mar 11 21:43:26 2013 +0200
@@ -209,7 +209,7 @@
   char array_528[968];
   char array_8F0[968];
   int field_CB8;
-  int field_CBC_terrain_triangles_shade_type;
+  int max_terrain_dimming_level;
   int field_CC0;
   unsigned int pSpriteIDs_LUN[8];
   unsigned int uSpriteID_LUNFULL;
@@ -226,9 +226,9 @@
   int field_D0C;
   int field_D10;
   int field_D14;
-  int field_D18;
-  int field_D1C;
-  int field_D20;
+  int inv_sunlight_x;
+  int inv_sunlight_y;
+  int inv_sunlight_z;
   int field_D24;
   int field_D28;
   int field_D2C;
--- a/Outdoor_stuff.h	Mon Mar 11 17:07:51 2013 +0200
+++ b/Outdoor_stuff.h	Mon Mar 11 21:43:26 2013 +0200
@@ -41,12 +41,12 @@
   __int16 field_50;
   __int16 field_52;
   ODMFace *pODMFace;
-  char field_58;
+  char dimming_level;
   char field_59;
   char field_5A;
   char field_5B;
-  char field_5C;
-  char field_5D;
+  char terrain_grid_z;
+  char terrain_grid_x;
   unsigned __int8 uBModelID;
   unsigned __int8 uBModelFaceID;
   struct Edge *pEdgeList1[20];
--- a/Render.cpp	Mon Mar 11 17:07:51 2013 +0200
+++ b/Render.cpp	Mon Mar 11 21:43:26 2013 +0200
@@ -338,13 +338,13 @@
               v14 = *(int *)&v4->flags;
               if ( v14 & 0x10 && v4->field_59 != 5 )
               {
-                dword_80AA20 = (v4->field_5C - 64) << 25;
+                dword_80AA20 = (v4->terrain_grid_z - 64) << 25;
                 dword_80AA1C = dword_80AA20 + 0x1FF0000;
-                dword_80AA14 = (v4->field_5D << 25) + 0x7FFF0000;
+                dword_80AA14 = (v4->terrain_grid_x << 25) + 0x7FFF0000;
                 dword_80AA18 = dword_80AA14 - 0x1FF0000;
                 byte_80AA10 = ((unsigned int)pOutdoor->ActuallyGetSomeOtherTileInfo(
-                                               v4->field_5C,
-                                               v4->field_5D - 1) >> 9) & 1;
+                                               v4->terrain_grid_z,
+                                               v4->terrain_grid_x - 1) >> 9) & 1;
                 if ( *(int *)&v4->flags & 2 || (v15 = *(int *)&v4->flags, BYTE1(v15) & 1) )
                 {
                   if ( *(int *)&v4->flags & 2 )
@@ -372,15 +372,15 @@
                         sr_sub_48408A_prolly_odm_water_no_waves(v3);
                       else
                         sr_sub_485407_prolly_odm_water_wavy(v3);
-                      v18 = v4->field_5C - 64;
+                      v18 = v4->terrain_grid_z - 64;
                       v4->pTexture = v16;
                       dword_80AA20 = v18 << 25;
                       dword_80AA1C = (v18 << 25) + 0x1FF0000;
-                      dword_80AA14 = (v4->field_5D << 25) + 0x7FFF0000;
+                      dword_80AA14 = (v4->terrain_grid_x << 25) + 0x7FFF0000;
                       dword_80AA18 = dword_80AA14 - 0x1FF0000;
                       byte_80AA10 = ((unsigned int)pOutdoor->ActuallyGetSomeOtherTileInfo(
-                                                     v4->field_5C,
-                                                     v4->field_5D - 1) >> 9) & 1;
+                                                     v4->terrain_grid_z,
+                                                     v4->terrain_grid_x - 1) >> 9) & 1;
                       sr_sub_484442(v3);
                       v3->field_E = LOWORD(unnamed_6BE060[1]);
                       if ( v4->prolly_tail == v3 )
@@ -427,13 +427,13 @@
                   {
                     if ( v19 == 1 )
                     {
-                      dword_80AA20 = (v4->field_5C - 64) << 25;
+                      dword_80AA20 = (v4->terrain_grid_z - 64) << 25;
                       dword_80AA1C = dword_80AA20 + 33488896;
-                      dword_80AA14 = (v4->field_5D << 25) + 0x7FFF0000;
+                      dword_80AA14 = (v4->terrain_grid_x << 25) + 0x7FFF0000;
                       dword_80AA18 = dword_80AA14 - 33488896;
                       byte_80AA10 = ((unsigned int)pOutdoor->ActuallyGetSomeOtherTileInfo(
-                                                     v4->field_5C,
-                                                     v4->field_5D - 1) >> 9) & 1;
+                                                     v4->terrain_grid_z,
+                                                     v4->terrain_grid_x - 1) >> 9) & 1;
                       while ( 1 )
                       {
                         if ( !sr_sub_4847EB(v3) )
@@ -606,9 +606,9 @@
         v2 = (stru148 *)&pBitmaps_LOD->pTextures[pOutdoor->uMainTile_BitmapID],
         (array_77EC08[1999].pTexture = (Texture *)(pOutdoor->uMainTile_BitmapID != -1 ? (int)v2 : 0)) == 0) )
     return (signed __int16)v2;
-  array_77EC08[1999].field_58 = 23 - (-20 * pOutdoor->vSunlight.z >> 16);
-  if ( array_77EC08[1999].field_58 > 20 )
-    array_77EC08[1999].field_58 = 20;
+  array_77EC08[1999].dimming_level = 23 - (-20 * pOutdoor->vSunlight.z >> 16);
+  if ( array_77EC08[1999].dimming_level > 20 )
+    array_77EC08[1999].dimming_level = 20;
   v10 = stru_5C6E00->Sin(pIndoorCamera->sRotationX);
   array_77EC08[1999].v_18.y = 0;
   array_77EC08[1999].v_18.x = v10;
@@ -625,7 +625,7 @@
   array_77EC08[1999].pTexture = (Texture *)(pOutdoor->uSky_TextureID != -1 ? (int)v2 : 0);
   if ( !(pOutdoor->uSky_TextureID != -1 ? (int)v2 : 0) )
     return (signed __int16)v2;
-  array_77EC08[1999].field_58 = 0;
+  array_77EC08[1999].dimming_level = 0;
   v11 = stru_5C6E00->Sin(pIndoorCamera->sRotationX + 16);
   array_77EC08[1999].v_18.y = 0;
   array_77EC08[1999].v_18.x = -v11;
@@ -1822,7 +1822,17 @@
       v8->pODMFace = nullptr;
       v8->uNumVertices = 4;
       v8->field_59 = 5;
-      v8->field_58 = 0;
+
+
+      uint norm_idx = pTerrainNormalIndices[2 * (x + 128 * z) + 1];
+      assert(norm_idx < uNumTerrainNormals);
+
+      auto norm = pTerrainNormals + norm_idx;
+      float _f = (norm->x * (float)pOutdoor->vSunlight.x / 65536.0 -
+                  norm->y * (float)pOutdoor->vSunlight.y / 65536.0 -
+                  norm->z * (float)pOutdoor->vSunlight.z / 65536.0);
+      v8->dimming_level = 20.0 - floorf(20.0 * _f + 0.5f);
+
       ++pOutdoorCamera->numStru148s;
       ++pOutdoorCamera->field_44;
       assert(pOutdoorCamera->numStru148s < 20000);
@@ -2000,7 +2010,7 @@
   v4 = 0;
   v88 = 0;
   v84 = v3 - 1;
-  v90 = (float)pOutdoor->vSunlight.x / 65536,0;
+  v90 = (float)pOutdoor->vSunlight.x / 65536.0;
   v91 = (float)pOutdoor->vSunlight.y / 65536.0;
   v92 = (float)pOutdoor->vSunlight.z / 65536.0;
   if ( v3 - 1 > 0 )
@@ -2067,22 +2077,22 @@
           v16->field_32 = 0;
           v20 = v93;
           v16->field_59 = 1;
-          v16->field_5D = (char)v19;
+          v16->terrain_grid_x = (char)v19;
           v16->field_34 = *(_WORD *)(v20 + 2);
           v21 = v89;
-          v16->field_5C = v89;
+          v16->terrain_grid_z = v89;
           v22 = pTerrainNormalIndices[2 * (v19 + 128 * v21) + 1];
           if ( v22 < 0 || v22 > uNumTerrainNormals - 1 )
             v23 = 0;
           else
             v23 = &pTerrainNormals[v22];
-          v24 = v92 * v23->y;
+          v24 = v92 * v23->z;
           //v99 = v23;
-          thisf = 20.0 - (-v24 - v91 * v23->z - v90 * v23->x) * 20.0;
+          thisf = 20.0 - (-v24 - v91 * v23->y - v90 * v23->x) * 20.0;
           //v25 = thisf + 6.7553994e15;
           //v27 = pOutdoorCamera->numStru148s > 1999;
           //v26 = pOutdoorCamera->numStru148s - 1999 < 0;
-          v16->field_58 = floorf(thisf + 0.5f);
+          v16->dimming_level = floorf(thisf + 0.5f);
           if ( pOutdoorCamera->numStru148s >= 1999 )
             return;
           ++pOutdoorCamera->numStru148s;
@@ -2142,7 +2152,7 @@
               v33 = v108 != 0 ? 5 : 0;
             static_sub_0048034E_stru_154._49B0C9(v23, v95);
             if ( pDecalBuilder->uNumDecals > 0 )
-              pDecalBuilder->ApplyDecals(31 - v16->field_58, 4, &static_sub_0048034E_stru_154, a5, array_50AC10, 0, *(float *)&v33, -1);
+              pDecalBuilder->ApplyDecals(31 - v16->dimming_level, 4, &static_sub_0048034E_stru_154, a5, array_50AC10, 0, *(float *)&v33, -1);
           }
           if ( stru_F8AD28.uNumLightsApplied > 0 )
             pGame->pLightmapBuilder->ApplyLights(&stru_F8AD28, &static_sub_0048034E_stru_154, a5, array_50AC10, 0, v33);
@@ -2205,10 +2215,10 @@
       *(int *)&v40->flags = v42;
       v44 = v93;
       v40->field_59 = 1;
-      v40->field_5D = (char)v43;
+      v40->terrain_grid_x = (char)v43;
       v40->field_34 = *(_WORD *)(v44 + 2);
       v45 = v89;
-      v40->field_5C = v89;
+      v40->terrain_grid_z = v89;
       v46 = 4 * ((char)v43 + (v45 << 7));
       v85 = v46;
       v47 = *(unsigned __int16 *)((char *)pTerrainNormalIndices + v46 + 2);//    v47 = pTerrainNormalIndices[v46 + 1];
@@ -2220,9 +2230,9 @@
       //v99 = v48;
       thisg = 20.0 - (-v49 - v91 * v48->z - v90 * v48->x) * 20.0;
       v50 = thisg + 6.755399441055744e15;
-      v40->field_58 = LOBYTE(v50);
+      v40->dimming_level = LOBYTE(v50);
       if ( LOBYTE(v50) < 0 )
-        v40->field_58 = 0;
+        v40->dimming_level = 0;
       if ( pOutdoorCamera->numStru148s >= 1999 )
         return;
       ++pOutdoorCamera->numStru148s;
@@ -2287,7 +2297,7 @@
         //a8 = (RenderVertexSoft *)(this_3a ? 3 : v108 != 0 ? 5 : 0);
         static_sub_0048034E_stru_76D590._49B0C9(v48, *(float *)&a4);
         if ( pDecalBuilder->uNumDecals > 0 )
-          pDecalBuilder->ApplyDecals(31 - v40->field_58, 4, &static_sub_0048034E_stru_76D590, uNumVertices, array_50AC10, 0, (char)pVertices, -1);
+          pDecalBuilder->ApplyDecals(31 - v40->dimming_level, 4, &static_sub_0048034E_stru_76D590, uNumVertices, array_50AC10, 0, (char)pVertices, -1);
       }
       if ( stru_F8AD28.uNumLightsApplied > 0 )
         v96->ApplyLights(&stru_F8AD28, &static_sub_0048034E_stru_76D590, uNumVertices, array_50AC10, 0, (char)pVertices);
@@ -2339,8 +2349,8 @@
       v61 = v93;
       v59->field_59 = 1;
       v59->field_34 = *(_WORD *)(v61 + 2);
-      v59->field_5C = v89;
-      v59->field_5D = v97;
+      v59->terrain_grid_z = v89;
+      v59->terrain_grid_x = v97;
       v62 = *(unsigned __int16 *)((char *)pTerrainNormalIndices + v85);
       if ( v62 > (signed int)(uNumTerrainNormals - 1) )
         v63 = 0;
@@ -2349,9 +2359,9 @@
       v64 = v92 * v63->y;
       //v99 = v63;
       thish = 20.0 - (-v64 - v91 * v63->y - v90 * v63->x) * 20.0;
-      v59->field_58 = floorf(thish + 0.5f);
-      if ( v59->field_58 < 0 )
-        v59->field_58 = 0;
+      v59->dimming_level = floorf(thish + 0.5f);
+      if ( v59->dimming_level < 0 )
+        v59->dimming_level = 0;
       if ( pOutdoorCamera->numStru148s >= 1999 )
         return;
       ++pOutdoorCamera->numStru148s;
@@ -2410,7 +2420,7 @@
           v70 = v108 != 0 ? 5 : 0;
         static_sub_0048034E_stru_76D578._49B0C9(v63, v87);
         if ( pDecalBuilder->uNumDecals > 0 )
-          pDecalBuilder->ApplyDecals(31 - v40->field_58, 4, &static_sub_0048034E_stru_76D578, v100, array_50AC10, 0, v70, -1);
+          pDecalBuilder->ApplyDecals(31 - v40->dimming_level, 4, &static_sub_0048034E_stru_76D578, v100, array_50AC10, 0, v70, -1);
       }
       if ( stru_F8AD28.uNumLightsApplied > 0 )
         v96->ApplyLights(&stru_F8AD28, &static_sub_0048034E_stru_76D578, v100, array_50AC10, 0, v70);
@@ -2588,9 +2598,9 @@
   v6 = 0;
   v90 = 0;
   v81 = v3 - 1;
-  v95 = (double)pOutdoor->vSunlight.x * 0.000015258789;
-  v96 = (double)pOutdoor->vSunlight.y * 0.000015258789;
-  v97 = (double)pOutdoor->vSunlight.z * 0.000015258789;
+  v95 = (double)pOutdoor->vSunlight.x / 65536.0;
+  v96 = (double)pOutdoor->vSunlight.y / 65536.0;
+  v97 = (double)pOutdoor->vSunlight.z / 65536.0;
   if ( v3 - 1 > 0 )
   {
     while ( 1 )
@@ -2643,10 +2653,10 @@
         *(int *)&v17->flags = v19;
         v21 = v92;
         v17->field_59 = 1;
-        v17->field_5D = LOBYTE(v20);
+        v17->terrain_grid_x = LOBYTE(v20);
         v17->field_34 = v21->distance;
         v22 = v94;
-        v17->field_5C = v94;
+        v17->terrain_grid_z = v94;
         v23 = pTerrainNormalIndices[2 * (LODWORD(v20) + (v22 << 7)) + 1];
         if ( v23 < 0 || v23 > (signed int)(uNumTerrainNormals - 1) )
           v24 = 0;
@@ -2661,11 +2671,11 @@
           v99 = v25 * 31.0;
           v76 = v99 + 6.7553994e15;
           v84 = LODWORD(v76);
-          v17->field_58 = 31 - LOBYTE(v76);
+          v17->dimming_level = 31 - LOBYTE(v76);
         }
         else
         {
-          v17->field_58 = 0;
+          v17->dimming_level = 0;
         }
         if ( pOutdoorCamera->numStru148s >= 1999 )
           return;
@@ -2760,10 +2770,10 @@
     *(int *)&v38->flags = v40;
     v42 = v92;
     v38->field_59 = 1;
-    v38->field_5D = LOBYTE(v41);
+    v38->terrain_grid_x = LOBYTE(v41);
     v38->field_34 = v42->distance;
     v43 = v94;
-    v38->field_5C = v94;
+    v38->terrain_grid_z = v94;
     v44 = 2 * (LODWORD(v41) + (v43 << 7));
     LODWORD(v93) = v44 * 2;
     v45 = pTerrainNormalIndices[v44 + 1];
@@ -2780,14 +2790,14 @@
       v88 = v47 * 31.0;
       v74 = v88 + 6.7553994e15;
       v87 = LODWORD(v74);
-      v38->field_58 = 31 - LOBYTE(v74);
+      v38->dimming_level = 31 - LOBYTE(v74);
     }
     else
     {
-      v38->field_58 = 0;
-    }
-    if ( v38->field_58 < 0 )
-      v38->field_58 = 0;
+      v38->dimming_level = 0;
+    }
+    if ( v38->dimming_level < 0 )
+      v38->dimming_level = 0;
     if ( pOutdoorCamera->numStru148s >= 1999 )
       return;
     ++pOutdoorCamera->numStru148s;
@@ -2849,8 +2859,8 @@
           v58 = v92;
           v17->field_59 = 1;
           v17->field_34 = v58->distance;
-          v17->field_5C = v94;
-          v17->field_5D = LOBYTE(v99);
+          v17->terrain_grid_z = v94;
+          v17->terrain_grid_x = LOBYTE(v99);
           v59 = *(unsigned __int16 *)((char *)pTerrainNormalIndices + LODWORD(v93));
           if ( v59 > (signed int)(uNumTerrainNormals - 1) )
           {
@@ -2870,14 +2880,14 @@
             v93 = v61 * 31.0;
             v72 = v93 + 6.7553994e15;
             v83 = LODWORD(v72);
-            v17->field_58 = 31 - LOBYTE(v72);
+            v17->dimming_level = 31 - LOBYTE(v72);
           }
           else
           {
-            v17->field_58 = 0;
+            v17->dimming_level = 0;
           }
-          if ( v17->field_58 < 0 )
-            v17->field_58 = 0;
+          if ( v17->dimming_level < 0 )
+            v17->dimming_level = 0;
           if ( pOutdoorCamera->numStru148s >= 1999 )
             return;
           ++pOutdoorCamera->numStru148s;
@@ -4478,7 +4488,7 @@
   unsigned int v55; // [sp+5Ch] [bp-Ch]@34
   unsigned int v56; // [sp+60h] [bp-8h]@12
   int v57; // [sp+60h] [bp-8h]@34
-  HRESULT a2; // [sp+64h] [bp-4h]@4
+  unsigned int a2; // [sp+64h] [bp-4h]@4
 
   v5 = this;
   v6 = 0;
@@ -4488,11 +4498,11 @@
     v53 = v7;
     v54 = v7->std__vector_000004_size;
     if ( v7->std__vector_000004_size)
-      a2 = -1;
-    pGame->_44EE30(a4, (int)&a2);
+      a2 = 0xFFFFFFFF;
+    pGame->AlterGamma_ODM(a4, &a2);
     if ( byte_4D864C && pGame->uFlags & 1 )
     {
-      v8 = GetActorTintColor(a3->field_58, 0, array_50AC10[0].vWorldViewPosition.x, 0, 0);
+      v8 = ::GetActorTintColor(a3->dimming_level, 0, array_50AC10[0].vWorldViewPosition.x, 0, 0);
       v7->_45D74F_MessWithLight(v8, 0);
     }
     else
@@ -4514,8 +4524,8 @@
           v55 = uNumVertices;
           do
           {
-            a2 = GetActorTintColor(a3->field_58, 0, *(float *)v45, 0, 0);
-            pGame->_44EE30(a4, (int)&a2);
+            a2 = ::GetActorTintColor(a3->dimming_level, 0, *(float *)v45, 0, 0);
+            pGame->AlterGamma_ODM(a4, &a2);
             v46 = v57;
             v47 = *(float *)v45 * 1000.0 / (double)pOutdoorCamera->shading_dist_mist;
             *(int *)(v57 - 4) = *((int *)v45 + 3);
@@ -4576,7 +4586,7 @@
             v9->pFacePlane.vNormal.x = *((int *)v10 + 4);
             *(float *)&v9->pFacePlane.vNormal.y = 1.0 - 1.0 / v12;
             *(float *)&v9->pFacePlane.vNormal.z = 1.0 / (*(float *)v10 + 0.0000001);
-            v13 = GetActorTintColor(a3->field_58, 0, *(float *)v10, 0, 0);
+            v13 = GetActorTintColor(a3->dimming_level, 0, *(float *)v10, 0, 0);
             v14 = a4;
             v15 = *(float *)v10;
             a4->pFacePlane.dist = v13;
@@ -7305,6 +7315,7 @@
 //----- (004A2031) --------------------------------------------------------
 unsigned int Render::GetActorTintColor(float a2, int tint, int a4, int a5, RenderBillboard *a6)
 {
+  __debugbreak(); // should not fire outside decal builder
   return ::GetActorTintColor(tint, a4, a2, a5, a6);
 }
 
@@ -7503,7 +7514,7 @@
     v10 = v9->std__vector_000004_size;*/
     if ( byte_4D864C && pGame->uFlags & 1 )
     {
-      v11 = GetActorTintColor(a4->field_58, 0, array_50AC10[0].vWorldViewPosition.x, 0, 0);
+      v11 = ::GetActorTintColor(a4->dimming_level, 0, array_50AC10[0].vWorldViewPosition.x, 0, 0);
       pGame->pLightmapBuilder->_45D74F_MessWithLight(v11, 0);
     }
     else
@@ -7546,7 +7557,7 @@
             *(int *)v51 = *((int *)v52 + 4);
             *(float *)(v51 + 4) = 1.0 - 1.0 / v54;
             *(float *)(v51 + 8) = 1.0 / (*(float *)v52 + 0.0000001);
-            v55 = GetActorTintColor(a4->field_58, 0, *(float *)v52, 0, 0);
+            v55 = ::GetActorTintColor(a4->dimming_level, 0, *(float *)v52, 0, 0);
             v56 = a7;
             v57 = *(float *)v52;
             *(int *)(a7 + 12) = v55;
@@ -7596,7 +7607,7 @@
             *(int *)v12 = *((int *)v13 + 4);
             *(float *)(v12 + 4) = 1.0 - 1.0 / v15;
             *(float *)(v12 + 8) = 1.0 / (*(float *)v13 + 0.0000001);
-            v16 = GetActorTintColor(a4->field_58, 0, *(float *)v13, 0, 0);
+            v16 = GetActorTintColor(a4->dimming_level, 0, *(float *)v13, 0, 0);
             v17 = a7;
             v18 = *(float *)v13;
             *(int *)(a7 + 12) = v16;
@@ -7738,7 +7749,7 @@
    pVertices[i].pos.z = 0.99989998;
    pVertices[i].rhw = array_50AC10[i]._rhw;
 
-   pVertices[i].diffuse = GetActorTintColor(31, 0, array_50AC10[i].vWorldViewPosition.x, 1, 0);
+   pVertices[i].diffuse = ::GetActorTintColor(31, 0, array_50AC10[i].vWorldViewPosition.x, true, false);
    v7 = 0;
    if (this->bUsingSpecular)
    {
@@ -7816,9 +7827,9 @@
     if ( a2 >= 3 )
     {
       ErrD3D(pRenderD3D->pDevice->SetTextureStageState(0, D3DTSS_ADDRESS, D3DTADDRESS_WRAP));
-      v5 = 31 - (a3->field_58 & 0x1F);
-      if ( v5 < pOutdoor->field_CBC_terrain_triangles_shade_type )
-        v5 = pOutdoor->field_CBC_terrain_triangles_shade_type;
+      v5 = 31 - (a3->dimming_level & 0x1F);
+      if ( v5 < pOutdoor->max_terrain_dimming_level )
+        v5 = pOutdoor->max_terrain_dimming_level;
       v6 = 8 * v5 | ((8 * v5 | (v5 << 11)) << 8);
       if ( a2 > 0 )
       {
@@ -7903,7 +7914,7 @@
   auto uCorrectedColor = uColor;
   if (pGame->pLightmapBuilder->std__vector_000004_size)
     uCorrectedColor = 0xFFFFFFFF;
-  pGame->AlterGamma(pFace, &uCorrectedColor);
+  pGame->AlterGamma_BLV(pFace, &uCorrectedColor);
 
   if (byte_4D864C && pGame->uFlags & 1)
   {
@@ -8570,7 +8581,7 @@
   v30 = (a2->_screenspace_x_scaler_packedfloat & 0xFFFF) / 65530.0 + HIWORD(a2->_screenspace_x_scaler_packedfloat);
   v29 = (a2->_screenspace_y_scaler_packedfloat & 0xFFFF) / 65530.0 + HIWORD(a2->_screenspace_y_scaler_packedfloat);
 
-  unsigned int diffuse = GetActorTintColor(paletteSubindex, 0, a2->zbuffer_depth, 0, pBillboard);
+  unsigned int diffuse = ::GetActorTintColor(paletteSubindex, 0, a2->zbuffer_depth, 0, pBillboard);
   if (a2->uTintColor & 0x00FFFFFF && bTinting)
   {
     diffuse = sub_4A19D8(a2->uTintColor, diffuse);
--- a/mm7_2.cpp	Mon Mar 11 17:07:51 2013 +0200
+++ b/mm7_2.cpp	Mon Mar 11 21:43:26 2013 +0200
@@ -10446,7 +10446,7 @@
 }
 
 bool new_sky = false;
-bool change_seasons = true;
+bool change_seasons = false;
 
 //----- (00462C94) --------------------------------------------------------
 bool MM_Main(const wchar_t *pCmdLine)
--- a/mm7_3.cpp	Mon Mar 11 17:07:51 2013 +0200
+++ b/mm7_3.cpp	Mon Mar 11 21:43:26 2013 +0200
@@ -4847,11 +4847,11 @@
       pLightmapBuilder = (LightmapBuilder *)(v51 + v53 + v52);
       v51 = 20 * (int)pLightmapBuilder;
       result = 20 - (20 * (signed int)pLightmapBuilder >> 16);
-      v7->field_58 = result;
+      v7->dimming_level = result;
       if ( result < 0 )
-        v7->field_58 = 0;
-      if ( v7->field_58 > 31 )
-        v7->field_58 = 31;
+        v7->dimming_level = 0;
+      if ( v7->dimming_level > 31 )
+        v7->dimming_level = 31;
       if ( pOutdoorCamera->numStru148s >= 1999 + 5000)
         return result;
       ++pOutdoorCamera->numStru148s;
@@ -4912,8 +4912,7 @@
             v38 = 0;
             v37 = array_50AC10;
             v36 = uNumVertices;
-            pDecalBuilder->ApplyDecals(
-              31 - v7->field_58,
+            pDecalBuilder->ApplyDecals(31 - v7->dimming_level,
               2,
               &static_RenderBuildingsD3D_stru_73C834,
               uNumVertices,
@@ -5170,8 +5169,8 @@
         *(float *)&v84 = v13 * 31.0;
         v14 = *(float *)&v84 + 6.7553994e15;
         v71 = LODWORD(v14);
-        v15 = (int)&v12->field_58;
-        v12->field_58 = 31 - LOBYTE(v14);
+        v15 = (int)&v12->dimming_level;
+        v12->dimming_level = 31 - LOBYTE(v14);
         if ( (char)(31 - LOBYTE(v14)) < 0 )
           *(char *)v15 = 0;
         if ( *(char *)v15 > 31 )
@@ -5529,11 +5528,11 @@
   float v15; // [sp+8h] [bp-30h]@1
   float v16; // [sp+Ch] [bp-2Ch]@1
 
-  v14 = (double)pOutdoor->vSunlight.x * 0.000015258789;
+  v14 = (double)pOutdoor->vSunlight.x / 65536.0;
   result = 0;
   v1 = (unsigned int)&array_77EC08[pOutdoorCamera->numStru148s];
-  v15 = (double)pOutdoor->vSunlight.y * 0.000015258789;
-  v16 = (double)pOutdoor->vSunlight.z * 0.000015258789;
+  v15 = (double)pOutdoor->vSunlight.y / 65536.0;
+  v16 = (double)pOutdoor->vSunlight.z / 65536.0;
   if ( v1 > (unsigned int)array_77EC08 )
   {
     v2 = (char *)&array_77EC08[0].pODMFace;
@@ -6136,7 +6135,7 @@
   if (pOutdoor->uSky_TextureID == -1)
     return;
 
-  _this.field_58 = 0;
+  _this.dimming_level = 0;
   _this.uNumVertices = 4;
   _this.v_18.x = -stru_5C6E00->Sin(pIndoorCamera->sRotationX + 16);
   _this.v_18.y = 0;
@@ -6404,7 +6403,7 @@
   if ( !v62.pTexture )
     return;
   v8 = pBLVRenderParams->sPartyRotX;
-  v62.field_58 = 0;
+  v62.dimming_level = 0;
   v62.uNumVertices = v3;
   v9 = stru_5C6E00->Sin(pBLVRenderParams->sPartyRotX + 16);
   v62.v_18.y = 0;
@@ -6904,8 +6903,8 @@
       v10 = 27;
     if ( v10 < a4 )
       v10 = a4;
-    if ( v10 > pOutdoor->field_CBC_terrain_triangles_shade_type )
-      v10 = pOutdoor->field_CBC_terrain_triangles_shade_type;
+    if ( v10 > pOutdoor->max_terrain_dimming_level )
+      v10 = pOutdoor->max_terrain_dimming_level;
     return PaletteManager::Get_Dark_or_Red_LUT(v4, v10, 1);
   }
   v6 = 0;
@@ -7004,7 +7003,7 @@
         *a5 = 31;
         *a6 = -1;
       }
-      v16 = v8->field_58 - terrain_gamma;
+      v16 = v8->dimming_level - terrain_gamma;
       if ( v16 >= 0 )
       {
         if ( v16 > 27 )
@@ -7037,8 +7036,8 @@
         *v14 = v20;
       if ( *v14 < v16 )
         *v14 = v16;
-      if ( *v14 > pOutdoor->field_CBC_terrain_triangles_shade_type )
-        *v14 = pOutdoor->field_CBC_terrain_triangles_shade_type;
+      if ( *v14 > pOutdoor->max_terrain_dimming_level )
+        *v14 = pOutdoor->max_terrain_dimming_level;
       goto LABEL_45;
     }
     if ( v9 >= day_fogrange_1 << 16 )
@@ -7366,7 +7365,7 @@
 
 
 //----- (0047C4FC) --------------------------------------------------------
-signed int __fastcall GetActorTintColor(int tint, int a2, float a3, int a4, RenderBillboard *a5)
+signed int __fastcall GetActorTintColor(int max_dimm, int min_dimm, float distance, int a4, RenderBillboard *a5)
 {
   //int v5; // esi@1
   signed int v6; // edx@1
@@ -7385,11 +7384,11 @@
   //double v19; // ST0C_8@44
   signed int v20; // [sp+10h] [bp-4h]@10
   float a3a; // [sp+1Ch] [bp+8h]@33
-  float a3b; // [sp+1Ch] [bp+8h]@34
+  //float a3b; // [sp+1Ch] [bp+8h]@34
   float a3c; // [sp+1Ch] [bp+8h]@44
   //float a3d; // [sp+1Ch] [bp+8h]@44
   float a4b; // [sp+20h] [bp+Ch]@18
-  int a4a; // [sp+20h] [bp+Ch]@33
+  //int a4a; // [sp+20h] [bp+Ch]@33
   //float a4c; // [sp+20h] [bp+Ch]@44
   //float a4d; // [sp+20h] [bp+Ch]@44
   int a5a; // [sp+24h] [bp+10h]@44
@@ -7398,12 +7397,13 @@
   v6 = 0;
 
   if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
-    return 8 * (31 - tint) | ((8 * (31 - tint) | ((31 - tint) << 11)) << 8);
+    return 8 * (31 - max_dimm) | ((8 * (31 - max_dimm) | ((31 - max_dimm) << 11)) << 8);
+
   if (pParty->armageddon_timer)
     return 0xFFFF0000;
 
   v8 = pWeather->field_FA0;
-  if ( bUnderwater == 1 )
+  if (bUnderwater)
     v8 = 0;
   if ( v8 )
   {
@@ -7416,11 +7416,11 @@
     v9 = (double)v20 * 1024.0;
     if ( a4 )
       goto LABEL_19;
-    if ( a3 <= v9 )
-    {
-      if ( a3 > 0.0 )
-      {
-        a4b = a3 * 216.0 / v9;
+    if ( distance <= v9 )
+    {
+      if ( distance > 0.0 )
+      {
+        a4b = distance * 216.0 / v9;
         v10 = a4b + 6.7553994e15;
         v6 = LODWORD(v10);
         if ( SLODWORD(v10) > 216 )
@@ -7431,7 +7431,7 @@
     {
       v6 = 216;
     }
-    if ( a3 != 0.0 )
+    if ( distance != 0.0 )
     {
 LABEL_20:
       if ( a5 )
@@ -7447,10 +7447,11 @@
 
 
 
-  if ( a3 == 0.0 )
+  if (fabsf(distance) < 1.0e-6f)
     return 0xFFF8F8F8;
 
-  v11 = 8 * (tint - a2);
+  // dim in measured in 8-steps
+  v11 = 8 * (max_dimm - min_dimm);
     //v12 = v11;
     if ( v11 >= 0 )
     {
@@ -7460,27 +7461,32 @@
     else
       v11 = 0;
 
-    if ( a4 )
-    {
-      a3b = pOutdoor->fFogDensity * 216.0;
+    float fog_density_mult = 216.0f;
+    if (a4)
+      fog_density_mult += distance / (double)pOutdoorCamera->shading_dist_shade * 32.0;
+
+    v6 = v11 + floorf(pOutdoor->fFogDensity * fog_density_mult + 0.5f);
+    /*if ( a4 )
+    {
+      //a3b = pOutdoor->fFogDensity * 216.0;
       //v14 = a3b + 6.7553994e15;
-      a4a = floorf(a3b + 0.5f);//LODWORD(v14);
-    }
-    else
-    {
-      a3a = (a3 / (double)pOutdoorCamera->shading_dist_shade * 32.0 + 216.0) * pOutdoor->fFogDensity;
+      //a4a = floorf(a3b + 0.5f);//LODWORD(v14);
+    }
+    else
+    {
+      //a3a = (distance / (double)pOutdoorCamera->shading_dist_shade * 32.0 + 216.0) * pOutdoor->fFogDensity;
       //v13 = a3a + 6.7553994e15;
-      a4a = floorf(a3a + 0.5f);//LODWORD(v13);
-    }
-    v6 = a4a + v11;
+      //a4a = floorf(a3a + 0.5f);//LODWORD(v13);
+    }
+    v6 = a4a + v11;*/
     if ( a5 )
       v6 = 8 * _43F55F_get_billboard_light_level(a5, v6 >> 3);
     if ( v6 > 216 )
       v6 = 216;
     if ( v6 < v11 )
       v6 = v11;
-    if ( v6 > 8 * pOutdoor->field_CBC_terrain_triangles_shade_type )
-      v6 = 8 * pOutdoor->field_CBC_terrain_triangles_shade_type;
+    if ( v6 > 8 * pOutdoor->max_terrain_dimming_level )
+      v6 = 8 * pOutdoor->max_terrain_dimming_level;
     if ( !bUnderwater )
       return (255 - v6) | ((255 - v6) << 16) | ((255 - v6) << 8);
     else
--- a/mm7_data.h	Mon Mar 11 17:07:51 2013 +0200
+++ b/mm7_data.h	Mon Mar 11 21:43:26 2013 +0200
@@ -2194,7 +2194,7 @@
 char *__fastcall sr_sub_47C28C_get_palette(stru148 *a1, char a2, signed int a3, signed int a4);
 unsigned int __cdecl GetLevelFogColor();
 int __fastcall sub_47C3D7_get_fog_related_stuff(int a1, int a2, float a3);
-signed int __fastcall GetActorTintColor(int a1, int a2, float a3, int a4, struct RenderBillboard *a5);
+signed int __fastcall GetActorTintColor(int max_dim, int min_dim, float distance, int a4, struct RenderBillboard *a5);
 unsigned int __stdcall WorldPosToGridCellX(int); // weak
 unsigned int __stdcall WorldPosToGridCellZ(int); // weak
 int __stdcall GridCellToWorldPosX(int); // weak