DEADSOFTWARE

"mon_sq_enabled" console command
[d2df-sdl.git] / src / game / g_items.pas
index 6d7cf5a10a7918ea8bc0480160d33c9769c0099e..eb122d80c4535816860eaa4710c775e7b43f7dd6 100644 (file)
@@ -25,7 +25,8 @@ Type
   PItem = ^TItem;
   TItem = record
   private
-    treeNode: Integer;
+    //treeNode: Integer;
+    slotIsUsed: Boolean;
     arrIdx: Integer; // in ggItems
 
   public
@@ -60,12 +61,12 @@ procedure g_Items_LoadState(var Mem: TBinMemoryReader);
 
 procedure g_Items_RestartRound ();
 
-function g_ItemValidId (idx: Integer): Boolean; inline;
-function g_ItemByIdx (idx: Integer): PItem;
-function g_ItemObjByIdx (idx: Integer): PObj;
+function g_Items_ValidId (idx: Integer): Boolean; inline;
+function g_Items_ByIdx (idx: Integer): PItem;
+function g_Items_ObjByIdx (idx: Integer): PObj;
 
-procedure g_Item_EmitPickupSound (idx: Integer); // at item position
-procedure g_Item_EmitPickupSoundAt (idx, x, y: Integer);
+procedure g_Items_EmitPickupSound (idx: Integer); // at item position
+procedure g_Items_EmitPickupSoundAt (idx, x, y: Integer);
 
 
 type
@@ -88,71 +89,82 @@ uses
   g_grid, z_aabbtree, binheap;
 
 
-// ////////////////////////////////////////////////////////////////////////// //
 var
-  itemTree: TDynAABBTree = nil;
   ggItems: Array of TItem = nil;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+{
+type
+  TDynAABBTreeItemBase = specialize TDynAABBTreeBase<Integer>;
+
+  TDynAABBTreeItem = class(TDynAABBTreeItemBase)
+    function getFleshAABB (out aabb: AABB2D; flesh: Integer; tag: Integer): Boolean; override;
+  end;
+
+function TDynAABBTreeItem.getFleshAABB (out aabb: AABB2D; flesh: Integer; tag: Integer): Boolean;
+var
+  it: PItem;
+begin
+  result := false;
+  if (flesh < 0) or (flesh > High(ggItems)) then raise Exception.Create('DynTree: trying to get dimensions of inexistant item');
+  it := @ggItems[flesh];
+  if (it.Obj.Rect.Width < 1) or (it.Obj.Rect.Height < 1) then exit;
+  aabb := AABB2D.Create(it.Obj.X, it.Obj.Y, it.Obj.X+it.Obj.Rect.Width-1, it.Obj.Y+it.Obj.Rect.Height-1);
+  if not aabb.valid then raise Exception.Create('wutafuuuuuuu?!');
+  result := true;
+end;
+}
+
+
+// ////////////////////////////////////////////////////////////////////////// //
+var
+  //itemTree: TDynAABBTreeItem = nil;
   freeIds: TBinaryHeapInt = nil; // free item ids
 
 
 // ////////////////////////////////////////////////////////////////////////// //
-function g_ItemValidId (idx: Integer): Boolean; inline;
+function g_Items_ValidId (idx: Integer): Boolean; inline;
 begin
   result := false;
   if (idx < 0) or (idx > High(ggItems)) then exit;
-  if (ggItems[idx].treeNode = -1) then exit;
+  //if (ggItems[idx].treeNode = -1) then exit;
+  if not ggItems[idx].slotIsUsed then exit;
   result := true;
 end;
 
 
-function g_ItemByIdx (idx: Integer): PItem;
+function g_Items_ByIdx (idx: Integer): PItem;
 begin
   if (idx < 0) or (idx > High(ggItems)) then raise Exception.Create('g_ItemObjByIdx: invalid index');
   result := @ggItems[idx];
-  if (result.treeNode = -1) then raise Exception.Create('g_ItemObjByIdx: requested inexistent item');
+  //if (result.treeNode = -1) then raise Exception.Create('g_ItemObjByIdx: requested inexistent item');
+  if not result.slotIsUsed then raise Exception.Create('g_ItemObjByIdx: requested inexistent item');
 end;
 
 
