DEADSOFTWARE

more code for tracing and other shit; NOTHING IS WORKING YET
[d2df-sdl.git] / src / game / g_monsters.pas
index 55a02104f4a56e602de638d507b13490936100cf..f94e8e8dc3160fb7e451647ce6513afb0db0d671 100644 (file)
@@ -20,7 +20,7 @@ interface
 
 uses
   g_basic, e_graphics, g_phys, g_textures,
-  g_saveload, BinEditor, g_panel;
+  g_saveload, BinEditor, g_panel, z_aabbtree, xprofiler;
 
 const
   MONSTATE_SLEEP  = 0;
@@ -90,6 +90,8 @@ type
     function findNewPrey(): Boolean;
     procedure ActivateTriggers();
 
+    function getMapAABB (): AABB2D; inline;
+
   public
     FNoRespawn: Boolean;
     FFireTime: Integer;
@@ -158,6 +160,8 @@ type
     property GameAccelY: Integer read FObj.Accel.Y write FObj.Accel.Y;
     property GameDirection: TDirection read FDirection write FDirection;
 
+    property mapAABB: AABB2D read getMapAABB;
+
     property StartID: Integer read FStartID;
   end;
 
@@ -181,7 +185,7 @@ function  g_Monsters_GetKilledBy (MonsterType: Byte): String;
 
 
 type
-  TEachMonsterCB = function (monidx: Integer; mon: TMonster): Boolean is nested; // return `true` to stop
+  TEachMonsterCB = function (mon: TMonster): Boolean is nested; // return `true` to stop
 
 // throws on invalid uid
 function g_Mons_ByIdx (uid: Integer): TMonster; inline;
