changeset 798:f57bd5c0890c

Слияние
author Ritor1
date Mon, 25 Mar 2013 09:49:21 +0600
parents 11dab247bd72 (current diff) 346f7069676a (diff)
children 977407dfa4c5
files
diffstat 19 files changed, 288 insertions(+), 246 deletions(-) [+]
line wrap: on
line diff
--- a/DecalBuilder.cpp	Mon Mar 25 09:49:12 2013 +0600
+++ b/DecalBuilder.cpp	Mon Mar 25 09:49:21 2013 +0600
@@ -467,7 +467,7 @@
 
   if (pFace->uAttributes & 0x400000)
     return true;
-  if (pFace->Animated())
+  if (pFace->Fluid())
     return true;
 
   for (uint i = 0; i < pBloodsplatContainer->std__vector_pBloodsplats_size; ++i)
--- a/Game.cpp	Mon Mar 25 09:49:12 2013 +0600
+++ b/Game.cpp	Mon Mar 25 09:49:21 2013 +0600
@@ -22,6 +22,7 @@
 #include "Arcomage.h"
 #include "texts.h"
 #include "Actor.h"
+#include "GUIFont.h"
 #include "Log.h"
 
 //#include "MM7.h"
@@ -119,6 +120,11 @@
   }
   pRenderer->DrawBillboards_And_MaybeRenderSpecialEffects_And_EndScene();
 LABEL_22:
+
+  //DEBUG: force redraw gui
+  viewparams->bRedrawGameUI = true;
+
+
   pRenderer->BeginScene();
   if (pRenderer->pRenderD3D)
     pMouse->DrawCursorToTarget();
@@ -166,12 +172,35 @@
     pOtherOverlayList->DrawTurnBasedIcon(v4);
     GameUI_DrawTorchlightAndWizardEye();
   }
+
+  if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
+  {
+    sprintf(pTmpBuf, "Party Sector ID:        %u/%u\n", pBLVRenderParams->uPartySectorID, pIndoor->uNumSectors);
+    pPrimaryWindow->DrawText(pFontArrus, 16, 16, GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(255, 255, 255), pTmpBuf, 0, 0, 0xFFFFFFFF);
+  }
+  sprintf(pTmpBuf, "Party Position:         % d % d % d", pParty->vPosition.x, pParty->vPosition.y, pParty->vPosition.z);
+  pPrimaryWindow->DrawText(pFontArrus, 16, 16 + 16, GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(255, 255, 255), pTmpBuf, 0, 0, 0xFFFFFFFF);
+  
+  if (uCurrentlyLoadedLevelType == LEVEL_Indoor)
+  {
+    uint uFaceID;
+    auto floor_level = BLV_GetFloorLevel(pParty->vPosition.x, pParty->vPosition.y, pParty->vPosition.z, pBLVRenderParams->uPartySectorID, &uFaceID);
+    sprintf(pTmpBuf, "BLV_GetFloorLevel: %d   face_id %d\n", floor_level, uFaceID);
+  }
+  else
+  {
+    int on_water, _a6;
+    auto floor_level = ODM_GetFloorLevel(pParty->vPosition.x, pParty->vPosition.y, pParty->vPosition.z, 0, &on_water, &_a6, false);
+    sprintf(pTmpBuf, "ODM_GetFloorLevel: %d   on_water: %s    a6 = %d\n", floor_level, on_water ? "true" : "false", _a6);
+  }
+  pPrimaryWindow->DrawText(pFontArrus, 16, 16 + 16 + 16, GenerateColorAsCloseAsPossibleToR8G8B8InTargetFormat(255, 255, 255), pTmpBuf, 0, 0, 0xFFFFFFFF);
+
   GUI_UpdateWindows();
   pParty->UpdatePlayersAndHirelingsEmotions();
   ++stru_51076C.field_8;
   _unused_5B5924_is_travel_ui_drawn = false;
   if (v4)
-    pMouse->field_14 = 1;
+    pMouse->bRedraw = true;
   pMouse->_469EA4();
   pMouse->DrawCursor();
   pMouse->_469E1C();
--- a/Indoor.cpp	Mon Mar 25 09:49:12 2013 +0600
+++ b/Indoor.cpp	Mon Mar 25 09:49:21 2013 +0600
@@ -23,6 +23,9 @@
 #include "PaletteManager.h"
 #include "MapInfo.h"
 #include "IndoorCamera.h"
+#include "GUIWindow.h"
+#include "GUIButton.h"
+#include "GUIFont.h"
 
 #include "mm7_data.h"
 
@@ -375,10 +378,14 @@
   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.field_0_timer = pEventTimer->uTotalGameTimeElapsed;
   _this.field_1C_mb_fov = 65;
