diff --git a/src/game/g_items.pas b/src/game/g_items.pas
index 27dbc75bf19abf1ced60905a43afd6212a3ac526..5ec5ddb77998633d60adbd4ebd7ee1f9f007bc5a 100644 (file)
--- a/src/game/g_items.pas
+++ b/src/game/g_items.pas
var
gItemsTexturesID: Array [1..ITEM_MAX] of DWORD;
- gMaxDist: Integer = 1;
+ gMaxDist: Integer = 1; // for sounds
ITEM_RESPAWNTIME: Integer = 60 * 36;
implementation
g_basic, e_graphics, g_sound, g_main, g_gfx, g_map,
Math, g_game, g_triggers, g_console, SysUtils, g_player, g_net, g_netmsg,
e_log,
- g_grid, binheap;
+ g_grid, binheap, idpool;
var
// ////////////////////////////////////////////////////////////////////////// //
var
- freeIds: TBinaryHeapInt = nil; // free item ids
+ freeIds: TIdPool = nil;
// ////////////////////////////////////////////////////////////////////////// //
InitTextures();
- freeIds := binHeapNewIntLess();
+ freeIds := TIdPool.Create();
end;
g_Texture_Delete('ITEM_JETPACK');
freeIds.Free();
+ freeIds := nil;
end;
it: PItem;
begin
if (idx < 0) or (idx > High(ggItems)) then raise Exception.Create('releaseItem: invalid item id');
+ if not freeIds.hasAlloced[LongWord(idx)] then raise Exception.Create('releaseItem: trying to release unallocated item (0)');
it := @ggItems[idx];
- if not it.slotIsUsed then raise Exception.Create('releaseItem: trying to release unallocated item');
+ if not it.slotIsUsed then raise Exception.Create('releaseItem: trying to release unallocated item (1)');
if (it.arrIdx <> idx) then raise Exception.Create('releaseItem: arrIdx inconsistency');
it.slotIsUsed := false;
if (it.Animation <> nil) then
it.Live := False;
it.SpawnTrigger := -1;
it.ItemType := ITEM_NONE;
- freeIds.insert(it.arrIdx);
+ freeIds.release(LongWord(idx));
end;
-function allocItem (): DWORD;
+procedure growItemArrayTo (newsz: Integer);
var
i, olen: Integer;
it: PItem;
begin
- if (freeIds.count = 0) then
+ if (newsz < Length(ggItems)) then exit;
+ // no free slots
+ olen := Length(ggItems);
+ SetLength(ggItems, newsz);
+ for i := olen to High(ggItems) do
begin
- // no free slots
- olen := Length(ggItems);
- SetLength(ggItems, olen+64);
- for i := olen to High(ggItems) do
- begin
- it := @ggItems[i];
- it.slotIsUsed := false;
- it.arrIdx := i;
- it.ItemType := ITEM_NONE;
- it.Animation := nil;
- it.Live := false;
- it.SpawnTrigger := -1;
- it.Respawnable := false;
- freeIds.insert(i);
- end;
+ it := @ggItems[i];
+ it.slotIsUsed := false;
+ it.arrIdx := i;
+ it.ItemType := ITEM_NONE;
+ it.Animation := nil;
+ it.Live := false;
+ it.SpawnTrigger := -1;
+ it.Respawnable := false;
+ //if not freeIds.hasFree[LongWord(i)] then raise Exception.Create('internal error in item idx manager');
end;
+end;
- result := freeIds.front;
- freeIds.popFront();
+function allocItem (): DWORD;
+begin
+ result := freeIds.alloc();
+ if (result >= Length(ggItems)) then growItemArrayTo(Integer(result)+64);
if (Integer(result) > High(ggItems)) then raise Exception.Create('allocItem: freeid list corrupted');
if (ggItems[result].arrIdx <> Integer(result)) then raise Exception.Create('allocItem: arrIdx inconsistency');
end;
// it will be slow if the slot is free (we have to rebuild the heap)
function wantItemSlot (slot: Integer): Integer;
var
- i, olen: Integer;
+ olen: Integer;
it: PItem;
- rebuildFreeList: Boolean = true;
begin
if (slot < 0) or (slot > $0fffffff) then raise Exception.Create('wantItemSlot: bad item slot request');
// do we need to grow item storate?
olen := Length(ggItems);
- if (slot >= olen) then
- begin
- // need more spice!
- SetLength(ggItems, slot+64);
- // add free slots to free list
- for i := olen to High(ggItems) do
- begin
- it := @ggItems[i];
- it.slotIsUsed := false;
- it.arrIdx := i;
- it.ItemType := ITEM_NONE;
- it.Animation := nil;
- it.Live := false;
- it.SpawnTrigger := -1;
- it.Respawnable := false;
- if (i <> slot) then freeIds.insert(i);
- end;
- rebuildFreeList := false;
- end;
+ if (slot >= olen) then growItemArrayTo(slot+64);
it := @ggItems[slot];
if not it.slotIsUsed then
begin
- // this is unused slot; get it, and rebuild id list
- if rebuildFreeList then
- begin
- freeIds.clear();
- for i := 0 to High(ggItems) do
- begin
- if (i <> slot) and (not it.slotIsUsed) then freeIds.insert(i);
- end;
- end;
+ freeIds.alloc(LongWord(slot));
end
else
begin
- // it will be readded
- it.slotIsUsed := false;
+ if not freeIds.hasAlloced[slot] then raise Exception.Create('wantItemSlot: internal error in item idx manager');
end;
+ it.slotIsUsed := false;
result := slot;
end;
begin
if ForcedID < 0 then find_id := allocItem() else find_id := wantItemSlot(ForcedID);
- {$IF DEFINED(D2F_DEBUG)}e_WriteLog(Format('allocated item #%d', [Integer(find_id)]), MSG_NOTIFY);{$ENDIF}
+ //{$IF DEFINED(D2F_DEBUG)}e_WriteLog(Format('allocated item #%d', [Integer(find_id)]), MSG_NOTIFY);{$ENDIF}
it := @ggItems[find_id];