diff mm7_3.cpp @ 138:a8ec7e1e18b6

Sliding downhill & relative subs. how it's done: each time you get a little bit pushed in the air along terrain normal, and then falling to the gravity, gradually sliding downwards. nice trick
author Nomad
date Tue, 12 Feb 2013 00:22:30 +0200
parents 1c471f3629fb
children 7eeea515f5ff
line wrap: on
line diff
--- a/mm7_3.cpp	Mon Feb 11 20:27:00 2013 +0200
+++ b/mm7_3.cpp	Tue Feb 12 00:22:30 2013 +0200
@@ -995,7 +995,7 @@
     v74 = v4;
     if ( !v0->CanAct() )
       v74 = 0;
-    v70 = GetTerrainHeightsAroundParty(v0->vPosition.x, v0->vPosition.y);
+    v70 = IsTerrainSlopeTooHigh(v0->vPosition.x, v0->vPosition.y);
     v5 = sub_46D49E_prolly_get_world_y_under_party(
            v0->vPosition.x,
            v0->vPosition.y,
@@ -1088,7 +1088,7 @@
         v18 = v0->vPosition.y;
         v19 = v0->vPosition.x;
         v0->vPosition.z = v7;
-        _46DCC8_get_gravity_direction_outdoor(v19, v18, &v62);
+        ODM_GetTerrainNormalAt(v19, v18, &v62);
         v20 = GetGravityStrength();
         v21 = v62.y;
         v22 = v62.z;
@@ -1826,7 +1826,7 @@
   v1 = &pLayingItems[uLayingItemID];
   v58 = 0;
   v2 = &pObjectList->pObjects[v1->uObjectDescID];
-  v57 = GetTerrainHeightsAroundParty(v1->vPosition.x, v1->vPosition.y);
+  v57 = IsTerrainSlopeTooHigh(v1->vPosition.x, v1->vPosition.y);
   v3 = v1->vPosition.y;
   v4 = v1->vPosition.x;
   v5 = v2->uHeight;
@@ -1864,7 +1864,7 @@
       v11 = v1->vPosition.y;
       v12 = v1->vPosition.x;
       v1->vPosition.z = v8;
-      _46DCC8_get_gravity_direction_outdoor(v12, v11, &v51);
+      ODM_GetTerrainNormalAt(v12, v11, &v51);
       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 = (Actor *)((unsigned __int64)(v56 * (signed __int64)v51.x) >> 16);
@@ -2994,7 +2994,7 @@
 //----- (00473893) --------------------------------------------------------
 void __cdecl ODM_ProcessPartyActions()
 {
-  int _zero; // esi@1
+  //int _zero; // esi@1
   int v1; // edi@1
   int v2; // ebx@1
   int v3; // eax@14
@@ -3092,9 +3092,10 @@
   int v95; // [sp-4h] [bp-98h]@104
   int v96; // [sp-4h] [bp-98h]@246
   int v97; // [sp+Ch] [bp-88h]@180
-  int v98; // [sp+10h] [bp-84h]@147
-  int v99; // [sp+14h] [bp-80h]@147
-  int v100; // [sp+18h] [bp-7Ch]@147
+  Vec3_int_ v98;
+  //int v98; // [sp+10h] [bp-84h]@147
+  //int v99; // [sp+14h] [bp-80h]@147
+  //int v100; // [sp+18h] [bp-7Ch]@147
   bool v101; // [sp+1Ch] [bp-78h]@33
   int v102; // [sp+20h] [bp-74h]@1
   int v103; // [sp+24h] [bp-70h]@1
@@ -3128,7 +3129,6 @@
 
   v121 = pParty->uFallSpeed;
   v123 = pParty->vPosition.z;
-  _zero = 0;
   v1 = 0;
   v103 = 0;
   v2 = 0;
@@ -3137,7 +3137,7 @@
   v117 = pParty->vPosition.y;
   v113 = pParty->field_6F0;
   bJumping = 0;
-  v118 = GetTerrainHeightsAroundParty(pParty->vPosition.x, pParty->vPosition.y);
+  auto partyAtHighSlope = IsTerrainSlopeTooHigh(pParty->vPosition.x, pParty->vPosition.y);
   v114 = 0;
   v124 = 0;
   v108 = 0;
@@ -3205,35 +3205,34 @@
         ++v4;
       }
       while ( (signed int)v4 <= (signed int)&pPlayers[4] );
-      _zero = 0;
     }
   }
   v109 = -1;
-  if ( pParty->bFlying != _zero )
+  if ( pParty->bFlying )
     v109 = sub_46D8E3(v116, v117, v123 + pParty->uPartyHeight, (int)&v102);