-  _this.vPosition.x = pParty->vPosition.x - ((stru_5C6E00->Cos(pParty->sRotationY) * (signed __int64)pParty->y_rotation_granularity) >> 16);
-  _this.vPosition.y = pParty->vPosition.y - ((stru_5C6E00->Sin(pParty->sRotationY) * (signed __int64)pParty->y_rotation_granularity) >> 16);
+  _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;
@@ -537,7 +544,7 @@
         if (pDecalBuilder->uNumDecals > 0)
           pDecalBuilder->ApplyDecals(a4a, 1, &stru_F7B60C, uNumVerticesa, array_507D30, pVertices, 0, pFace->uSectorID);
 
-        if (pFace->Animated() &&
+        if (pFace->Fluid() &&
             pFace->uBitmapID == pRenderer->hd_water_tile_id )
         {
           __debugbreak();
@@ -545,7 +552,7 @@
           goto LABEL_42;
         }
 
-        if (pFace->Animated())
+        if (pFace->Fluid())
         {
           //auto v24 = GetTickCount() / 4;
           //auto v25 = v24 - stru_5C6E00->uIntegerHalfPi;
@@ -1467,6 +1474,7 @@
           }
           if (pBLVRenderParams->uFlags & INDOOR_CAMERA_DRAW_SW_OUTLINES)
             pGame->pIndoorCameraD3D->PrepareAndDrawDebugOutline(pFace, 0x1E1EFF);
+            //pGame->pIndoorCameraD3D->DebugDrawPortal(pFace);
         }
 }
 
@@ -3121,10 +3129,10 @@
   ///Vec3_short_ *v29; // eax@26
   //Vec3_short_ *v30; // edx@26
   //int v31; // edx@26
-  signed int v32; // edi@27
+  //signed int v32; // edi@27
   signed __int64 v33; // qtt@27
   //Vec3_short_ *v34; // edx@27
-  int v35; // edx@32
+  //int v35; // edx@32
   int v37; // edi@38
   int pSectorID; // ebx@40
   int v39; // eax@41
@@ -3150,12 +3158,10 @@
   int v59; // [sp+110h] [bp-4h]@16
 
   v4 = 0;
-  //v7 = __OFSUB__(this->uNumSectors, 1);
-  //v5 = this->uNumSectors == 1;
-  //v6 = this->uNumSectors - 1 < 0;
+  v43[0] = 0;
+
   v55 = 0;
-  v43[0] = 0;
-  //v56 = 1;
+
   if (uNumSectors < 2)
     return 0;
 
