DEADSOFTWARE

some fixes for recursive grid queries (grid doesn't support recursive queries, but...
authorKetmar Dark <ketmar@ketmar.no-ip.org>
Tue, 29 Aug 2017 15:42:35 +0000 (18:42 +0300)
committerKetmar Dark <ketmar@ketmar.no-ip.org>
Tue, 29 Aug 2017 15:43:10 +0000 (18:43 +0300)
src/game/g_grid.pas
src/game/g_items.pas
src/game/g_map.pas
src/game/g_triggers.pas
src/shared/utils.pas

index b4b0e32795cddfaa38864fa8154c2f260e903328..346770246cfd96eb4bb196e9471360ef95763d13 100644 (file)
@@ -102,6 +102,7 @@ type
     mProxyFree: TBodyProxyId; // free
     mProxyCount: Integer; // currently used
     mProxyMaxCount: Integer;
+    mInQuery: Boolean;
 
   public
     dbgShowTraceLog: Boolean;
@@ -1235,6 +1236,9 @@ begin
   if (x+w <= 0) or (y+h <= 0) then exit;
   if (x >= gw*tsize) or (y >= mHeight*tsize) then exit;
 
+  if mInQuery then raise Exception.Create('recursive queries aren''t supported');
+  mInQuery := true;
+
   // increase query counter
   Inc(mLastQuery);
   if (mLastQuery = 0) then
@@ -1274,11 +1278,12 @@ begin
           if (x0+w <= px.mX) or (y0+h <= px.mY) then continue;
           if assigned(cb) then
           begin
-            if cb(px.mObj, ptag) then begin result := px.mObj; exit; end;
+            if cb(px.mObj, ptag) then begin result := px.mObj; mInQuery := false; exit; end;
           end
           else
           begin
             result := px.mObj;
+            mInQuery := false;
             exit;
           end;
         end;
@@ -1286,6 +1291,8 @@ begin
       end;
     end;
   end;
+
+  mInQuery := false;
 end;
 
 
@@ -1552,6 +1559,9 @@ begin
 
   //if (dbgShowTraceLog) then e_WriteLog(Format('raycast start: (%d,%d)-(%d,%d); xptr^=%d; yptr^=%d', [ax0, ay0, ax1, ay1, xptr^, yptr^]), MSG_NOTIFY);
 
+  if mInQuery then raise Exception.Create('recursive queries aren''t supported');
+  mInQuery := true;
+
   // increase query counter
   Inc(mLastQuery);
   if (mLastQuery = 0) then
@@ -1629,6 +1639,7 @@ begin
                     result := px.mObj;
                     ex := x;
                     ey := y;
+                    mInQuery := false;
                     exit;
                   end;
                 end
@@ -1643,6 +1654,7 @@ begin
                     ex := x;
                     ey := y;
                     result := px.mObj;
+                    mInQuery := false;
                     exit;
                   end;
                 end;
@@ -1697,6 +1709,7 @@ begin
                   result := px.mObj;
                   ex := prevx;
                   ey := prevy;
+                  mInQuery := false;
                   exit;
                 end;
               end
@@ -1720,8 +1733,8 @@ begin
           // next cell
           ccidx := cc.next;
         end;
-        if wasHit and not assigned(cb) then begin result := lastObj; exit; end;
-        if assigned(cb) and cb(nil, 0, x, y, x, y) then begin result := lastObj; exit; end;
+        if wasHit and not assigned(cb) then begin result := lastObj; mInQuery := false; exit; end;
+        if assigned(cb) and cb(nil, 0, x, y, x, y) then begin result := lastObj; mInQuery := false; exit; end;
       end;
       // skip to next tile
       if hopt then
@@ -1778,6 +1791,7 @@ begin
     end;
     // we can travel less than one cell
     if wasHit and not assigned(cb) then result := lastObj else begin ex := ax1; ey := ay1; end;
+    mInQuery := false;
     exit;
   end;
   {$ENDIF}
@@ -1811,11 +1825,12 @@ begin
         // signal cell completion
         if assigned(cb) then
         begin
-          if cb(nil, 0, xptr^+minx, yptr^+miny, prevx, prevy) then begin result := lastObj; exit; end;
+          if cb(nil, 0, xptr^+minx, yptr^+miny, prevx, prevy) then begin result := lastObj; mInQuery := false; exit; end;
         end
         else if wasHit then
         begin
           result := lastObj;
+          mInQuery := false;
           exit;
         end;
       end;
@@ -1853,6 +1868,7 @@ begin
                   result := px.mObj;
                   ex := prevx;
                   ey := prevy;
+                  mInQuery := false;
                   exit;
                 end;
               end
@@ -1890,11 +1906,12 @@ begin
         ccidx := -1;
         if assigned(cb) then
         begin
-          if cb(nil, 0, x, y, prevx, prevy) then begin result := lastObj; exit; end;
+          if cb(nil, 0, x, y, prevx, prevy) then begin result := lastObj; mInQuery := false; exit; end;
         end
         else if wasHit then
         begin
           result := lastObj;
+          mInQuery := false;
           exit;
         end;
       end;
@@ -1933,6 +1950,8 @@ begin
     ex := ax1; // why not?
     ey := ay1; // why not?
   end;
+
+  mInQuery := false;
 end;
 
 
@@ -2143,6 +2162,9 @@ begin
   //lastGA := (yptr^ div tsize)*gw+(xptr^ div tsize);
   //ccidx := mGrid[lastGA];
 
+  if mInQuery then raise Exception.Create('recursive queries aren''t supported');
+  mInQuery := true;
+
   // increase query counter
   Inc(mLastQuery);
   if (mLastQuery = 0) then
@@ -2205,11 +2227,12 @@ begin
               px.mQueryMark := lq; // mark as processed
               if assigned(cb) then
               begin
-                if cb(px.mObj, ptag) then begin result := px.mObj; exit; end;
+                if cb(px.mObj, ptag) then begin result := px.mObj; mInQuery := false; exit; end;
               end
               else
               begin
                 result := px.mObj;
+                mInQuery := false;
                 exit;
               end;
             end;
@@ -2271,6 +2294,7 @@ begin
       end;
       Dec(wklen, wkstep);
     end;
+    mInQuery := false;
     exit;
   end;
   {$ENDIF}
@@ -2323,11 +2347,12 @@ begin
             px.mQueryMark := lq; // mark as processed
             if assigned(cb) then
             begin
-              if cb(px.mObj, ptag) then begin result := px.mObj; exit; end;
+              if cb(px.mObj, ptag) then begin result := px.mObj; mInQuery := false; exit; end;
             end
             else
             begin
               result := px.mObj;
+              mInQuery := false;
               exit;
             end;
           end;
@@ -2357,6 +2382,8 @@ begin
     if (e >= 0) then begin yd += sty; e -= dx2; end else e += dy2;
     xd += stx;
   end;
+
+  mInQuery := false;
 end;
 
 
index dffeb96096c08d34d753150f155a2f86cfb2e057..672e4810e78d496f275fed809a7355b6b15e0381 100644 (file)
@@ -892,16 +892,17 @@ begin
     it := @ggItems[f];
     if not it.Live then continue;
     case it.ItemType of
-      ITEM_KEY_RED: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 32,  1.0, 0.0, 0.0, 0.6);
-      ITEM_KEY_GREEN: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 32,  0.0, 1.0, 0.0, 0.6);
-      ITEM_KEY_BLUE: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 32,  0.0, 0.0, 1.0, 0.6);
+      ITEM_KEY_RED: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 24,  1.0, 0.0, 0.0, 0.6);
+      ITEM_KEY_GREEN: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 24,  0.0, 1.0, 0.0, 0.6);
+      ITEM_KEY_BLUE: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 24,  0.0, 0.0, 1.0, 0.6);
       ITEM_ARMOR_GREEN: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 42,  0.0, 1.0, 0.0, 0.6);
       ITEM_ARMOR_BLUE: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 42,  0.0, 0.0, 1.0, 0.6);
       ITEM_SPHERE_BLUE: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 32,  0.0, 1.0, 0.0, 0.6);
       ITEM_SPHERE_WHITE: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 32,  1.0, 1.0, 1.0, 0.6);
       ITEM_INVUL: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 32,  1.0, 0.0, 0.0, 0.6);
       ITEM_INVIS: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 32,  1.0, 1.0, 0.0, 0.6);