@@ -200,17 +204,62 @@ function g_Mons_ForEachAliveAt (x, y: Integer; width, height: Integer; cb: TEach
 function g_Mons_getNewTrapFrameId (): DWord;
 
 
+type
+  TMonsAlongLineCB = function (mon: TMonster; dist: Single): Boolean is nested;
+
+function g_Mons_alongLine (x0, y0, x1, y1: Integer; cb: TMonsAlongLineCB): TMonster;
+
+
 var
   gmon_debug_use_sqaccel: Boolean = true;
 
 
+//HACK!
+procedure g_Mons_ProfilersBegin ();
+procedure g_Mons_ProfilersEnd ();
+
+procedure g_Mons_LOS_Start (); inline;
+procedure g_Mons_LOS_End (); inline;
+
+var
+  profMonsLOS: TProfiler = nil; //WARNING: FOR DEBUGGING ONLY!
+
+
 implementation
 
 uses
   e_log, g_main, g_sound, g_gfx, g_player, g_game,
   g_weapons, g_triggers, MAPDEF, g_items, g_options,
   g_console, g_map, Math, SysUtils, g_menu, wadreader,
-  g_language, g_netmsg, z_aabbtree;
+  g_language, g_netmsg;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+procedure g_Mons_ProfilersBegin ();
+begin
+  if (profMonsLOS = nil) then profMonsLOS := TProfiler.Create('LOS CALC', g_profile_history_size);
+  profMonsLOS.mainBegin(g_profile_los);
+  if g_profile_los then
+  begin
+    profMonsLOS.sectionBegin('loscalc');
+    profMonsLOS.sectionEnd();
+  end;
+end;
+
+procedure g_Mons_ProfilersEnd ();
+begin
+  if (profMonsLOS <> nil) and (g_profile_los) then profMapCollision.mainEnd();
+end;
+
+procedure g_Mons_LOS_Start (); inline;
+begin
+  profMonsLOS.sectionBeginAccum('loscalc');
+end;
+
+procedure g_Mons_LOS_End (); inline;
+begin
+  profMonsLOS.sectionEnd();
+end;
 
 
 // ////////////////////////////////////////////////////////////////////////// //
@@ -218,6 +267,12 @@ var
   monCheckTrapLastFrameId: DWord;
 
 
+function TMonster.getMapAABB (): AABB2D; inline;
+begin
+  result := AABB2D.CreateWH(FObj.X+FObj.Rect.X, FObj.Y+FObj.Rect.Y, FObj.Rect.Width, FObj.Rect.Height);
+end;
+
+
 // ////////////////////////////////////////////////////////////////////////// //
 type
   TDynAABBTreeMonsBase = specialize TDynAABBTreeBase<TMonster>;
@@ -231,7 +286,8 @@ begin
   result := false;
   if (flesh = nil) then raise Exception.Create('DynTree: trying to get dimensions of inexistant monsters');
   if (flesh.Obj.Rect.Width < 1) or (flesh.Obj.Rect.Height < 1) then raise Exception.Create('DynTree: monster without size, wtf?!');
-  aabb := AABB2D.CreateWH(flesh.Obj.X+flesh.Obj.Rect.X, flesh.Obj.Y+flesh.Obj.Rect.Y, flesh.Obj.Rect.Width, flesh.Obj.Rect.Height);
+  //aabb := AABB2D.CreateWH(flesh.Obj.X+flesh.Obj.Rect.X, flesh.Obj.Y+flesh.Obj.Rect.Y, flesh.Obj.Rect.Width, flesh.Obj.Rect.Height);
+  aabb := flesh.getMapAABB();
   if not aabb.valid then raise Exception.Create('wutafuuuuuuu?!');
   result := true;
 end;
@@ -241,18 +297,48 @@ var
   monsTree: TDynAABBTreeMons = nil;
 
 
+function g_Mons_alongLine (x0, y0, x1, y1: Integer; cb: TMonsAlongLineCB): TMonster;
+
+  function sqchecker (mon: TMonster; var ray: Ray2D): Single;
+  var
+    aabb: AABB2D;
+    tmin: Single;
+  begin
+    result := -666.0; // invalid
+    aabb := mon.mapAABB;
+    if not aabb.valid then exit;
+    if aabb.intersects(ray, @tmin) then
+    begin
+      if (tmin <= 0.0) then tmin := 0.0;
+      result := tmin;
+      if cb(mon, tmin) then result := 0.0; // instant stop
+    end;
+  end;
+
+var
+  qr: TDynAABBTreeMons.TSegmentQueryResult;
+begin
+  result := nil;
+  if not assigned(cb) then exit;
+  if monsTree.segmentQuery(qr, x0, y0, x1, y1, sqchecker) then
+  begin
+    if (qr.flesh <> nil) then result := qr.flesh;
+  end;
+end;
+
+
 //WARNING! call this after monster position was changed, or coldet will not work right!
 procedure TMonster.positionChanged ();
 var
   x, y: Integer;
 begin
-  {$IF DEFINED(D2F_DEBUG)}
+  {$IF DEFINED(D2F_DEBUG_MONS_MOVE)}
   //e_WriteLog(Format('monster #%d(%u): pos=(%d,%d); rpos=(%d,%d)', [arrIdx, UID, FObj.X, FObj.Y, FObj.Rect.X, FObj.Rect.Y]), MSG_NOTIFY);
   {$ENDIF}
   if (treeNode = -1) then
   begin
     treeNode := monsTree.insertObject(self, 0);
-    {$IF DEFINED(D2F_DEBUG)}
+    {$IF DEFINED(D2F_DEBUG_MONS_MOVE)}
     monsTree.getNodeXY(treeNode, x, y);
     e_WriteLog(Format('monster #%d(%u): inserted into the tree; nodeid=%d; x=%d; y=%d', [arrIdx, UID, treeNode, x, y]), MSG_NOTIFY);
     {$ENDIF}
@@ -261,7 +347,7 @@ begin
   begin
     monsTree.getNodeXY(treeNode, x, y);
     if (FObj.X+FObj.Rect.X = x) and (FObj.Y+FObj.Rect.Y = y) then exit; // nothing to do
-    {$IF DEFINED(D2F_DEBUG)}e_WriteLog(Format('monster #%d(%u): updating tree; nodeid=%d; x=%d; y=%d', [arrIdx, UID, treeNode, x, y]), MSG_NOTIFY);{$ENDIF}
+    {$IF DEFINED(D2F_DEBUG_MONS_MOVE)}e_WriteLog(Format('monster #%d(%u): updating tree; nodeid=%d; x=%d; y=%d', [arrIdx, UID, treeNode, x, y]), MSG_NOTIFY);{$ENDIF}
 
     {$IFDEF TRUE}
     monsTree.updateObject(treeNode);
@@ -270,7 +356,7 @@ begin
     treeNode := monsTree.insertObject(self);
     {$ENDIF}
 
-    {$IF DEFINED(D2F_DEBUG)}
+    {$IF DEFINED(D2F_DEBUG_MONS_MOVE)}
     monsTree.getNodeXY(treeNode, x, y);
     e_WriteLog(Format('monster #%d(%u): updated tree; nodeid=%d; x=%d; y=%d', [arrIdx, UID, treeNode, x, y]), MSG_NOTIFY);
     {$ENDIF}
@@ -573,6 +659,7 @@ begin
   Result := False;
 end;
 
+
 function BehaviourDamage(SpawnerUID: Word; BH, SelfType: Byte): Boolean;
 var
   m: TMonster;
@@ -602,6 +689,7 @@ begin
   end;
 end;
 
+
 function canShoot(m: Byte): Boolean;
 begin
   Result := False;
@@ -614,7 +702,8 @@ begin
   end;
 end;
 
-function isCorpse(o: PObj; immediately: Boolean): Integer;
+
+function isCorpse (o: PObj; immediately: Boolean): Integer;
 
   function monsCollCheck (mon: TMonster; atag: Integer): Boolean;
   begin
@@ -1932,7 +2021,7 @@ begin
   begin
     if monsTree.isValidId(treeNode) then
     begin
-      {$IF DEFINED(D2F_DEBUG)}
+      {$IF DEFINED(D2F_DEBUG_MONS_MOVE)}
       e_WriteLog(Format('monster #%d(%u): removed from tree; nodeid=%d', [arrIdx, UID, treeNode]), MSG_NOTIFY);
       {$ENDIF}
       monsTree.removeObject(treeNode);
@@ -4447,7 +4536,7 @@ begin
     mon := gMonsters[idx];
     if (mon <> nil) then
     begin
-      result := cb(idx, gMonsters[idx]);
+      result := cb(mon);
       if result then exit;
     end;
   end;
@@ -4466,7 +4555,7 @@ begin
     mon := gMonsters[idx];
     if (mon <> nil) and mon.Live then
     begin
-      result := cb(idx, gMonsters[idx]);
+      result := cb(mon);
       if result then exit;
     end;
   end;
@@ -4513,7 +4602,7 @@ function g_Mons_ForEachAt (x, y: Integer; width, height: Integer; cb: TEachMonst
   function monsCollCheck (mon: TMonster; atag: Integer): Boolean;
   begin
     result := false;
-    if g_Obj_Collide(x, y, width, height, @mon.Obj) then result := cb(mon.arrIdx, mon);
+    if g_Obj_Collide(x, y, width, height, @mon.Obj) then result := cb(mon);
   end;
 
 var
@@ -4535,7 +4624,7 @@ begin
       begin
         if g_Obj_Collide(x, y, width, height, @mon.Obj) then
         begin
-          result := cb(idx, mon);
+          result := cb(mon);
           if result then exit;
         end;
       end;
@@ -4549,7 +4638,7 @@ function g_Mons_ForEachAliveAt (x, y: Integer; width, height: Integer; cb: TEach
   function monsCollCheck (mon: TMonster; atag: Integer): Boolean;
   begin
     result := false;
-    if mon.Live and g_Obj_Collide(x, y, width, height, @mon.Obj) then result := cb(mon.arrIdx, mon);
+    if mon.Live and g_Obj_Collide(x, y, width, height, @mon.Obj) then result := cb(mon);
   end;
 
 var
@@ -4578,7 +4667,7 @@ begin
       begin
         if g_Obj_Collide(x, y, width, height, @mon.Obj) then
         begin
-          result := cb(idx, mon);
+          result := cb(mon);
           if result then exit;
         end;
       end;