@@ -3163,126 +3169,101 @@
   {
     auto pSector = pSectors + i;
 
-    if (pSector->pBounding.x1 <= sX  && pSector->pBounding.x2 >= sX)
-      if (pSector->pBounding.y1 <= sY  && pSector->pBounding.y2 >= sY)
-        if (pSector->pBounding.z1 - 64 <= sZ && pSector->pBounding.z2 + 64 >= sZ)
-        {
+    if (pSector->pBounding.x1 > sX || pSector->pBounding.x2 < sX ||
+        pSector->pBounding.y1 > sY || pSector->pBounding.y2 < sY ||
+        pSector->pBounding.z1 - 64 > sZ || pSector->pBounding.z2 + 64 < sZ)
+      continue;
+
           //Log::Warning(L"Sector[%u]", i);
-          v51 = pSector->uNumFloors + pSector->uNumPortals;
-          if (!v51)
-            continue;
-
-          //v9 = pSector->uNumFloors;
-                //v10 = v9 + pSector->uNumPortals;
-                //v11 = 0;
-                //v44 = v9;
-                //v48 = 0;
-
-                  //v12 = -2 * v9;
-                  //v53 = -2 * v9;
-           for (uint j = 0; j < v51; ++j)
-           {
-             unsigned int uFaceID;
-             if (j < pSector->uNumFloors)
-               uFaceID = pSector->pFloors[j];
-             else
-               uFaceID = pSector->pPortals[j - pSector->uNumFloors];
-
-             auto pFace = pFaces + uFaceID;
-                    //v14 = (signed __int16)v13;
-                    //v15 = this->pFaces;
-                    //v46 = v13;
-                    //v14 *= 96;
-                    //v45 = v13 * sizeof(BLVFace);
-                    //v16 = pFaces + uFaceID;
-                    //v17 = v16->uPolygonType;
-             if (pFace->uPolygonType == POLYGON_Floor ||
-                 pFace->uPolygonType == POLYGON_InBetweenFloorAndWall)
-             {
-               //pVertexIDs = pFace->pVertexIDs;
-                      //v19 = this->pVertices;
-               //v20 = pVertices[pFace->pVertexIDs[0]].y;
-               v54 = 0;
-               //v57 = 0;
-               //v5 = v16->uNumVertices == 0;
-               v59 = pVertices[pFace->pVertexIDs[0]].y >= sY;
-
-                        //v21 = pFace->pVertexIDs + 1;
-               for (uint k = 0; k < pFace->uNumVertices; k++)
-               {
-                 if (v54 >= 2)
-                   break;
-
-                 //v49 = &pVertices[pFace->pVertexIDs[k]];
-                 auto v2 = &pVertices[pFace->pVertexIDs[k]];
-                          //v22 = pVertex->y;
-                          //v47 = pVertex->y;
-                 v50 = v2->y >= sY;
-                 if ( v59 != v50 )
-                 {
-                            //v58 = &pVertices[pFace->pVertexIDs[k - 1]];
-                   auto v1 = &pVertices[pFace->pVertexIDs[k]];
-                            //v23 = v58->x;
-                            //HIWORD(v24) = HIWORD(v49);
-                            //LOWORD(v24) = v49->x;
-                            //v49 = v24;
-                            //v59 = v49->x;
-                   v25 = v1->x >= sX ? 0 : 2;
-                   v26 = v25 | v2->x < sX;
-                   if ( v26 != 3 )
-                   {
-                    if (!v26)
-                      ++v54;
-                    else
-                    {
-                      if (v1->x >= v2->x)
-                      {
-                        int _a58;
+    v51 = pSector->uNumFloors + pSector->uNumPortals;
+    if (!v51)
+      continue;
+
+
+    for (uint j = 0; j < v51; ++j)
+    {
+      uint uFaceID;
+      if (j < pSector->uNumFloors)
+        uFaceID = pSector->pFloors[j];
+      else
+        uFaceID = pSector->pPortals[j - pSector->uNumFloors];
+
+      auto pFace = pFaces + uFaceID;
+      if (pFace->uPolygonType != POLYGON_Floor &&
+          pFace->uPolygonType != POLYGON_InBetweenFloorAndWall)
+        continue;
+
+      v54 = 0;
+      v50 = pVertices[pFace->pVertexIDs[0]].y >= sY;
+
+      for (uint k = 1; k < pFace->uNumVertices; k++)
+      {
+        v59 = v50;
+
+        if (v54 >= 2)
+          break;
+
+        auto v2 = &pVertices[pFace->pVertexIDs[k]];
+        v50 = v2->y >= sY;
+
+        if ( v59 == v50 )
+          continue;
+
+        auto v1 = &pVertices[pFace->pVertexIDs[k - 1]];
+        v25 = v2->x >= sX ? 0 : 2;
+        v26 = v25 | (v1->x < sX);
+
+        if (v26 == 3)
+          continue;
+
+        if (!v26)
+          ++v54;
+        else
+        {
+          if (v1->x >= v2->x)
+          {
+                        /*int _a58;
                         int _a59;
 
                         v32 = v1->x - v2->x;
                         LODWORD(v33) = v32 << 16;
-                        HIDWORD(v33) = v32 >> 16;
-                        _a58 = v33 / (v1->y - v2->y);
-                        _a59 = (unsigned __int64)(_a58 * (__int64)(sY - v2->y)) >> 16;
-
-                        if (v59 + pVertices[k].x > sX)
-                          ++v54;
-                      }
-                      else
-                      {
-                        int _a58;
+                        HIDWORD(v33) = v32 >> 16;*/
+                        //fixpoint_div(v1->x - v2->x, v1->y - v2->y);
+                        //_a58 = v33 / (v1->y - v2->y);
+                        //_a59 = fixpoint_mul(_a58, sY - v2->y);
+            auto x_div_y = fixpoint_div(v1->x - v2->x, v1->y - v2->y);
+            auto rval = fixpoint_mul(x_div_y, sY - v2->y);  // a / b * c  - looks like projection 
+            if (rval + v2->x > sX)
+              ++v54;
+          }
+          else
+          {
+            auto x_div_y = fixpoint_div(v2->x - v1->x, v2->y - v1->y);
+            auto res = fixpoint_mul(x_div_y, sY - v1->y);
+
+            if (res + v1->x > sX)
+              ++v54;
+
+                        /*int _a58;
                         int _a59;
-                        v32 = v2->x - v1->x;
+                        auto v32 = v2->x - v1->x;
                         LODWORD(v33) = v32 << 16;
                         HIDWORD(v33) = v32 >> 16;
                         _a58 = v33 / (v2->y - v1->y);
-                        _a59 = (unsigned __int64)(_a58 * (signed __int64)(sY - v1->y)) >> 16;
+                        _a59 = fixpoint_mul(_a58, sY - v1->y);
 
                         if (_a59 + pVertices[k].x > sX)
-                          ++v54;
-                      }
-                    }
-                  }
-                }
-
-                v59 = v50;
-              }
-
-              if (pFace->uNumVertices)
-              {
-                if (v54 == 1)
-                {
-                  v35 = v55++;
-                  v43[v35] = uFaceID;
-                }
-              }
-            }
+                          ++v54;*/
           }
-          v4 = v43[0];
         }
+      }
+
+      if (pFace->uNumVertices && v54 == 1)
+        v43[v55++] = uFaceID;
+    }
   }
 
+  v4 = v43[0];
   if ( v55 == 1 )
     return this->pFaces[v4].uSectorID;
   v37 = 0;
--- a/Indoor.h	Mon Mar 25 09:49:12 2013 +0600
+++ b/Indoor.h	Mon Mar 25 09:49:21 2013 +0600
@@ -252,7 +252,7 @@
 
 #define FACE_PORTAL             0x00000001 // portal/two-sided
 #define FACE_CAN_SATURATE_COLOR 0x00000002
-#define FACE_TEXTURE_ANIMATED   0x00000010 // like wavy water
+#define FACE_FLUID              0x00000010 // wavy animated water or lava
 #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
@@ -285,7 +285,7 @@
   inline bool Invisible() const {return uAttributes & FACE_INVISIBLE;}
   inline bool Visible() const   {return !Invisible();}
   inline bool Portal() const    {return uAttributes & FACE_PORTAL;}
-  inline bool Animated() const  {return uAttributes & FACE_TEXTURE_ANIMATED;}
+  inline bool Fluid() const     {return uAttributes & FACE_FLUID;}
   inline bool Clickable() const {return uAttributes & FACE_CLICKABLE;}
 
 
@@ -527,6 +527,10 @@
 #pragma pack(push, 1)
 struct BLVRenderParams
 {
+  inline BLVRenderParams():
+    uFlags(0)
+  {}
+
   int Reset(struct IndoorLocation_drawstru *a2);
 
   int field_0_timer_;
--- a/IndoorCamera.h	Mon Mar 25 09:49:12 2013 +0600
+++ b/IndoorCamera.h	Mon Mar 25 09:49:21 2013 +0600
@@ -4,6 +4,7 @@
 
 #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
--- a/IndoorCameraD3D.cpp	Mon Mar 25 09:49:12 2013 +0600
+++ b/IndoorCameraD3D.cpp	Mon Mar 25 09:49:21 2013 +0600
@@ -998,6 +998,59 @@
   do_draw_debug_line_sw(&a2[v5], uDiffuse, a2, uDiffuse, 0, a5);
 }
 
+
+void IndoorCameraD3D::DebugDrawPortal(BLVFace *pFace)
+{
+  assert(pFace->uNumVertices <= 32);
+
+  RenderVertexSoft sw[32];
+  for (uint i = 0; i < pFace->uNumVertices; ++i)
+  {
+    sw[i].vWorldPosition.x = pIndoor->pVertices[pFace->pVertexIDs[i]].x;
+    sw[i].vWorldPosition.y = pIndoor->pVertices[pFace->pVertexIDs[i]].y;
+    sw[i].vWorldPosition.z = pIndoor->pVertices[pFace->pVertexIDs[i]].z;
+  }
+  ViewTransform(sw, pFace->uNumVertices);
+  Project(sw, pFace->uNumVertices, 0);
+
+
+
+  RenderVertexD3D3 v[32];
+  for (uint i = 0; i < pFace->uNumVertices; ++i)
+  {
+    v[i].pos.x = sw[i].vWorldViewProjX;
+    v[i].pos.y = sw[i].vWorldViewProjY;
+    v[i].pos.z = 1.0 - 1.0 / (sw[i].vWorldViewPosition.x * 0.061758894);
+    v[i].rhw = 1.0 / sw[i].vWorldViewPosition.x;
+    v[i].diffuse = 0x80F020F0;
+    v[i].specular = 0;
+    //v[i].texcoord.x = pFace->pVertexUIDs[i] / (double)pTex->uTextureWidth;
+    //v[i].texcoord.y = pFace->pVertexUIDs[i] / (double)pTex->uTextureHeight;
+    v[i].texcoord.x = 0;
+    v[i].texcoord.y = 0;
+  }
+
+
+  //ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, false));
+  //ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, false));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA));
+  
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetTexture(0, nullptr));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,
+                D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1,
+                v,
+                pFace->uNumVertices,
+                28));
+
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_ZERO));
+  ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, FALSE));
+  //ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, TRUE));
+  //ErrD3D(pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, TRUE));
+}
+
 //----- (00437906) --------------------------------------------------------
 void IndoorCameraD3D::PrepareAndDrawDebugOutline(BLVFace *pFace, unsigned int uDiffuse)
 {
--- a/IndoorCameraD3D.h	Mon Mar 25 09:49:12 2013 +0600
+++ b/IndoorCameraD3D.h	Mon Mar 25 09:49:21 2013 +0600
@@ -158,6 +158,8 @@
   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);
 
+  void DebugDrawPortal(struct BLVFace *pFace);
+
   //void (__thiscall ***vdestructor_ptr)(IndoorCameraD3D *, bool);
   IndoorCameraD3D_Vec3 field_4[3];
   //IndoorCameraD3D_Vec3 field_14;
--- a/Mouse.cpp	Mon Mar 25 09:49:12 2013 +0600
+++ b/Mouse.cpp	Mon Mar 25 09:49:21 2013 +0600
@@ -89,7 +89,7 @@
     v2->uCursorTextureID_2 = v9;
     v2->AllocCursorSystemMem();
     v2->field_C = 0;
-    v2->field_14 = 1;
+    v2->bRedraw = 1;
     v2->bActive = 1;
     if ( !areWeLoadingTexture )
     {
@@ -378,7 +378,7 @@
     v8 = v1->pCursorBitmapRect.z;
     v1->bActive = 0;
     v1->uCursorBitmapWidth = v8 - v5->x;
-    v11 = v1->field_14 == 0;
+    v11 = v1->bRedraw == 0;
     v1->uCursorBitmapHeight = v1->pCursorBitmapRect.w - v1->pCursorBitmapRect.y;
     if ( !v11 )
     {
@@ -393,7 +393,7 @@
         pRenderer->pTargetSurface,
         pRenderer->uTargetSurfacePitch,
         &v1->pCursorBitmapRect);
-      v1->field_14 = 0;
+      v1->bRedraw = false;
     }
   }
 }
