property StartID: Integer read FStartID;
end;
-procedure g_Monsters_LoadData();
-procedure g_Monsters_FreeData();
-procedure g_Monsters_Init();
-procedure g_Monsters_Free();
-function g_Monsters_Create(MonsterType: Byte; X, Y: Integer;
- Direction: TDirection; AdjCoord: Boolean = False; ForcedUID: Integer = -1): TMonster;
-procedure g_Monsters_Update();
-procedure g_Monsters_Draw();
-procedure g_Monsters_DrawHealth();
-function g_Monsters_Get(UID: Word): TMonster;
-procedure g_Monsters_killedp();
-procedure g_Monsters_SaveState(var Mem: TBinMemoryWriter);
-procedure g_Monsters_LoadState(var Mem: TBinMemoryReader);
-function g_Monsters_GetIDByName(name: String): Integer;
-function g_Monsters_GetNameByID(MonsterType: Byte): String;
-function g_Monsters_GetKilledBy(MonsterType: Byte): String;
+
+procedure g_Monsters_LoadData ();
+procedure g_Monsters_FreeData ();
+procedure g_Monsters_Init ();
+procedure g_Monsters_Free ();
+function g_Monsters_Create (MonsterType: Byte; X, Y: Integer; Direction: TDirection;
+ AdjCoord: Boolean = False; ForcedUID: Integer = -1): TMonster;
+procedure g_Monsters_Update ();
+procedure g_Monsters_Draw ();
+procedure g_Monsters_DrawHealth ();
+function g_Monsters_ByUID (UID: Word): TMonster;
+procedure g_Monsters_killedp ();
+procedure g_Monsters_SaveState (var Mem: TBinMemoryWriter);
+procedure g_Monsters_LoadState (var Mem: TBinMemoryReader);
+function g_Monsters_GetIDByName (name: String): Integer;
+function g_Monsters_GetNameByID (MonsterType: Byte): String;
+function g_Monsters_GetKilledBy (MonsterType: Byte): String;
type
var
gMonsters: array of TMonster;
+ uidMap: array [0..65535] of TMonster; // monster knows it's index
+
+
+procedure clearUidMap ();
+var
+ idx: Integer;
+begin
+ for idx := 0 to High(uidMap) do uidMap[idx] := nil;
+end;
+
var
pt_x: Integer = 0;
UIDType := g_GetUIDType(SpawnerUID);
if UIDType = UID_MONSTER then
begin
- m := g_Monsters_Get(SpawnerUID);
+ m := g_Monsters_ByUID(SpawnerUID);
if m = nil then Exit;
MonsterType := m.FMonsterType;
end;
g_Sound_CreateWADEx('SOUND_MONSTER_FISH_ATTACK', GameWAD+':MSOUNDS\FISH_ATTACK');
monsTree := TDynAABBTreeMons.Create();
+ clearUidMap();
end;
procedure g_Monsters_FreeData();
var
a: Integer;
begin
- if gMonsters <> nil then
- for a := 0 to High(gMonsters) do
- gMonsters[a].Free();
-
+ for a := 0 to High(gMonsters) do gMonsters[a].Free();
monsTree.reset();
gMonsters := nil;
+ clearUidMap();
end;
function g_Monsters_Create(MonsterType: Byte; X, Y: Integer;
mon.arrIdx := find_id;
mon.treeNode := -1;
+ uidMap[mon.FUID] := mon;
+
// Íàñòðàèâàåì ïîëîæåíèå
with mon do
begin
var
a: Integer;
begin
-// Öåëåóêàçàòåëü:
+ // Öåëåóêàçàòåëü
if gTime mod (GAME_TICK*2) = 0 then
begin
pt_x := pt_x+pt_xs;
pt_y := pt_y+pt_ys;
- if Abs(pt_x) > 246 then
- pt_xs := -pt_xs;
- if Abs(pt_y) > 100 then
- pt_ys := -pt_ys;
+ if abs(pt_x) > 246 then pt_xs := -pt_xs;
+ if abs(pt_y) > 100 then pt_ys := -pt_ys;
end;
gMon := True; // Äëÿ ðàáîòû BlockMon'à
- if gMonsters <> nil then
- for a := 0 to High(gMonsters) do
- if (gMonsters[a] <> nil) then
- if not gMonsters[a].FRemoved then
- begin
- if g_Game_IsClient then
- gMonsters[a].ClientUpdate()
- else
- gMonsters[a].Update();
- end
- else
- begin
- gMonsters[a].Free();
- gMonsters[a] := nil;
- end;
+ for a := 0 to High(gMonsters) do
+ begin
+ if (gMonsters[a] = nil) then continue;
+ if not gMonsters[a].FRemoved then
+ begin
+ if g_Game_IsClient then
+ gMonsters[a].ClientUpdate()
+ else
+ gMonsters[a].Update();
+ end
+ else
+ begin
+ gMonsters[a].Free();
+ gMonsters[a] := nil;
+ end;
+ end;
gMon := False;
end;
end;
end;
-function g_Monsters_Get(UID: Word): TMonster;
-var
- a: Integer;
+function g_Monsters_ByUID (UID: Word): TMonster;
+//var a: Integer;
begin
+ result := uidMap[UID];
+ {
Result := nil;
-
if gMonsters <> nil then
for a := 0 to High(gMonsters) do
if (gMonsters[a] <> nil) and
Result := gMonsters[a];
Break;
end;
+ }
end;
procedure g_Monsters_SaveState(var Mem: TBinMemoryWriter);
end;
// Òåïåðü öåëü - óäàðèâøèé, åñëè òîëüêî íå ñàì ñåáÿ:
- if (SpawnerUID <> FUID) and
- (BehaviourDamage(SpawnerUID, FBehaviour, FMonsterType)) then
+ if (SpawnerUID <> FUID) and (BehaviourDamage(SpawnerUID, FBehaviour, FMonsterType)) then
begin
FTargetUID := SpawnerUID;
FTargetTime := 0;
if FHealth < FMaxHealth then
begin
IncMax(FHealth, Value, FMaxHealth);
- if g_Game_IsServer and g_Game_IsNet then
- MH_SEND_MonsterState(FUID);
+ if g_Game_IsServer and g_Game_IsNet then MH_SEND_MonsterState(FUID);
Result := True;
end;
end;
monsTree.removeObject(treeNode);
end;
+ if (arrIdx <> -1) then
+ begin
+ gMonsters[arrIdx] := nil;
+ end;
+
+ uidMap[FUID] := nil;
+
inherited Destroy();
end;
begin
FObj.Accel.X := FObj.Accel.X + vx;
FObj.Accel.Y := FObj.Accel.Y + vy;
- if g_Game_IsServer and g_Game_IsNet then
- MH_SEND_MonsterPos(FUID);
+ if g_Game_IsServer and g_Game_IsNet then MH_SEND_MonsterPos(FUID);
end;
procedure TMonster.SetState(State: Byte; ForceAnim: Byte = 255);
NET_GFX_TELE);
end;
- if g_Game_IsServer and g_Game_IsNet then
- MH_SEND_MonsterPos(FUID);
+ if g_Game_IsServer and g_Game_IsNet then MH_SEND_MonsterPos(FUID);
Result := True;
end;
begin
FFireTime := 100;
FFireAttacker := Attacker;
- if g_Game_IsNet and g_Game_IsServer then
- MH_SEND_MonsterState(FUID);
+ if g_Game_IsNet and g_Game_IsServer then MH_SEND_MonsterState(FUID);
end;
procedure TMonster.OnFireFlame(Times: DWORD = 1);
var
M: TMonster;
begin
- M := g_Monsters_Get(UID);
+ M := g_Monsters_ByUID(UID);
if M = nil then
Exit;
var
M: TMonster;
begin
- M := g_Monsters_Get(UID);
+ M := g_Monsters_ByUID(UID);
if M = nil then Exit;
NetOut.Write(Byte(NET_MSG_MPOS));
var
M: TMonster;
begin
- M := g_Monsters_Get(UID);
+ M := g_Monsters_ByUID(UID);
if M = nil then Exit;
NetOut.Write(Byte(NET_MSG_MSTATE));
var
M: TMonster;
begin
- M := g_Monsters_Get(UID);
+ M := g_Monsters_ByUID(UID);
if M = nil then Exit;
NetOut.Write(Byte(NET_MSG_MDEL));
Mon: TMonster;
begin
ID := M.ReadWord();
- Mon := g_Monsters_Get(ID);
+ Mon := g_Monsters_ByUID(ID);
if Mon <> nil then
Exit;
MDir := M.ReadByte();
g_Monsters_Create(MType, X, Y, TDirection(MDir), False, ID);
- Mon := g_Monsters_Get(ID);
+ Mon := g_Monsters_ByUID(ID);
if Mon = nil then
Exit;
ID: Word;
begin
ID := M.ReadWord();
- Mon := g_Monsters_Get(ID);
+ Mon := g_Monsters_ByUID(ID);
if Mon = nil then
Exit;
AnimRevert: Boolean;
begin
ID := M.ReadWord();
- Mon := g_Monsters_Get(ID);
+ Mon := g_Monsters_ByUID(ID);
if Mon = nil then Exit;
MState := M.ReadByte();
begin
ID := M.ReadWord();
- Mon := g_Monsters_Get(ID);
+ Mon := g_Monsters_ByUID(ID);
if Mon = nil then Exit;
X := M.ReadLongInt();
Mon: TMonster;
begin
ID := M.ReadWord();
- Mon := g_Monsters_Get(ID);
+ Mon := g_Monsters_ByUID(ID);
if Mon = nil then Exit;
Mon.SetState(5);
Mon.MonsterRemoved := True;
end;
procedure CheckTrap(ID: DWORD; dm: Integer; t: Byte);
-
var
a, b, c, d, i1, i2: Integer;
pl, mn: WArray;
+ {
function monsWaterCheck (monidx: Integer; mon: TMonster): Boolean;
begin
result := false; // don't stop
mn[i2] := monidx;
end;
end;
+ }
+
+ function monsWaterCheck (monidx: Integer; mon: TMonster): Boolean;
+ begin
+ result := false; // don't stop
+ if (not InWArray(monidx, mn)) and (i2 < 1023) then //FIXME
+ begin
+ i2 += 1;
+ mn[i2] := monidx;
+ end;
+ end;
begin
if (gWater = nil) or (WaterMap = nil) then Exit;
end;
end;
- g_Mons_ForEach(monsWaterCheck);
+ //g_Mons_ForEach(monsWaterCheck);
+ g_Mons_ForEachAtAlive(
+ gWater[WaterMap[a][c]].X, gWater[WaterMap[a][c]].Y,
+ gWater[WaterMap[a][c]].Width, gWater[WaterMap[a][c]].Height,
+ monsWaterCheck);
end;
if i1 <> -1 then
- for d := 0 to i1 do
- gPlayers[pl[d]].Damage(dm, Shots[ID].SpawnerUID, 0, 0, t);
+ begin
+ for d := 0 to i1 do gPlayers[pl[d]].Damage(dm, Shots[ID].SpawnerUID, 0, 0, t);
+ end;
if i2 <> -1 then
- for d := 0 to i2 do
- g_Mons_ByIdx(mn[d]).Damage(dm, 0, 0, Shots[ID].SpawnerUID, t);
+ begin
+ for d := 0 to i2 do g_Mons_ByIdx(mn[d]).Damage(dm, 0, 0, Shots[ID].SpawnerUID, t);
+ end;
end;
pl := nil;
tt := g_GetUIDType(SpawnerUID);
if tt = UID_MONSTER then
begin
- mon := g_Monsters_Get(SpawnerUID);
+ mon := g_Monsters_ByUID(SpawnerUID);
if mon <> nil then
- mt := g_Monsters_Get(SpawnerUID).MonsterType
+ mt := g_Monsters_ByUID(SpawnerUID).MonsterType
else
mt := 0;
end
case g_GetUIDType(UID) of
UID_PLAYER: Result := HitPlayer(g_Player_Get(UID), d, 0, 0, SpawnerUID, t);
- UID_MONSTER: Result := HitMonster(g_Monsters_Get(UID), d, 0, 0, SpawnerUID, t);
+ UID_MONSTER: Result := HitMonster(g_Monsters_ByUID(UID), d, 0, 0, SpawnerUID, t);
else Exit;
end;
end;