-      ITEM_BOTTLE: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 32,  0.0, 0.0, 1.0, 0.6);
+      ITEM_BOTTLE: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 16,  0.0, 0.0, 0.8, 0.6);
+      ITEM_HELMET: g_AddDynLight(it.Obj.X+(it.Obj.Rect.Width div 2), it.Obj.Y+(it.Obj.Rect.Height div 2), 16,  0.0, 0.8, 0.0, 0.6);
     end;
   end;
 end;
index 681e182d7b1583834630e5a8fd7999ac4b65cbf9..4f86e9b0d3f14ddc3f21e097756080f4996e2e12 100644 (file)
@@ -1359,12 +1359,16 @@ begin
         SetLength(s, 64);
         CopyMemory(@s[1], @_textures[a].Resource[0], 64);
         for b := 1 to Length(s) do
+        begin
           if s[b] = #0 then
           begin
             SetLength(s, b-1);
             Break;
           end;
+        end;
+        {$IF DEFINED(D2F_DEBUG)}
         e_WriteLog(Format('    Loading texture #%d: %s', [a, s]), MSG_NOTIFY);
+        {$ENDIF}
         //if g_Map_IsSpecialTexture(s) then e_WriteLog('      SPECIAL!', MSG_NOTIFY);
       // Àíèìèðîâàííàÿ òåêñòóðà:
         if ByteBool(_textures[a].Anim) then