--- a/Mouse.h	Mon Mar 25 09:49:12 2013 +0600
+++ b/Mouse.h	Mon Mar 25 09:49:21 2013 +0600
@@ -84,7 +84,7 @@
   int field_8;
   int field_C;
   unsigned int bInitialized;
-  int field_14;
+  unsigned int bRedraw;
   int field_18;
   int field_1C;
   int field_20;
--- a/Outdoor.cpp	Mon Mar 25 09:49:12 2013 +0600
+++ b/Outdoor.cpp	Mon Mar 25 09:49:21 2013 +0600
@@ -88,6 +88,7 @@
   pIndoorCamera->flags = 0;
   if (viewparams->draw_d3d_outlines)
     pIndoorCamera->flags |= INDOOR_CAMERA_DRAW_D3D_OUTLINES;
+  //INDOOR_CAMERA_DRAW_TERRAIN_OUTLINES
 
   pIndoorCamera->sRotationX = pParty->sRotationX;
   pIndoorCamera->sRotationY = pParty->sRotationY;
--- a/Outdoor.h	Mon Mar 25 09:49:12 2013 +0600
+++ b/Outdoor.h	Mon Mar 25 09:49:21 2013 +0600
@@ -89,7 +89,8 @@
   
   inline bool Invisible() const {return uAttributes & FACE_INVISIBLE;}
   inline bool Visible() const   {return !Invisible();}