-function g_ItemObjByIdx (idx: Integer): PObj;
+function g_Items_ObjByIdx (idx: Integer): PObj;
 begin
   if (idx < 0) or (idx > High(ggItems)) then raise Exception.Create('g_ItemObjByIdx: invalid index');
-  if (ggItems[idx].treeNode = -1) then raise Exception.Create('g_ItemObjByIdx: requested inexistent item');
+  //if (ggItems[idx].treeNode = -1) then raise Exception.Create('g_ItemObjByIdx: requested inexistent item');
+  if not ggItems[idx].slotIsUsed then raise Exception.Create('g_ItemObjByIdx: requested inexistent item');
   result := @ggItems[idx].Obj;
 end;
 
 
-// ////////////////////////////////////////////////////////////////////////// //
-type
-  TDynAABBTreeItem = class(TDynAABBTree)
-    function getFleshAABB (var aabb: AABB2D; flesh: TTreeFlesh; tag: Integer): Boolean; override;
-  end;
-
-function TDynAABBTreeItem.getFleshAABB (var aabb: AABB2D; flesh: TTreeFlesh; tag: Integer): Boolean;
-var
-  it: PItem;
-begin
-  result := false;
-  if (flesh = nil) then begin aabb := AABB2D.Create(0, 0, 0, 0); exit; end;
-  //if not g_ItemValidId(tag) then raise Exception.Create('DynTree: trying to get dimensions of inexistant item');
-  if (tag < 0) or (tag > High(ggItems)) then raise Exception.Create('DynTree: trying to get dimensions of inexistant item');
-  it := @ggItems[tag];
-  if (it.Obj.Rect.Width < 1) or (it.Obj.Rect.Height < 1) then exit;
-  aabb := AABB2D.Create(it.Obj.X, it.Obj.Y, it.Obj.X+it.Obj.Rect.Width, it.Obj.Y+it.Obj.Rect.Height);
-  if not aabb.valid then raise Exception.Create('wutafuuuuuuu?!');
-  result := true;
-end;
-
-
 // ////////////////////////////////////////////////////////////////////////// //
 procedure TItem.positionChanged ();
-var
-  x, y: Integer;
+//var
+//  x, y: Integer;
 begin