index e39b8c66a3dfdd7b6a2491f85087cae51e119ddb..3b1f911bf133db08b97b0c1f50da8e5a1732fed1 100644 (file)
@@ -101,7 +101,7 @@ uses
   g_player, g_map, Math, g_gfx, g_game, g_textures,
   g_console, g_monsters, g_items, g_phys, g_weapons,
   wadreader, g_main, SysUtils, e_log, g_language,
-  g_options, g_net, g_netmsg;
+  g_options, g_net, g_netmsg, utils;
 
 const
   TRIGGER_SIGNATURE = $52475254; // 'TRGR'
@@ -2196,29 +2196,34 @@ begin
   Result := find_id;
 end;
 
+
+// sorry; grid doesn't support recursive queries, so we have to do this
+type
+  TSimpleMonsterList = specialize TSimpleList<TMonster>;
+
+var
+  tgMonsList: TSimpleMonsterList = nil;
+
 procedure g_Triggers_Update();
 var
   a, b, i: Integer;
   Affected: array of Integer;
 
-  {function monsNear (mon: TMonster): Boolean;
-  begin
-    result := false; // don't stop
-    if mon.Collide(gTriggers[a].X, gTriggers[a].Y, gTriggers[a].Width, gTriggers[a].Height) then
-    begin
-      gTriggers[a].ActivateUID := mon.UID;
-      ActivateTrigger(gTriggers[a], ACTIVATE_MONSTERCOLLIDE);
-    end;
-  end;}
-
   function monsNear (mon: TMonster): Boolean;
   begin
     result := false; // don't stop
+    {
     gTriggers[a].ActivateUID := mon.UID;
     ActivateTrigger(gTriggers[a], ACTIVATE_MONSTERCOLLIDE);
+    }
+    tgMonsList.append(mon);
   end;
 
+var
+  mon: TMonster;
 begin
+  if (tgMonsList = nil) then tgMonsList := TSimpleMonsterList.Create();
+
   if gTriggers = nil then
     Exit;
   SetLength(Affected, 0);