-  inline bool TwoSided() const  {return uAttributes & FACE_PORTAL;}
+  inline bool Portal() const    {return uAttributes & FACE_PORTAL;}
+  inline bool Fluid() const     {return uAttributes & FACE_FLUID;}
 
   struct Plane_int_ pFacePlane;
   int zCalc1;
--- a/Render.cpp	Mon Mar 25 09:49:12 2013 +0600
+++ b/Render.cpp	Mon Mar 25 09:49:21 2013 +0600
@@ -7609,8 +7609,7 @@
       }
     }
 
-    if (pIndoorCamera->flags & INDOOR_CAMERA_DRAW_D3D_OUTLINES ||
-        pBLVRenderParams->uFlags & INDOOR_CAMERA_DRAW_D3D_OUTLINES )
+    if (pIndoorCamera->flags & INDOOR_CAMERA_DRAW_TERRAIN_OUTLINES || pBLVRenderParams->uFlags & INDOOR_CAMERA_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
--- a/UIHouses.cpp	Mon Mar 25 09:49:12 2013 +0600
+++ b/UIHouses.cpp	Mon Mar 25 09:49:21 2013 +0600
@@ -1484,13 +1484,6 @@
 			v37 = v36 * (100 - pPlayers[uActiveCharacter]->GetMerchant()) / 100;
 			if ( v37 < v36 / 3 )
 			v37 = v36 / 3;
-              
-			__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]
 
 			//if (false)
 			if(byte_4ED970_skill_learn_ability_by_class_table[v35->classType][uMessageParam-36])
--- a/mm7_1.cpp	Mon Mar 25 09:49:12 2013 +0600
+++ b/mm7_1.cpp	Mon Mar 25 09:49:21 2013 +0600
@@ -58,11 +58,18 @@
 bool __fastcall FindMM7CD(HWND hWnd, char *pCDDrive);
 bool __fastcall Initialize(HINSTANCE hInst, char *pCmdLine);
 
+
+//----- (004A1780) mm6_chinese---------------------------------------------
+int fixpoint_div(int a1, int a2)
+{
+  return ((__int64)a1 << 16) / a2;
+}
+
 //----- (004453C0) mm6-----------------------------------------------------
 //----- (004A1760) mm6_chinese---------------------------------------------
 int fixpoint_mul(int a1, int a2)
 {
-  return ((__int64)a1 * a2) >> 16;
+  return ((__int64)a1 * (__int64)a2) / 65536;
 }
 
 //----- (004196A0) --------------------------------------------------------
