DEADSOFTWARE

uidmap for monsters, so we don't have to do linear searches
authorKetmar Dark <ketmar@ketmar.no-ip.org>
Sun, 20 Aug 2017 04:54:57 +0000 (07:54 +0300)
committerKetmar Dark <ketmar@ketmar.no-ip.org>
Sun, 20 Aug 2017 05:33:44 +0000 (08:33 +0300)
src/game/g_basic.pas
src/game/g_monsters.pas
src/game/g_netmsg.pas
src/game/g_player.pas
src/game/g_triggers.pas
src/game/g_weapons.pas

index 626596b01878e2154c7ac0caf6ff9b8f275b97b5..98cebcce846067023ff07b3fa558f1c9ddba0797 100644 (file)
@@ -226,7 +226,7 @@ begin
       while true do
       begin
         result := UID_MAX_PLAYER+$1+Random(UID_MAX_MONSTER-UID_MAX_GAME-UID_MAX_PLAYER+$1);
-        if (g_Monsters_Get(result) = nil) then break;
+        if (g_Monsters_ByUID(result) = nil) then break;
       end;
     end;
   end;
@@ -947,7 +947,7 @@ begin
 
     UID_MONSTER:
     begin
-      m := g_Monsters_Get(UID);
+      m := g_Monsters_ByUID(UID);
       if m = nil then Exit;
       if not m.Live then Exit;
 
index 59b5506a5ee732d02bde51f54f49820dedc7a1c2..4a20c4853a01e09aa08920b90785922338a355d9 100644 (file)
@@ -160,22 +160,23 @@ type
     property StartID: Integer read FStartID;
   end;
 
-procedure g_Monsters_LoadData();
-procedure g_Monsters_FreeData();
-procedure g_Monsters_Init();
-procedure g_Monsters_Free();
-function g_Monsters_Create(MonsterType: Byte; X, Y: Integer;
-            Direction: TDirection; AdjCoord: Boolean = False; ForcedUID: Integer = -1): TMonster;
-procedure g_Monsters_Update();
-procedure g_Monsters_Draw();
-procedure g_Monsters_DrawHealth();
-function  g_Monsters_Get(UID: Word): TMonster;
-procedure g_Monsters_killedp();
-procedure g_Monsters_SaveState(var Mem: TBinMemoryWriter);
-procedure g_Monsters_LoadState(var Mem: TBinMemoryReader);
-function  g_Monsters_GetIDByName(name: String): Integer;
-function  g_Monsters_GetNameByID(MonsterType: Byte): String;
-function  g_Monsters_GetKilledBy(MonsterType: Byte): String;
+
+procedure g_Monsters_LoadData ();
+procedure g_Monsters_FreeData ();
+procedure g_Monsters_Init ();
+procedure g_Monsters_Free ();
+function g_Monsters_Create (MonsterType: Byte; X, Y: Integer; Direction: TDirection;
+  AdjCoord: Boolean = False; ForcedUID: Integer = -1): TMonster;
+procedure g_Monsters_Update ();
+procedure g_Monsters_Draw ();
+procedure g_Monsters_DrawHealth ();
+function  g_Monsters_ByUID (UID: Word): TMonster;
+procedure g_Monsters_killedp ();
+procedure g_Monsters_SaveState (var Mem: TBinMemoryWriter);
+procedure g_Monsters_LoadState (var Mem: TBinMemoryReader);
+function  g_Monsters_GetIDByName (name: String): Integer;
+function  g_Monsters_GetNameByID (MonsterType: Byte): String;
+function  g_Monsters_GetKilledBy (MonsterType: Byte): String;
 
 
 type
@@ -472,6 +473,16 @@ const
 
 var
   gMonsters: array of TMonster;
+  uidMap: array [0..65535] of TMonster; // monster knows it's index
+
+
+procedure clearUidMap ();
+var
+  idx: Integer;
+begin
+  for idx := 0 to High(uidMap) do uidMap[idx] := nil;
+end;
+
 
 var
   pt_x: Integer = 0;