@@ -2454,7 +2459,14 @@ begin
           begin
             //g_Mons_ForEach(monsNear);
             //Alive?!
+            tgMonsList.reset();
             g_Mons_ForEachAt(gTriggers[a].X, gTriggers[a].Y, gTriggers[a].Width, gTriggers[a].Height, monsNear);
+            for mon in tgMonsList do
+            begin
+              gTriggers[a].ActivateUID := mon.UID;
+              ActivateTrigger(gTriggers[a], ACTIVATE_MONSTERCOLLIDE);
+            end;
+            tgMonsList.reset(); // just in case
           end;
 
           // "Ìîíñòðîâ íåò"
index c182da196a11ed57a1e61716031f8b033ad76424..49408d77a7ac88ab8481e9b1e7bb5e3d8be19e8a 100644 (file)
@@ -139,9 +139,125 @@ function digitInBase (ch: AnsiChar; base: Integer): Integer;
 function quoteStr (const s: AnsiString): AnsiString;
 
 
+type
+  generic TSimpleList<ItemT> = class
+  private
+    type PItemT = ^ItemT;
+
+  public
+    type
+      TEnumerator = record
+      private
+        mItems: PItemT;
+        mCount: Integer;
+        mCurrent: Integer;
+      public
+        constructor Create (aitems: PItemT; acount: Integer);
+        function MoveNext: Boolean;
+        function getCurrent (): ItemT;
+        property Current: ItemT read getCurrent;
+      end;
+
+  private
+    mItems: array of ItemT;
+    mCount: Integer; // can be less than `mItems` size
+
+  private
+    function getAt (idx: Integer): ItemT; inline;
+
+  public
+    constructor Create ();
+    destructor Destroy (); override;
+
+    function GetEnumerator (): TEnumerator;
+
+    procedure reset (); inline; // won't resize `mItems`
+    procedure clear (); inline;
+
+    procedure append (constref it: ItemT); inline;
+
+  public
+    property count: Integer read mCount;
+    property at[idx: Integer]: ItemT read getAt; default;
+  end;
+
+
 implementation
 
 
+// ////////////////////////////////////////////////////////////////////////// //
+constructor TSimpleList.TEnumerator.Create (aitems: PItemT; acount: Integer);
+begin
+  mItems := aitems;
+  mCount := acount;
+  mCurrent := -1;
+end;
+
+function TSimpleList.TEnumerator.MoveNext: Boolean;
+begin
+  Inc(mCurrent);
+  result := (mCurrent < mCount);
+end;
+
+function TSimpleList.TEnumerator.getCurrent (): ItemT;
+begin
+  result := mItems[mCurrent];
+end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+constructor TSimpleList.Create ();
+begin
+  mItems := nil;
+  mCount := 0;
+end;
+
+
+destructor TSimpleList.Destroy ();
+begin
+  mItems := nil;
+  inherited;
+end;
+
+
+function TSimpleList.GetEnumerator (): TEnumerator;
+begin
+  if (Length(mItems) > 0) then result := TEnumerator.Create(@mItems[0], mCount)
+  else result := TEnumerator.Create(nil, -1);
+end;
+
+
+procedure TSimpleList.reset (); inline;
+begin
+  mCount := 0;
+end;
+
+
+procedure TSimpleList.clear (); inline;
+begin
+  mItems := nil;
+  mCount := 0;
+end;
+
+
+function TSimpleList.getAt (idx: Integer): ItemT; inline;
+begin
+  if (idx >= 0) and (idx < mCount) then result := mItems[idx] else result := Default(ItemT);
+end;
+
+
+procedure TSimpleList.append (constref it: ItemT); inline;
+begin
+  if (mCount = Length(mItems)) then
+  begin
+    if (mCount = 0) then SetLength(mItems, 128) else SetLength(mItems, mCount*2);
+  end;
+  mItems[mCount] := it;
+  Inc(mCount);
+end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
 var
   wc2shitmap: array[0..65535] of AnsiChar;
   wc2shitmapInited: Boolean = false;