@@ -1164,7 +1171,7 @@
     }
     else
     {
-      if ( (v0 & 7) != OBJECT_BModel || (unsigned int)v0 >= 0x2000000 )
+      if ( (v0 & 7) != OBJECT_BModel || (signed)v0 >= 0x2000000 )
 	  {
           v4 = pParty->pPickedItem.uItemID;
           if ( !pParty->pPickedItem.uItemID )
--- a/mm7_3.cpp	Mon Mar 25 09:49:12 2013 +0600
+++ b/mm7_3.cpp	Mon Mar 25 09:49:21 2013 +0600
@@ -7756,7 +7756,7 @@
 }
 
 //----- (0048257A) --------------------------------------------------------
-int __fastcall GetTerrainHeightsAroundParty2(int a1, int a2, int *a3, int a4)
+int __fastcall GetTerrainHeightsAroundParty2(int a1, int a2, int *pIsOnWater, int a4)
 {
   unsigned int v4; // ebx@1
   unsigned int v5; // edi@1
@@ -7787,11 +7787,11 @@
   dword_76D51C_terrain_cell_world_pos_around_party_y = pOutdoor->DoGetHeightOnTerrain(v4 + 1, v5);
   dword_76D520_terrain_cell_world_pos_around_party_y = pOutdoor->DoGetHeightOnTerrain(v4 + 1, v5 + 1);
   dword_76D524_terrain_cell_world_pos_around_party_y = pOutdoor->DoGetHeightOnTerrain(v4, v5 + 1);
-  *a3 = 0;
+  *pIsOnWater = false;
   if ( pOutdoor->ActuallyGetSomeOtherTileInfo(v4, v5) & 2 )
-    *a3 = 1;
+    *pIsOnWater = true;
   v14 = 0;
-  if ( !a4 && *a3 )
+  if ( !a4 && *pIsOnWater )
     v14 = -60;
   if ( dword_76D518_terrain_cell_world_pos_around_party_y != dword_76D51C_terrain_cell_world_pos_around_party_y
     || dword_76D51C_terrain_cell_world_pos_around_party_y != dword_76D520_terrain_cell_world_pos_around_party_y
@@ -11973,8 +11973,8 @@
 
 			v6 = ((unsigned short)_evt->v12 << 8) + _evt->v11;
 
-			v3->field_C = ((unsigned short)_evt->v12 << 8) + _evt->v11;
-			v3->field_E = ((unsigned short)_evt->v12 << 8) + _evt->v11;
+			v3->time_left_to_fire = ((unsigned short)_evt->v12 << 8) + _evt->v11;
+            v3->fire_interval = ((unsigned short)_evt->v12 << 8) + _evt->v11;
 			if (v3->timer_evt_type  == EVENT_OnLongTimer && !(short)v6 )
 			{
 				if ( v20 )
@@ -11988,7 +11988,7 @@
 					if ( v3->field_10 )
 					{
 						++dword_5B65C8_timers_count;
-						v3->field_0_time = 0;
+                        v3->next_fire_time = 0;
 						continue;
 					}
 				}
@@ -11997,7 +11997,7 @@
 					v26 != 0 || !v20)
 				{
 					++dword_5B65C8_timers_count;
-					v3->field_0_time = 0;
+					v3->next_fire_time = 0;
 					continue;
 				}
 			}
@@ -12052,7 +12052,7 @@
 						}
 					}
 				}