@@ -546,7 +557,7 @@ begin
   UIDType := g_GetUIDType(SpawnerUID);
   if UIDType = UID_MONSTER then
   begin
-    m := g_Monsters_Get(SpawnerUID);
+    m := g_Monsters_ByUID(SpawnerUID);
     if m = nil then Exit;
     MonsterType := m.FMonsterType;
   end;
@@ -866,6 +877,7 @@ begin
   g_Sound_CreateWADEx('SOUND_MONSTER_FISH_ATTACK', GameWAD+':MSOUNDS\FISH_ATTACK');
 
   monsTree := TDynAABBTreeMons.Create();
+  clearUidMap();
 end;
 
 procedure g_Monsters_FreeData();
@@ -1095,12 +1107,10 @@ procedure g_Monsters_Free();
 var
   a: Integer;
 begin
-  if gMonsters <> nil then
-    for a := 0 to High(gMonsters) do
-      gMonsters[a].Free();
-
+  for a := 0 to High(gMonsters) do gMonsters[a].Free();
   monsTree.reset();
   gMonsters := nil;
+  clearUidMap();
 end;
 
 function g_Monsters_Create(MonsterType: Byte; X, Y: Integer;
@@ -1128,6 +1138,8 @@ begin
   mon.arrIdx := find_id;
   mon.treeNode := -1;
 
+  uidMap[mon.FUID] := mon;
+
   // Íàñòðàèâàåì ïîëîæåíèå
   with mon do
   begin
@@ -1179,34 +1191,33 @@ procedure g_Monsters_Update();
 var
   a: Integer;
 begin
-// Öåëåóêàçàòåëü:
+  // Öåëåóêàçàòåëü
   if gTime mod (GAME_TICK*2) = 0 then
   begin
     pt_x := pt_x+pt_xs;
     pt_y := pt_y+pt_ys;
-    if Abs(pt_x) > 246 then
-      pt_xs := -pt_xs;
-    if Abs(pt_y) > 100 then
-      pt_ys := -pt_ys;
+    if abs(pt_x) > 246 then pt_xs := -pt_xs;
+    if abs(pt_y) > 100 then pt_ys := -pt_ys;
   end;
 
   gMon := True; // Äëÿ ðàáîòû BlockMon'à
 
-  if gMonsters <> nil then
-    for a := 0 to High(gMonsters) do
-      if (gMonsters[a] <> nil) then
-        if not gMonsters[a].FRemoved then
-        begin
-          if g_Game_IsClient then
-            gMonsters[a].ClientUpdate()
-          else
-            gMonsters[a].Update();
-        end
-        else
-          begin
-            gMonsters[a].Free();
-            gMonsters[a] := nil;
-          end;
+  for a := 0 to High(gMonsters) do
+  begin
+    if (gMonsters[a] = nil) then continue;
+    if not gMonsters[a].FRemoved then
+    begin
+      if g_Game_IsClient then
+        gMonsters[a].ClientUpdate()
+      else
+        gMonsters[a].Update();
+    end
+    else
+    begin
+      gMonsters[a].Free();
+      gMonsters[a] := nil;
+    end;
+  end;
 
   gMon := False;
 end;
@@ -1238,12 +1249,12 @@ begin
     end;
 end;
 
-function g_Monsters_Get(UID: Word): TMonster;
-var
-  a: Integer;
+function g_Monsters_ByUID (UID: Word): TMonster;
+//var a: Integer;
 begin
+  result := uidMap[UID];
+  {
   Result := nil;
-
   if gMonsters <> nil then
     for a := 0 to High(gMonsters) do
       if (gMonsters[a] <> nil) and
@@ -1252,6 +1263,7 @@ begin
         Result := gMonsters[a];
         Break;
       end;
+  }
 end;
 
 procedure g_Monsters_SaveState(var Mem: TBinMemoryWriter);
@@ -1763,8 +1775,7 @@ begin
   end;
 
 // Òåïåðü öåëü - óäàðèâøèé, åñëè òîëüêî íå ñàì ñåáÿ:
-  if (SpawnerUID <> FUID) and
-  (BehaviourDamage(SpawnerUID, FBehaviour, FMonsterType)) then
+  if (SpawnerUID <> FUID) and (BehaviourDamage(SpawnerUID, FBehaviour, FMonsterType)) then
   begin
     FTargetUID := SpawnerUID;
     FTargetTime := 0;
@@ -1870,8 +1881,7 @@ begin
   if FHealth < FMaxHealth then
   begin
     IncMax(FHealth, Value, FMaxHealth);
-    if g_Game_IsServer and g_Game_IsNet then
-      MH_SEND_MonsterState(FUID);
+    if g_Game_IsServer and g_Game_IsNet then MH_SEND_MonsterState(FUID);
     Result := True;
   end;
 end;
@@ -1896,6 +1906,13 @@ begin
     monsTree.removeObject(treeNode);
   end;
 
+  if (arrIdx <> -1) then
+  begin
+    gMonsters[arrIdx] := nil;
+  end;
+
+  uidMap[FUID] := nil;
+
   inherited Destroy();
 end;
 
@@ -2000,8 +2017,7 @@ procedure TMonster.Push(vx, vy: Integer);
 begin
   FObj.Accel.X := FObj.Accel.X + vx;
   FObj.Accel.Y := FObj.Accel.Y + vy;
-  if g_Game_IsServer and g_Game_IsNet then
-    MH_SEND_MonsterPos(FUID);
+  if g_Game_IsServer and g_Game_IsNet then MH_SEND_MonsterPos(FUID);
 end;
 
 procedure TMonster.SetState(State: Byte; ForceAnim: Byte = 255);
@@ -2125,8 +2141,7 @@ begin
                     NET_GFX_TELE);
   end;
 