+  (*
   if (treeNode = -1) then
   begin
-    treeNode := itemTree.insertObject(itemTree{doesn't matter}, arrIdx, true); // static object
+    treeNode := itemTree.insertObject(arrIdx, 0, true); // static object
+    {$IF DEFINED(D2F_DEBUG)}
     itemTree.getNodeXY(treeNode, x, y);
-    {$IF DEFINED(D2F_DEBUG)}e_WriteLog(Format('item #%d: inserted into the tree; nodeid=%d; x=%d; y=%d', [arrIdx, treeNode, x, y]), MSG_NOTIFY);{$ENDIF}
+    e_WriteLog(Format('item #%d: inserted into the tree; nodeid=%d; x=%d; y=%d', [arrIdx, treeNode, x, y]), MSG_NOTIFY);
+    {$ENDIF}
   end
   else
   begin
@@ -164,12 +176,15 @@ begin
     itemTree.updateObject(treeNode);
     {$ELSE}
     itemTree.removeObject(treeNode);
-    treeNode := itemTree.insertObject(itemTree{doesn't matter}, arrIdx, true); // static object
+    treeNode := itemTree.insertObject(arrIdx, 0, true); // static object
     {$ENDIF}
 
+    {$IF DEFINED(D2F_DEBUG)}
     itemTree.getNodeXY(treeNode, x, y);
-    {$IF DEFINED(D2F_DEBUG)}e_WriteLog(Format('item #%d: updated tree; nodeid=%d; x=%d; y=%d', [arrIdx, treeNode, x, y]), MSG_NOTIFY);{$ENDIF}
+    e_WriteLog(Format('item #%d: updated tree; nodeid=%d; x=%d; y=%d', [arrIdx, treeNode, x, y]), MSG_NOTIFY);
+    {$ENDIF}
   end;
+  *)
 end;
 
 
@@ -306,7 +321,7 @@ begin
 
   InitTextures();
 
-  itemTree := TDynAABBTreeItem.Create();
+  //itemTree := TDynAABBTreeItem.Create();
   freeIds := binHeapNewIntLess();
 end;
 
@@ -364,7 +379,7 @@ begin
   g_Texture_Delete('ITEM_MEDKIT_BLACK');
   g_Texture_Delete('ITEM_JETPACK');
 
-  itemTree.Free();
+  //itemTree.Free();
   freeIds.Free();
 end;
 
@@ -375,10 +390,12 @@ var
 begin
   if (idx < 0) or (idx > High(ggItems)) then raise Exception.Create('releaseItem: invalid item id');
   it := @ggItems[idx];
-  if (it.treeNode = -1) then raise Exception.Create('releaseItem: trying to release unallocated item');
+  //if (it.treeNode = -1) then raise Exception.Create('releaseItem: trying to release unallocated item');
+  if not it.slotIsUsed then raise Exception.Create('releaseItem: trying to release unallocated item');
   if (it.arrIdx <> idx) then raise Exception.Create('releaseItem: arrIdx inconsistency');
-  itemTree.removeObject(it.treeNode);
-  it.treeNode := -1;
+  //itemTree.removeObject(it.treeNode);
+  //it.treeNode := -1;
+  it.slotIsUsed := false;
   if (it.Animation <> nil) then
   begin
     it.Animation.Free();
@@ -404,7 +421,8 @@ begin
     for i := olen to High(ggItems) do
     begin
       it := @ggItems[i];
-      it.treeNode := -1;
+      //it.treeNode := -1;
+      it.slotIsUsed := false;
       it.arrIdx := i;
       it.ItemType := ITEM_NONE;
       it.Animation := nil;
@@ -441,7 +459,8 @@ begin
     for i := olen to High(ggItems) do
     begin
       it := @ggItems[i];
-      it.treeNode := -1;
+      //it.treeNode := -1;
+      it.slotIsUsed := false;
       it.arrIdx := i;
       it.ItemType := ITEM_NONE;
       it.Animation := nil;
@@ -454,7 +473,7 @@ begin
   end;
 
   it := @ggItems[slot];
-  if (it.treeNode = -1) then
+  if {(it.treeNode = -1)} not it.slotIsUsed then
   begin
     // this is unused slot; get it, and rebuild id list
     if rebuildFreeList then
@@ -462,15 +481,16 @@ begin
       freeIds.clear();
       for i := 0 to High(ggItems) do
       begin
-        if (i <> slot) and (ggItems[i].treeNode = -1) then freeIds.insert(i);
+        if (i <> slot) and {(ggItems[i].treeNode = -1)} (not it.slotIsUsed) then freeIds.insert(i);
       end;
     end;
   end
   else
   begin
     // it will be readded
-    itemTree.removeObject(it.treeNode);
-    it.treeNode := -1;
+    //itemTree.removeObject(it.treeNode);
+    //it.treeNode := -1;
+    it.slotIsUsed := false;
   end;
 
   result := slot;
@@ -497,7 +517,7 @@ begin
     for i := 0 to High(ggItems) do ggItems[i].Animation.Free();
     ggItems := nil;
   end;
-  if (itemTree <> nil) then itemTree.reset();
+  //if (itemTree <> nil) then itemTree.reset();
   freeIds.clear();
 end;
 
@@ -515,6 +535,12 @@ begin
 
   it := @ggItems[find_id];
 
+  //if (it.treeNode <> -1) then raise Exception.Create('g_Items_Create: trying to reuse already allocated item');
+  if (it.arrIdx <> find_id) then raise Exception.Create('g_Items_Create: arrIdx inconsistency');
+  //it.treeNode := -1;
+  //it.arrIdx := find_id;
+  it.slotIsUsed := true;
+
   it.ItemType := ItemType;
   it.Respawnable := Respawnable;
   if g_Game_IsServer and (ITEM_RESPAWNTIME = 0) then it.Respawnable := False;
@@ -525,11 +551,6 @@ begin
   it.Live := True;
   it.QuietRespawn := False;
 
-  if (it.treeNode <> -1) then raise Exception.Create('g_Items_Create: trying to reuse already allocated item');
-  if (it.arrIdx <> find_id) then raise Exception.Create('g_Items_Create: arrIdx inconsistency');
-  //it.treeNode := -1;
-  //it.arrIdx := find_id;
-
   g_Obj_Init(@it.Obj);
   it.Obj.X := X;
   it.Obj.Y := Y;
@@ -637,7 +658,7 @@ begin
                 +2. I_MEGA,I_INVL,I_SUPER
                 3. I_STIM,I_MEDI,I_ARM1,I_ARM2,I_AQUA,I_KEYR,I_KEYG,I_KEYB,I_SUIT,I_RTORCH,I_GTORCH,I_BTORCH,I_GOR1,I_FCAN
               }
-              g_Item_EmitPickupSoundAt(i, gPlayers[j].Obj.X, gPlayers[j].Obj.Y);
+              g_Items_EmitPickupSoundAt(i, gPlayers[j].Obj.X, gPlayers[j].Obj.Y);
 
               // Íàäî óáðàòü ñ êàðòû, åñëè ýòî íå êëþ÷, êîòîðûì íóæíî ïîäåëèòüñÿ ñ äðóãèì èãðîêîì
               if r then
@@ -737,15 +758,19 @@ procedure g_Items_Remove (ID: DWORD);
 var
   it: PItem;
   trig: Integer;
-  x, y: Integer;
+{$IF DEFINED(D2F_DEBUG)}
+  //x, y: Integer;
+{$ENDIF}
 begin
-  if not g_ItemValidId(ID) then raise Exception.Create('g_Items_Remove: invalid item id');
+  if not g_Items_ValidId(ID) then raise Exception.Create('g_Items_Remove: invalid item id');
 
   it := @ggItems[ID];
   if (it.arrIdx <> ID) then raise Exception.Create('g_Items_Remove: arrIdx desync');
 
-  itemTree.getNodeXY(it.treeNode, x, y);
-  {$IF DEFINED(D2F_DEBUG)}e_WriteLog(Format('removing item #%d: updating tree; nodeid=%d; x=%d; y=%d (%d,%d)', [it.arrIdx, it.treeNode, x, y, it.Obj.X, it.Obj.Y]), MSG_NOTIFY);{$ENDIF}
+  {$IF DEFINED(D2F_DEBUG)}
+  //itemTree.getNodeXY(it.treeNode, x, y);
+  //e_WriteLog(Format('removing item #%d: updating tree; nodeid=%d; x=%d; y=%d (%d,%d)', [it.arrIdx, it.treeNode, x, y, it.Obj.X, it.Obj.Y]), MSG_NOTIFY);
+  {$ENDIF}
 
   trig := it.SpawnTrigger;
 
@@ -901,20 +926,20 @@ end;
 
 
 // ////////////////////////////////////////////////////////////////////////// //
-procedure g_Item_EmitPickupSound (idx: Integer);
+procedure g_Items_EmitPickupSound (idx: Integer);
 var
   it: PItem;
 begin
-  if not g_ItemValidId(idx) then exit;
+  if not g_Items_ValidId(idx) then exit;
   it := @ggItems[idx];
-  g_Item_EmitPickupSoundAt(idx, it.Obj.X, it.Obj.Y);
+  g_Items_EmitPickupSoundAt(idx, it.Obj.X, it.Obj.Y);
 end;
 
-procedure g_Item_EmitPickupSoundAt (idx, x, y: Integer);
+procedure g_Items_EmitPickupSoundAt (idx, x, y: Integer);
 var
   it: PItem;
 begin
-  if not g_ItemValidId(idx) then exit;
+  if not g_Items_ValidId(idx) then exit;
 
   it := @ggItems[idx];
   if gSoundEffectsDF then