-				v3->field_0_time = (signed __int64)((double)((seconds
+                v3->next_fire_time = (signed __int64)((double)((seconds
 					+ 60 * minutes
 					+ 3600 * hours
 					+ 0x93A80 * weeks
@@ -13522,95 +13522,65 @@
 }
 
 //----- (00448B67) --------------------------------------------------------
-void __thiscall OnTimer(int a1)
-{
-  int v1; // ebp@1
-  unsigned int v2; // ebx@4
-  unsigned int v3; // edi@4
-  char *pField_C; // esi@6
-  __int16 v5; // ax@8
-  int v6; // ecx@10
-  unsigned int v7; // ebp@12
-  int v8; // eax@16
-  int v9; // eax@19
-  unsigned __int64 v10; // qax@20
-  int v11; // ecx@24
-  int v12; // [sp+Ch] [bp-10h]@5
-  unsigned int v13; // [sp+10h] [bp-Ch]@4
-
-  v1 = 0;
-  if ( !pEventTimer->bPaused )
-  {
-    if ( a1 )
-      dword_5773C0 = 0;
-    v3 = HIDWORD(pParty->uTimePlayed);
-    v2 = LODWORD(pParty->uTimePlayed);
-    v13 = (signed __int64)(pParty->uTimePlayed - _5773B8_event_timer) / 128;
-    if ( v13 )
-    {
-      _5773B8_event_timer = pParty->uTimePlayed;
-      v12 = 0;
-      if ( dword_5B65C8_timers_count > 0 )
-      {
-        pField_C = (char *)&array_5B5928_timers[0].field_C;
-        while ( 1 )
-        {
-          v5 = *(short *)pField_C;
-          if ( *(short *)pField_C != (short)v1 )
-            break;
-          v7 = *((int *)pField_C - 2);
-          if ( v7 <= v3 && (v7 < v3 || *((int *)pField_C - 3) <= v2) )
-          {
-            if ( *((short *)pField_C + 2) )
-            {
-              v8 = 29030400;
-            }
-            else
-            {
-              if ( *((short *)pField_C + 3) )
-              {
-                v8 = 2419200;
-              }
-              else
-              {
-                v9 = -(*((short *)pField_C + 4) != 0);
-                v8 = (v9 & 0x7E900) + 86400;
-              }
-            }
-            v10 = v7 + *((int *)pField_C - 3) + (signed __int64)((double)((signed __int64)v8 << 7) * 0.033333335);//v10 = __PAIR__(v7, *((int *)v4 - 3)) + (signed __int64)((double)((signed __int64)v8 << 7) * 0.033333335);
-            *((int *)pField_C - 3) = v10;
-            *((int *)pField_C - 2) = HIDWORD(v10);
-            if ( HIDWORD(v10) <= v3 && (HIDWORD(v10) < v3 || *((int *)pField_C - 3) < v2) )
-            {
-              *((int *)pField_C - 3) = v2;
-              *((int *)pField_C - 2) = v3;
-            }
-            v11 = *((short *)pField_C - 2);
-            start_event_seq_number = *((short *)pField_C - 1);
-            EventProcessor(v11, 0, 1);
-            start_event_seq_number = 0;
-LABEL_25:
-            v3 = HIDWORD(pParty->uTimePlayed);
-            v2 = LODWORD(pParty->uTimePlayed);
-          }
-LABEL_26:
-          ++v12;
-          pField_C += 32;
-          if ( v12 >= dword_5B65C8_timers_count )
-            return;
-          v1 = 0;
-        }
-        if ( v13 < v5 )
-        {
-          *(short *)pField_C = v5 - v13;
-          goto LABEL_26;
-        }
-        v6 = *((short *)pField_C - 2);
-        *(short *)pField_C = *((short *)pField_C + 1);
-        start_event_seq_number = *((short *)pField_C - 1);
-        EventProcessor(v6, 0, 1);
-        start_event_seq_number = v1;
-        goto LABEL_25;
+void OnTimer(int __unused)
+{
+  if (pEventTimer->bPaused)
+    return;
+  
+  if (__unused)
+    _5773C0_unused = 0;
+  
+  auto v13 = (signed __int64)(pParty->uTimePlayed - _5773B8_event_timer) / 128;
+  if (!v13)
+    return;
+
+  //uint _v2v3 = pParty->uTimePlayed;
+  //v3 = HIDWORD(pParty->uTimePlayed);
+  //v2 = LODWORD(pParty->uTimePlayed);
+
+  _5773B8_event_timer = pParty->uTimePlayed;
+
+  for (uint i = 0; i < dword_5B65C8_timers_count; ++i)
+  {
+        //v4 = (char *)&array_5B5928_timers[0].field_C;
+    auto timer = array_5B5928_timers + i;
+        //while ( 1 )
+        //{
+          //v5 = *(short *)v4;
+    if (timer->time_left_to_fire)
+    {
+      if (v13 < timer->time_left_to_fire)
+        timer->time_left_to_fire -= v13;
+      else
+      {
+        timer->time_left_to_fire = timer->fire_interval;
+
+        start_event_seq_number = timer->timer_evt_seq_num;
+        EventProcessor(timer->timer_evt_ID, 0, 1);
+
+        start_event_seq_number = 0;
+      }
+    }
+    else
+    {
+      if (timer->next_fire_time < pParty->uTimePlayed)
+      {
+        uint next_trigger_time = 1 * 60 * 60 * 24; // 1 day
+        if (timer->field_10)
+          next_trigger_time = 336 * 60 * 60 * 24; // 1 year
+        else if (timer->field_12)
+          next_trigger_time = 28 * 60 * 60 * 24; // 1 month
+        else if (timer->field_14)
+          next_trigger_time = 7 * 60 * 60 * 24; // 1 week
+
+        timer->next_fire_time += (next_trigger_time * 128) / 3.0f;
+        if (timer->next_fire_time < pParty->uTimePlayed) // make sure in wont fire several times in a row is big time interval has lapsed
+          timer->next_fire_time = pParty->uTimePlayed;
+
+        start_event_seq_number = timer->timer_evt_seq_num;
+        EventProcessor(timer->timer_evt_ID, 0, 1);
+
+        start_event_seq_number = 0;
       }
     }
   }
--- a/mm7_4.cpp	Mon Mar 25 09:49:12 2013 +0600
+++ b/mm7_4.cpp	Mon Mar 25 09:49:21 2013 +0600
@@ -439,7 +439,7 @@
 }
 
 //----- (0046D49E) --------------------------------------------------------
-int __fastcall ODM_GetFloorLevel(int X, signed int Y, int Z, int a4, int *a5, int *a6, int a7)
+int __fastcall ODM_GetFloorLevel(int X, signed int Y, int Z, int __unused, int *pIsOnWater, int *a6, int bWaterWalk)
 {
   BSPModel *pBModel; // esi@4
   ODMFace *pFace; // ecx@11
@@ -474,7 +474,7 @@
   v46 = 1;
   dword_721160[0] = -1;
   dword_721110[0] = -1;
-  odm_floor_level[0] = GetTerrainHeightsAroundParty2(X, Y, a5, a7);
+  odm_floor_level[0] = GetTerrainHeightsAroundParty2(X, Y, pIsOnWater, bWaterWalk);
   if ( (signed int)pOutdoor->uNumBModels <= 0 )
   {
     *a6 = 0;
@@ -605,9 +605,9 @@
   if ( v27 )
   {
     v32 = &pOutdoor->pBModels[dword_721160[v27]].pFaces[dword_721110[v27]];
-    *a5 = 0;
-    if ( v32->uAttributes & 0x10 )
-      *a5 = 1;
+    *pIsOnWater = false;
+    if ( v32->Fluid())
+      *pIsOnWater = true;
   }
   if ( odm_floor_level[v27] >= odm_floor_level[0] )
     odm_floor_level[0] = odm_floor_level[v27];
--- a/mm7_data.cpp	Mon Mar 25 09:49:12 2013 +0600
+++ b/mm7_data.cpp	Mon Mar 25 09:49:21 2013 +0600
@@ -1640,7 +1640,7 @@
 int dword_576E28; // weak
 int dword_576E2C; // weak
 __int64 _5773B8_event_timer; // weak
-int dword_5773C0; // weak
+int _5773C0_unused; // weak
 
 
 int dword_591084; // weak
--- a/mm7_data.h	Mon Mar 25 09:49:12 2013 +0600
+++ b/mm7_data.h	Mon Mar 25 09:49:21 2013 +0600
@@ -1146,7 +1146,7 @@
 extern int dword_576E28; // weak
 extern int dword_576E2C; // weak
 extern __int64 _5773B8_event_timer; // weak
-extern int dword_5773C0; // weak
+extern int _5773C0_unused; // weak
 
 
 extern int dword_591084; // weak
@@ -1857,7 +1857,7 @@
 void __fastcall sub_44892E_set_faces_bit(int sCogNumber, int bit, int on);
 void __fastcall ToggleActorGroupFlag(unsigned int uGroupID, unsigned int uFlag, unsigned int bToggle);
 void __thiscall GameUI_StatusBar_UpdateTimedString(unsigned int bForceHide); // idb
-void __thiscall OnTimer(int a1);
+void OnTimer(int);
 void __fastcall sub_448CF4_spawn_monsters(__int16 typeindex, __int16 level, int count, int x, int y, int z, int group, unsigned int uUniqueName);
 void __fastcall sub_448DF8_cast_spell(int spellnum, int rank, int level, int fromx, int fromy, int fromz, int tox, int toy, int toz);
 __int16 __fastcall sub_449A49_door_switch_animation(unsigned int uDoorID, int a2); // idb
@@ -1969,7 +1969,7 @@
 bool __fastcall _46BFFA_check_object_intercept(unsigned int uLayingItemID, signed int a2);
 void __cdecl check_event_triggers();
 int BLV_GetFloorLevel(int x, int y, int z, unsigned int uSectorID, unsigned int *pFaceID);
-int __fastcall ODM_GetFloorLevel(int X, signed int Y, int Z, int a4, int *a5, int *a6, int a7);
+int __fastcall ODM_GetFloorLevel(int X, signed int Y, int Z, int, int *pOnWater, int *a6, int bWaterWalk);
 int __fastcall sub_46D8E3(int a1, signed int a2, int a3, int a4);
 void ODM_GetTerrainNormalAt(int pos_x, int pos_z, Vec3_int_ *out);
 unsigned int __fastcall sub_46DEF2(signed int a2, unsigned int uLayingItemID);
@@ -2169,6 +2169,7 @@
 void DamageMonsterFromParty(signed int a1, unsigned int uActorID_Monster, struct Vec3_int_ *pVelocity);
 
 int fixpoint_mul(int, int);
+int fixpoint_div(int, int);
 
 
 #define ErrD3D(hr) do {extern void ErrHR(HRESULT, const char *, const char *, const char *, int); ErrHR(hr, "Direct3D", __FUNCTION__, __FILE__, __LINE__);} while(0)
--- a/stru176.h	Mon Mar 25 09:49:12 2013 +0600
+++ b/stru176.h	Mon Mar 25 09:49:21 2013 +0600
@@ -5,11 +5,11 @@
 #pragma pack(push, 1)
 struct stru176
 {
-  signed __int64 field_0_time;
+  __int64 next_fire_time;      // timer will either fire event at this time (type 2, field_C == 0)
   __int16 timer_evt_ID;
   __int16 timer_evt_seq_num;
-  __int16 field_C;
-  __int16 field_E;
+  __int16 time_left_to_fire;
+  __int16 fire_interval;       // or fire on these intervals (type 1)
   __int16 field_10;
   __int16 field_12;
   __int16 field_14;