-  if g_Game_IsServer and g_Game_IsNet then
-    MH_SEND_MonsterPos(FUID);
+  if g_Game_IsServer and g_Game_IsNet then MH_SEND_MonsterPos(FUID);
   Result := True;
 end;
 
@@ -4344,8 +4359,7 @@ procedure TMonster.CatchFire(Attacker: Word);
 begin
   FFireTime := 100;
   FFireAttacker := Attacker;
-  if g_Game_IsNet and g_Game_IsServer then
-    MH_SEND_MonsterState(FUID);
+  if g_Game_IsNet and g_Game_IsServer then MH_SEND_MonsterState(FUID);
 end;
 
 procedure TMonster.OnFireFlame(Times: DWORD = 1);
index 94326281ae68a2627669144725ed9f0b9aae50c0..213669e57aca2a89a5a93814f88e735080dc2264 100644 (file)
@@ -1321,7 +1321,7 @@ procedure MH_SEND_MonsterSpawn(UID: Word; ID: Integer = NET_EVERYONE);
 var
   M: TMonster;
 begin
-  M := g_Monsters_Get(UID);
+  M := g_Monsters_ByUID(UID);
   if M = nil then
     Exit;
 
@@ -1352,7 +1352,7 @@ procedure MH_SEND_MonsterPos(UID: Word; ID: Integer = NET_EVERYONE);
 var
   M: TMonster;
 begin
-  M := g_Monsters_Get(UID);
+  M := g_Monsters_ByUID(UID);
   if M = nil then Exit;
 
   NetOut.Write(Byte(NET_MSG_MPOS));
