DEADSOFTWARE

replaced manual pool walking with nice iterator (yet one should still call `.release...
[d2df-sdl.git] / src / game / g_monsters.pas
index b7d217b159a306c27aadb399139786a38fead474..bb3d293ded57dc0413327ff01394b2a2055f41f8 100644 (file)
@@ -1,4 +1,4 @@
-(* Copyright (C)  DooM 2D:Forever Developers
+(* Copyright (C)  Doom 2D: Forever Developers
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -50,7 +50,8 @@ const
 }
 
 type
-  TMonster = class(TPoolObject)
+  PMonster = ^TMonster;
+  TMonster = class{$IFDEF USE_MEMPOOL}(TPoolObject){$ENDIF}
   private
     FMonsterType: Byte;
     FUID: Word;
@@ -272,10 +273,12 @@ function g_Mons_getNewTrapFrameId (): DWord; inline;
 function g_Mons_getNewMPlatFrameId (): LongWord; inline;
 
 
+{
 type
   TMonsAlongLineCB = function (mon: TMonster; tag: Integer): Boolean is nested;
 
 function g_Mons_AlongLine (x0, y0, x1, y1: Integer; cb: TMonsAlongLineCB; log: Boolean=false): TMonster;
+}
 
 
 var
@@ -363,11 +366,13 @@ procedure TMonster.setDirty (); inline; begin mNeedSend := true; end;
 
 
 // ////////////////////////////////////////////////////////////////////////// //
+{
 function g_Mons_AlongLine (x0, y0, x1, y1: Integer; cb: TMonsAlongLineCB; log: Boolean=false): TMonster;
 begin
   if not assigned(cb) then begin result := nil; exit; end;
   result := monsGrid.forEachAlongLine(x0, y0, x1, y1, cb, -1, log);
 end;
+}
 
 
 //WARNING! call this after monster position was changed, or coldet will not work right!
@@ -534,11 +539,11 @@ const
      AnimDeltaRight: ((X:  8; Y: -4), (X:  8; Y: -4), (X: -2; Y: -1), (X:  3; Y: -2), (X: 14; Y: -4), (X: 14; Y: -4), (X: -5; Y: -4));
      AnimDeltaLeft:  ((X:  8; Y: -4), (X:  8; Y: -4), (X: -2; Y: -1), (X:  3; Y: -2), (X: 14; Y: -4), (X: 14; Y: -4), (X: -5; Y: -4))),
 
-    (LeftAnim: False; wX: 32; wY: 32; AnimSpeed:(3, 2, 3, 2, 3, 0, 4); //ZOMBY
+    (LeftAnim: True; wX: 32; wY: 32; AnimSpeed:(3, 2, 3, 2, 3, 0, 4); //ZOMBY
      AnimDeltaRight: ((X:  1; Y: -4), (X:  1; Y: -4), (X:  3; Y: -1), (X:  2; Y: -1), (X:  2; Y: -4), (X:  2; Y: -4), (X:  1; Y: -4));
      AnimDeltaLeft:  ((X:  1; Y: -4), (X:  1; Y: -4), (X:  3; Y: -1), (X:  2; Y: -1), (X:  2; Y: -4), (X:  2; Y: -4), (X:  1; Y: -4))),
 
-    (LeftAnim: False; wX: 32; wY: 32; AnimSpeed:(3, 2, 3, 2, 3, 0, 4); //SERG
+    (LeftAnim: True; wX: 32; wY: 32; AnimSpeed:(3, 2, 3, 2, 3, 0, 4); //SERG
      AnimDeltaRight: ((X:  0; Y: -4), (X:  0; Y: -4), (X: -3; Y: -1), (X: -4; Y: -1), (X:  1; Y: -4), (X:  1; Y: -4), (X:  0; Y: -4));
      AnimDeltaLeft:  ((X:  0; Y: -4), (X:  0; Y: -4), (X: -3; Y: -1), (X: -4; Y: -1), (X:  1; Y: -4), (X:  1; Y: -4), (X:  0; Y: -4))),
 
@@ -757,6 +762,7 @@ end;
 
 function isCorpse (o: PObj; immediately: Boolean): Integer;
 
+  (*
   function monsCollCheck (mon: TMonster; atag: Integer): Boolean;
   begin
     atag := atag; // shut up, fpc!
@@ -771,10 +777,13 @@ function isCorpse (o: PObj; immediately: Boolean): Integer;
       result := true;
     end;
   end;
+  *)
 
 var
   a: Integer;
-  mon: TMonster;
+  mon: PMonster;
+  mres: TMonster = nil;
+  it: TMonsterGrid.Iter;
 begin
   result := -1;
 
@@ -784,8 +793,21 @@ begin
   // Èùåì ìåðòâûõ ìîíñòðîâ ïîáëèçîñòè
   if gmon_debug_use_sqaccel then
   begin
-    mon := monsGrid.forEachInAABB(o.X+o.Rect.X, o.Y+o.Rect.Y, o.Rect.Width, o.Rect.Height, monsCollCheck);
-    if (mon <> nil) then result := mon.mArrIdx;
+    //mon := monsGrid.forEachInAABB(o.X+o.Rect.X, o.Y+o.Rect.Y, o.Rect.Width, o.Rect.Height, monsCollCheck);
+    //if (mon <> nil) then result := mon.mArrIdx;
+    it := monsGrid.forEachInAABB(o.X+o.Rect.X, o.Y+o.Rect.Y, o.Rect.Width, o.Rect.Height);
+    for mon in it do
+    begin
+      case mon.FMonsterType of // Íå âîñêðåñèòü:
+        MONSTER_SOUL, MONSTER_PAIN, MONSTER_CYBER, MONSTER_SPIDER,
+        MONSTER_VILE, MONSTER_BARREL, MONSTER_ROBO: begin end;
+        // Îñòàëüíûõ ìîæíî âîñêðåñèòü
+        else mres := mon^;
+      end;
+      if (mres <> nil) then break;
+    end;
+    it.release();
+    if (mres <> nil) then result := mres.mArrIdx;
   end
   else
   begin
@@ -821,6 +843,7 @@ begin
   g_Game_SetLoadingText(_lc[I_LOAD_MONSTER_TEXTURES]+' 5%', 0, True);
   g_Frames_CreateWAD(nil, 'FRAMES_MONSTER_ZOMBY_MESS', GameWAD+':MTEXTURES\ZOMBY_MESS', 64, 64, 9);
   g_Frames_CreateWAD(nil, 'FRAMES_MONSTER_ZOMBY_ATTACK', GameWAD+':MTEXTURES\ZOMBY_ATTACK', 64, 64, 2);
+  g_Frames_CreateWAD(nil, 'FRAMES_MONSTER_ZOMBY_ATTACK_L', GameWAD+':MTEXTURES\ZOMBY_ATTACK_L', 64, 64, 2);
   g_Frames_CreateWAD(nil, 'FRAMES_MONSTER_ZOMBY_PAIN', GameWAD+':MTEXTURES\ZOMBY_PAIN', 64, 64, 1);
   g_Frames_CreateWAD(nil, 'FRAMES_MONSTER_SERG_SLEEP', GameWAD+':MTEXTURES\SERG_SLEEP', 64, 64, 2);
   g_Frames_CreateWAD(nil, 'FRAMES_MONSTER_SERG_GO', GameWAD+':MTEXTURES\SERG_GO', 64, 64, 4);
@@ -828,6 +851,7 @@ begin
   g_Game_SetLoadingText(_lc[I_LOAD_MONSTER_TEXTURES]+' 10%', 0, True);
   g_Frames_CreateWAD(nil, 'FRAMES_MONSTER_SERG_MESS', GameWAD+':MTEXTURES\SERG_MESS', 64, 64, 9);
   g_Frames_CreateWAD(nil, 'FRAMES_MONSTER_SERG_ATTACK', GameWAD+':MTEXTURES\SERG_ATTACK', 64, 64, 2);
+  g_Frames_CreateWAD(nil, 'FRAMES_MONSTER_SERG_ATTACK_L', GameWAD+':MTEXTURES\SERG_ATTACK_L', 64, 64, 2);
   g_Frames_CreateWAD(nil, 'FRAMES_MONSTER_SERG_PAIN', GameWAD+':MTEXTURES\SERG_PAIN', 64, 64, 1);
   g_Frames_CreateWAD(nil, 'FRAMES_MONSTER_MAN_SLEEP', GameWAD+':MTEXTURES\MAN_SLEEP', 64, 64, 2);
   g_Frames_CreateWAD(nil, 'FRAMES_MONSTER_MAN_GO', GameWAD+':MTEXTURES\MAN_GO', 64, 64, 4);
@@ -1063,12 +1087,14 @@ begin
   g_Frames_DeleteByName('FRAMES_MONSTER_ZOMBY_DIE');
   g_Frames_DeleteByName('FRAMES_MONSTER_ZOMBY_MESS');
   g_Frames_DeleteByName('FRAMES_MONSTER_ZOMBY_ATTACK');
+  g_Frames_DeleteByName('FRAMES_MONSTER_ZOMBY_ATTACK_L');
   g_Frames_DeleteByName('FRAMES_MONSTER_ZOMBY_PAIN');
   g_Frames_DeleteByName('FRAMES_MONSTER_SERG_SLEEP');
   g_Frames_DeleteByName('FRAMES_MONSTER_SERG_GO');
   g_Frames_DeleteByName('FRAMES_MONSTER_SERG_DIE');
   g_Frames_DeleteByName('FRAMES_MONSTER_SERG_MESS');
   g_Frames_DeleteByName('FRAMES_MONSTER_SERG_ATTACK');
+  g_Frames_DeleteByName('FRAMES_MONSTER_SERG_ATTACK_L');
   g_Frames_DeleteByName('FRAMES_MONSTER_SERG_PAIN');
   g_Frames_DeleteByName('FRAMES_MONSTER_MAN_SLEEP');
   g_Frames_DeleteByName('FRAMES_MONSTER_MAN_GO');
@@ -3222,7 +3248,7 @@ _end:
                 MONSTER_ZOMBY:
                   begin
                     g_Sound_PlayExAt('SOUND_WEAPON_FIREPISTOL', wx, wy);
-                    g_Weapon_gun(wx, wy, tx, ty, 1, 3, FUID, False);
+                    g_Weapon_gun(wx, wy, tx, ty, 1, 3, FUID, True);
                     g_Player_CreateShell(wx, wy, 0, -2, SHELL_BULLET);
                   end;
                 MONSTER_SERG:
@@ -4684,21 +4710,26 @@ end;
 
 
 function g_Mons_IsAnyAliveAt (x, y: Integer; width, height: Integer): Boolean;
-
+  (*
   function monsCollCheck (mon: TMonster; atag: Integer): Boolean;
   begin
     result := mon.alive;// and g_Obj_Collide(x, y, width, height, @mon.Obj));
   end;
-
+  *)
 var
   idx: Integer;
   mon: TMonster;
+  mit: PMonster;
+  it: TMonsterGrid.Iter;
 begin
   result := false;
   if (width < 1) or (height < 1) then exit;
   if gmon_debug_use_sqaccel then
   begin
-    result := (monsGrid.forEachInAABB(x, y, width, height, monsCollCheck) <> nil);
+    //result := (monsGrid.forEachInAABB(x, y, width, height, monsCollCheck) <> nil);
+    it := monsGrid.forEachInAABB(x, y, width, height);
+    for mit in it do if (mit.alive) then begin result := true; break; end;
+    it.release();
   end
   else
   begin
@@ -4719,21 +4750,26 @@ end;
 
 
 function g_Mons_ForEachAt (x, y: Integer; width, height: Integer; cb: TEachMonsterCB): Boolean;
-
+  (*
   function monsCollCheck (mon: TMonster; atag: Integer): Boolean;
   begin
     result := cb(mon);
   end;
-
+  *)
 var
   idx: Integer;
   mon: TMonster;
+  mit: PMonster;
+  it: TMonsterGrid.Iter;
 begin
   result := false;
   if (width < 1) or (height < 1) then exit;
   if gmon_debug_use_sqaccel then
   begin
-    result := (monsGrid.forEachInAABB(x, y, width, height, monsCollCheck) <> nil);
+    //result := (monsGrid.forEachInAABB(x, y, width, height, monsCollCheck) <> nil);
+    it := monsGrid.forEachInAABB(x, y, width, height);
+    for mit in it do if (cb(mit^)) then begin result := true; break; end;
+    it.release();
   end
   else
   begin
@@ -4754,22 +4790,25 @@ end;
 
 
 function g_Mons_ForEachAliveAt (x, y: Integer; width, height: Integer; cb: TEachMonsterCB): Boolean;
-
+  (*
   function monsCollCheck (mon: TMonster; atag: Integer): Boolean;
   begin
     //result := false;
     //if mon.alive and g_Obj_Collide(x, y, width, height, @mon.Obj) then result := cb(mon);
     if mon.alive then result := cb(mon) else result := false;
   end;
-
+  *)
 var
   idx: Integer;
   mon: TMonster;
+  mit: PMonster;
+  it: TMonsterGrid.Iter;
 begin
   result := false;
   if (width < 1) or (height < 1) then exit;
   if gmon_debug_use_sqaccel then
   begin
+    {
     if (width = 1) and (height = 1) then
     begin
       result := (monsGrid.forEachAtPoint(x, y, monsCollCheck) <> nil);
@@ -4778,6 +4817,16 @@ begin
     begin
       result := (monsGrid.forEachInAABB(x, y, width, height, monsCollCheck) <> nil);
     end;
+    }
+    it := monsGrid.forEachInAABB(x, y, width, height);
+    for mit in it do
+    begin
+      if (mit^.alive) then
+      begin
+        if (cb(mit^)) then begin result := true; break; end;
+      end;
+    end;
+    it.release();
   end
   else
   begin