-  v107 = v108 == _zero;
+  v107 = v108 == 0;
   v105 = v111 + 1;
   if ( v123 <= v111 + 1 )
   {
     v109 = -1;
-    pParty->bFlying = _zero;
+    pParty->bFlying = false;
   }
   else
   {
     bJumping = 1;
   }
   v101 = v123 - v111 <= 32;
-  if ( bWalkSound != _zero && pParty->field_6F8 > _zero )
+  if ( bWalkSound && pParty->field_6F8 > 0 )
     pParty->field_6F8 -= pEventTimer->uTimeElapsed;
   if ( !bUnderwater
-    && SHIDWORD(pParty->pPartyBuffs[7].uExpireTime) <= _zero
-    && (SHIDWORD(pParty->pPartyBuffs[7].uExpireTime) < _zero || LODWORD(pParty->pPartyBuffs[7].uExpireTime) <= _zero) )
-    pParty->bFlying = _zero;
-  if ( bJumping == _zero )
+    && SHIDWORD(pParty->pPartyBuffs[7].uExpireTime) <= 0
+    && (SHIDWORD(pParty->pPartyBuffs[7].uExpireTime) < 0 || LODWORD(pParty->pPartyBuffs[7].uExpireTime) <= 0) )
+    pParty->bFlying = false;
+  if (!bJumping)
   {
     if ( pParty->field_6F4_packedid != (8 * v108 | OBJECT_BModel) )
     {
-      if ( v108 != _zero )
+      if (v108)
       {
         if ( v108 >> 6 < pOutdoor->uNumBModels )
         {
@@ -3269,12 +3268,14 @@
     switch ( pPartyActionQueue->Next() )
     {
       case PARTY_FlyUp:
-        if ( (signed __int64)pParty->pPartyBuffs[7].uExpireTime > 0 || bUnderwater == 1 )
-        {
-          pParty->bFlying = 0;
-          if ( bUnderwater
-            || pParty->pPartyBuffs[7].uFlags & 1
-            || pParty->pPlayers[pParty->pPartyBuffs[7].uCaster-1].sMana <= 0 )//*(int *)&pParty->pArtifactsFound[6972 * pParty->pPartyBuffs[7].uCaster + 10] > 0 )
+      {
+        if (!pParty->FlyActive() && !bUnderwater)
+          break;
+
+        pParty->bFlying = false;
+        if (bUnderwater ||
+            pParty->pPartyBuffs[PARTY_BUFF_FLY].uFlags & 1 ||
+            pParty->pPlayers[pParty->pPartyBuffs[PARTY_BUFF_FLY].uCaster - 1].sMana <= 0 )
           {
             if ( pParty->vPosition.z < 4000 || bJumping )
             {
@@ -3306,8 +3307,9 @@
               v127 = (BSPModel *)1;
             }
           }
-        }
-        goto LABEL_118;
+      }
+      break;
+
       case PARTY_FlyDown:
         if ( (signed __int64)pParty->pPartyBuffs[7].uExpireTime > 0 || bUnderwater == 1 )
         {
@@ -3456,7 +3458,7 @@
           v1 += v129;
           goto LABEL_93;
         }
-        if ( v118 && !v108 )
+        if ( partyAtHighSlope && !v108 )
         {
           v23 = stru_5C6E00->SinCos(_angle_y);
           v24 = (double)_walk_speed;
@@ -3548,7 +3550,7 @@
         _angle_x = 0;
         goto LABEL_118;
       case PARTY_Jump:
-        if ( (!v118 || v108) && !bJumping && pParty->field_24 && !(pParty->uFlags & 4) && !(BYTE1(pParty->uFlags) & 2) )
+        if ( (!partyAtHighSlope || v108) && !bJumping && pParty->field_24 && !(pParty->uFlags & 4) && !(BYTE1(pParty->uFlags) & 2) )
         {
           v126 = pParty->field_24 << 6;
           bJumping = 1;
@@ -3609,7 +3611,7 @@
     v121 += 2 * v33;
     goto LABEL_149;
   }
-  if ( !v118 )
+  if ( !partyAtHighSlope )
   {
     v34 = v121;
 LABEL_149:
@@ -3621,16 +3623,20 @@
   {
     if ( v108 )
       goto LABEL_150;
+
+    // rolling down the hill
+    // how it's done: you get a little bit pushed in the air along terrain normal, getting in the air
+    // and falling to the gravity, gradually sliding downwards. nice trick
     v123 = v111;
-    _46DCC8_get_gravity_direction_outdoor(v116, v117, (Vec3_int_ *)&v98);
+    ODM_GetTerrainNormalAt(v116, v117, &v98);
     v35 = v121 + -8 * pEventTimer->uTimeElapsed * GetGravityStrength();
-    v129 = abs((signed __int64)v2 * (signed __int64)v98 + (signed __int64)v1 * (signed __int64)v99 + (signed __int64)v35 * (signed __int64)v100) >> 16;
-    v127 = (BSPModel *)((unsigned __int64)(v129 * (signed __int64)v98) >> 16);
+    v129 = abs((signed __int64)v2 * v98.x + (signed __int64)v1 * v98.y + (signed __int64)v35 * v98.z) >> 16;
+    v127 = (BSPModel *)((unsigned __int64)(v129 * (signed __int64)v98.x) >> 16);
     v2 += (int)v127;
-    v127 = (BSPModel *)((unsigned __int64)(v129 * (signed __int64)v99) >> 16);
+    v127 = (BSPModel *)((unsigned __int64)(v129 * (signed __int64)v98.y) >> 16);
     v1 += (int)v127;
     v128 = v1;
-    v127 = (BSPModel *)((unsigned __int64)(v129 * (signed __int64)v100) >> 16);
+    v127 = (BSPModel *)((unsigned __int64)(v129 * (signed __int64)v98.z) >> 16);
     v34 = (int)((char *)v127 + v35);
     v32 = 0;
     v121 = v34;
@@ -3660,7 +3666,7 @@
 LABEL_150:
   pParty->uFallStartY = v123;
 LABEL_151:
-  if ( v2 * v2 + v1 * v1 < 400 && !v118 )
+  if ( v2 * v2 + v1 * v1 < 400 && !partyAtHighSlope )
   {
     *(float *)&v128 = 0.0;
     v2 = 0;
@@ -3720,8 +3726,8 @@
                         &v130,
                         &v110,
                         0);
-    v127 = (BSPModel *)GetTerrainHeightsAroundParty(_angle_x, v117);
-    v42 = GetTerrainHeightsAroundParty(v116, _angle_y);
+    v127 = (BSPModel *)IsTerrainSlopeTooHigh(_angle_x, v117);
+    v42 = IsTerrainSlopeTooHigh(v116, _angle_y);
     v107 = 0;
     v118 = v42;
     if ( !v97 && !v110 && !v108 )
@@ -3746,7 +3752,7 @@
                          &v130,
                          &v108,
                          0);
-    if ( GetTerrainHeightsAroundParty(_angle_x, _angle_y) && (signed int)v127 <= v123 )
+    if ( IsTerrainSlopeTooHigh(_angle_x, _angle_y) && (signed int)v127 <= v123 )
     {
       v43 = 1;
 LABEL_197:
@@ -9434,77 +9440,95 @@
 
 
 //----- (004823F4) --------------------------------------------------------
-bool __fastcall GetTerrainHeightsAroundParty(int a1, int a2)
-{
-  unsigned int v2; // ebx@1
-  unsigned int v3; // edi@1
-  int v4; // eax@1
-  int v6; // esi@5
-  int v7; // ecx@6
-  int v8; // edx@6
-  int v9; // eax@6
-  int v10; // esi@10
-  int v11; // [sp+14h] [bp-8h]@1
-  int v12; // [sp+18h] [bp-4h]@1
-
-  v12 = a1;
-  v11 = a2;
-  v2 = WorldPosToGridCellX(a1);
-  v3 = WorldPosToGridCellZ(v11) - 1;
-  dword_76D568_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(v2);
-  dword_76D56C_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(v2 + 1);
-  dword_76D570_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(v2 + 1);
-  dword_76D574_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(v2);
-  dword_76D558_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(v3);
-  dword_76D55C_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(v3);
-  dword_76D560_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(v3 + 1);
-  dword_76D564_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(v3 + 1);
-  dword_76D548_terrain_cell_world_pos_around_party_y = pOutdoor->DoGetHeightOnTerrain(v2, v3);
-  dword_76D54C_terrain_cell_world_pos_around_party_y = pOutdoor->DoGetHeightOnTerrain(v2 + 1, v3);
-  dword_76D550_terrain_cell_world_pos_around_party_y = pOutdoor->DoGetHeightOnTerrain(v2 + 1, v3 + 1);
-  v4 = pOutdoor->DoGetHeightOnTerrain(v2, v3 + 1);
-  dword_76D554_terrain_cell_world_pos_around_party_y = v4;
-  if ( dword_76D548_terrain_cell_world_pos_around_party_y == dword_76D54C_terrain_cell_world_pos_around_party_y
-    && dword_76D54C_terrain_cell_world_pos_around_party_y == dword_76D550_terrain_cell_world_pos_around_party_y
-    && dword_76D550_terrain_cell_world_pos_around_party_y == v4 )
-    return 0;
-  v6 = abs(v12 - dword_76D568_terrain_cell_world_pos_around_party_x);
-  if ( abs(dword_76D558_terrain_cell_world_pos_around_party_z - v11) >= v6 )
-  {
-    v7 = dword_76D554_terrain_cell_world_pos_around_party_y;
-    v8 = dword_76D550_terrain_cell_world_pos_around_party_y;
-    v9 = dword_76D548_terrain_cell_world_pos_around_party_y;
-  }
-  else
-  {
-    v7 = dword_76D54C_terrain_cell_world_pos_around_party_y;
-    v8 = dword_76D548_terrain_cell_world_pos_around_party_y;
-    v9 = dword_76D550_terrain_cell_world_pos_around_party_y;
-  }
-  if ( v7 >= v8 )
-  {
-    v10 = v8;
-    if ( v8 < v9 )
+bool IsTerrainSlopeTooHigh(int pos_x, int pos_z)
+{
+  //unsigned int v2; // ebx@1
+  //unsigned int v3; // edi@1
+  //int v4; // eax@1
+  //int v6; // esi@5
+  //int v7; // ecx@6
+  //int v8; // edx@6
+  //int v9; // eax@6
+  //int v10; // esi@10
+  //int v11; // [sp+14h] [bp-8h]@1
+  //int v12; // [sp+18h] [bp-4h]@1
+
+  //v12 = a1;
+  //v11 = a2;
+  auto grid_x = WorldPosToGridCellX(pos_x);
+  auto grid_z = WorldPosToGridCellZ(pos_z) - 1;
+
+  auto party_grid_x1 = GridCellToWorldPosX(grid_x);
+  //dword_76D56C_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(grid_x + 1);
+  //dword_76D570_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(grid_x + 1);
+  //dword_76D574_terrain_cell_world_pos_around_party_x = GridCellToWorldPosX(grid_x);
+  auto party_grid_z1 = GridCellToWorldPosZ(grid_z);
+  //dword_76D55C_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(grid_z);
+  //dword_76D560_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(grid_z + 1);
+  //dword_76D564_terrain_cell_world_pos_around_party_z = GridCellToWorldPosZ(grid_z + 1);
+  auto party_x1z1_y = pOutdoor->DoGetHeightOnTerrain(grid_x, grid_z);
+  auto party_x2z1_y = pOutdoor->DoGetHeightOnTerrain(grid_x + 1, grid_z);
+  auto party_x2z2_y = pOutdoor->DoGetHeightOnTerrain(grid_x + 1, grid_z + 1);
+  auto party_x1z2_y = pOutdoor->DoGetHeightOnTerrain(grid_x, grid_z + 1);
+  //dword_76D554_terrain_cell_world_pos_around_party_y = v4;
+  if (party_x1z1_y == party_x2z1_y &&
+      party_x2z1_y == party_x2z2_y &&
+      party_x2z2_y == party_x1z2_y )
+    return false;
+
+  auto dx = abs(pos_x - party_grid_x1),
+       dz = abs(party_grid_z1 - pos_z);
+
+  int y1, y2, y3;
+  if (dz >= dx)
+  {
+    y1 = party_x1z2_y;  //  lower-left triangle
+    y2 = party_x2z2_y;  //  y3 | \ 
+    y3 = party_x1z1_y;  //     |   \ 
+                        /*     |     \ 
+                               |______ \
+                            y1           y2   */
+  }
+  else
+  {
+    y1 = party_x2z1_y;  // upper-right
+    y2 = party_x1z1_y;  //  y2_______ y1
+    y3 = party_x2z2_y;  //    \     |
+                        /*      \   |
+                                  \ |
+                                    y3     */
+  }
+
+  int y_min = min(y1, min(y2, y3)),
+      y_max = max(y1, max(y2, y3));
+  return y_max - y_min > 512;
+
+  /*if ( y1 >= y2 )
+  {
+    y_min = y2;
+    if ( y2 < y3 )
       goto LABEL_13;
 LABEL_12:
-    v10 = v9;
+    y_min = y3;
     goto LABEL_13;
   }
-  if ( v7 >= v9 )
+  else if ( y1 >= y3 )
     goto LABEL_12;
-  v10 = v7;
+  else
+  y_min = y1;
+
 LABEL_13:
-  if ( v7 <= v8 )
-  {
-    if ( v8 > v9 )
-      v9 = v8;
-  }
-  else
-  {
-    if ( v7 > v9 )
-      v9 = v7;
-  }
-  return v9 - v10 > 512;
+  if ( y1 <= y2 )
+  {
+    if ( y2 > y3 )
+      y3 = y2;
+  }
+  else
+  {
+    if ( y1 > y3 )
+      y3 = y1;
+  }
+  return y3 - v10 > 512;*/
 }