@@ -1374,7 +1374,7 @@ procedure MH_SEND_MonsterState(UID: Word; ForcedAnim: Byte = 255; ID: Integer =
 var
   M: TMonster;
 begin
-  M := g_Monsters_Get(UID);
+  M := g_Monsters_ByUID(UID);
   if M = nil then Exit;
 
   NetOut.Write(Byte(NET_MSG_MSTATE));
@@ -1413,7 +1413,7 @@ procedure MH_SEND_MonsterDelete(UID: Word; ID: Integer = NET_EVERYONE);
 var
   M: TMonster;
 begin
-  M := g_Monsters_Get(UID);
+  M := g_Monsters_ByUID(UID);
   if M = nil then Exit;
 
   NetOut.Write(Byte(NET_MSG_MDEL));
@@ -2566,7 +2566,7 @@ var
   Mon: TMonster;
 begin
   ID := M.ReadWord();
-  Mon := g_Monsters_Get(ID);
+  Mon := g_Monsters_ByUID(ID);
   if Mon <> nil then
     Exit;
 
@@ -2587,7 +2587,7 @@ begin
   MDir := M.ReadByte();
 
   g_Monsters_Create(MType, X, Y, TDirection(MDir), False, ID);
-  Mon := g_Monsters_Get(ID);
+  Mon := g_Monsters_ByUID(ID);
   if Mon = nil then
     Exit;
 
@@ -2618,7 +2618,7 @@ var
   ID: Word;
 begin
   ID := M.ReadWord();
-  Mon := g_Monsters_Get(ID);
+  Mon := g_Monsters_ByUID(ID);
   if Mon = nil then
     Exit;
 
@@ -2641,7 +2641,7 @@ var
   AnimRevert: Boolean;
 begin
   ID := M.ReadWord();
-  Mon := g_Monsters_Get(ID);
+  Mon := g_Monsters_ByUID(ID);
   if Mon = nil then Exit;
 
   MState := M.ReadByte();
@@ -2685,7 +2685,7 @@ var
 begin
   ID := M.ReadWord();
 
-  Mon := g_Monsters_Get(ID);
+  Mon := g_Monsters_ByUID(ID);
   if Mon = nil then Exit;
 
   X := M.ReadLongInt();
@@ -2702,7 +2702,7 @@ var
   Mon: TMonster;
 begin
   ID := M.ReadWord();
-  Mon := g_Monsters_Get(ID);
+  Mon := g_Monsters_ByUID(ID);
   if Mon = nil then Exit;
   Mon.SetState(5);
   Mon.MonsterRemoved := True;
index c1b7c087645cce6d7e413ff3237812e18e5a06ca..612a4fb0aee855f664ae797deb1113959ba59583 100644 (file)
@@ -3121,7 +3121,7 @@ begin
       end
     else if g_GetUIDType(SpawnerUID) = UID_MONSTER then
       begin // Óáèò ìîíñòðîì
-        mon := g_Monsters_Get(SpawnerUID);
+        mon := g_Monsters_ByUID(SpawnerUID);
         if mon = nil then
           s := '?'
         else
@@ -6393,7 +6393,7 @@ begin
         if (g_GetUIDType(Target.UID) = UID_MONSTER) and
             vsMonster then
           begin // Ìîíñòð
-            mon := g_Monsters_Get(Target.UID);
+            mon := g_Monsters_ByUID(Target.UID);
             if mon <> nil then
               begin
                 Target.X := mon.Obj.X;
@@ -6626,7 +6626,7 @@ begin
             end
           else
             begin // Öåëü - ìîíñòð
-              mon := g_Monsters_Get(Target.UID);
+              mon := g_Monsters_ByUID(Target.UID);
               if (mon = nil) or (not mon.Live) then
                 Target.UID := 0; // òî çàáûòü öåëü
             end;
@@ -7378,7 +7378,7 @@ begin
         if (g_GetUIDType(FLastSpawnerUID) = UID_MONSTER) and
            LongBool(gGameSettings.Options and GAME_OPTION_BOTVSMONSTER) then
         begin // Ìîíñòð
-          mon := g_Monsters_Get(FLastSpawnerUID);
+          mon := g_Monsters_ByUID(FLastSpawnerUID);
           ok := not TargetOnScreen(mon.Obj.X + mon.Obj.Rect.X,
                                    mon.Obj.Y + mon.Obj.Rect.Y);
         end;
index 4fefb5d34b612cda301c2ed28f1734235b8e8867..29ea42ee3ddf3b1702d8a0569a4a490600ee6672 100644 (file)
@@ -755,7 +755,7 @@ begin
 
     UID_MONSTER:
       begin
-        m := g_Monsters_Get(ActivateUID);
+        m := g_Monsters_ByUID(ActivateUID);
         if m = nil then
           Exit;
 
@@ -801,7 +801,7 @@ begin
 
     UID_MONSTER:
       begin
-        m := g_Monsters_Get(ActivateUID);
+        m := g_Monsters_ByUID(ActivateUID);
         if m = nil then
           Exit;
 
@@ -1880,7 +1880,7 @@ begin
 
                 UID_MONSTER:
                   begin
-                    m := g_Monsters_Get(ActivateUID);
+                    m := g_Monsters_ByUID(ActivateUID);
                     if m = nil then
                       Exit;
 
index f8028eef33fc30d94871d95b80759ae45421593c..f3accc605fb3ad2cf654c3b8811462cb98139931 100644 (file)
@@ -244,11 +244,11 @@ begin
 end;
 
 procedure CheckTrap(ID: DWORD; dm: Integer; t: Byte);
-
 var
   a, b, c, d, i1, i2: Integer;
   pl, mn: WArray;
 
+  {
   function monsWaterCheck (monidx: Integer; mon: TMonster): Boolean;
   begin
     result := false; // don't stop
@@ -258,6 +258,17 @@ var
       mn[i2] := monidx;
     end;
   end;
+  }
+
+  function monsWaterCheck (monidx: Integer; mon: TMonster): Boolean;
+  begin
+    result := false; // don't stop
+    if (not InWArray(monidx, mn)) and (i2 < 1023) then //FIXME
+    begin
+      i2 += 1;
+      mn[i2] := monidx;
+    end;
+  end;
 
 begin
   if (gWater = nil) or (WaterMap = nil) then Exit;
@@ -292,16 +303,22 @@ begin
                   end;
         end;
 
-        g_Mons_ForEach(monsWaterCheck);
+        //g_Mons_ForEach(monsWaterCheck);
+        g_Mons_ForEachAtAlive(
+          gWater[WaterMap[a][c]].X, gWater[WaterMap[a][c]].Y,
+          gWater[WaterMap[a][c]].Width, gWater[WaterMap[a][c]].Height,
+          monsWaterCheck);
       end;
 
       if i1 <> -1 then
-        for d := 0 to i1 do
-          gPlayers[pl[d]].Damage(dm, Shots[ID].SpawnerUID, 0, 0, t);
+      begin
+        for d := 0 to i1 do gPlayers[pl[d]].Damage(dm, Shots[ID].SpawnerUID, 0, 0, t);
+      end;
 
       if i2 <> -1 then
-        for d := 0 to i2 do
-          g_Mons_ByIdx(mn[d]).Damage(dm, 0, 0, Shots[ID].SpawnerUID, t);
+      begin
+        for d := 0 to i2 do g_Mons_ByIdx(mn[d]).Damage(dm, 0, 0, Shots[ID].SpawnerUID, t);
+      end;
     end;
 
   pl := nil;
@@ -318,9 +335,9 @@ begin
   tt := g_GetUIDType(SpawnerUID);
   if tt = UID_MONSTER then
   begin
-    mon := g_Monsters_Get(SpawnerUID);
+    mon := g_Monsters_ByUID(SpawnerUID);
     if mon <> nil then
-      mt := g_Monsters_Get(SpawnerUID).MonsterType
+      mt := g_Monsters_ByUID(SpawnerUID).MonsterType
     else
       mt := 0;
   end
@@ -876,7 +893,7 @@ begin
 
   case g_GetUIDType(UID) of
     UID_PLAYER: Result := HitPlayer(g_Player_Get(UID), d, 0, 0, SpawnerUID, t);
-    UID_MONSTER: Result := HitMonster(g_Monsters_Get(UID), d, 0, 0, SpawnerUID, t);
+    UID_MONSTER: Result := HitMonster(g_Monsters_ByUID(UID), d, 0, 0, SpawnerUID, t);
     else Exit;
   end;
 end;