summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 2f523be)
raw | patch | inline | side by side (parent: 2f523be)
author | Ketmar Dark <ketmar@ketmar.no-ip.org> | |
Sun, 20 Aug 2017 00:21:14 +0000 (03:21 +0300) | ||
committer | Ketmar Dark <ketmar@ketmar.no-ip.org> | |
Sun, 20 Aug 2017 00:22:21 +0000 (03:22 +0300) |
diff --git a/src/game/g_basic.pas b/src/game/g_basic.pas
index 8430c9f98eecc88eba2aceba3096c4078e3f1704..e001f8567a3af1ad810da064330ec9cb595d0183 100644 (file)
--- a/src/game/g_basic.pas
+++ b/src/game/g_basic.pas
end;
function g_CollideMonster(X, Y: Integer; Width, Height: Word): Boolean;
-var
- a: Integer;
begin
- Result := False;
-
- if gMonsters = nil then Exit;
-
- for a := 0 to High(gMonsters) do
- if (gMonsters[a] <> nil) and gMonsters[a].Live then
- if g_Obj_Collide(X, Y, Width, Height, @gMonsters[a].Obj) then
- begin
- Result := True;
- Exit;
- end;
+ result := g_Mons_AnyAt(X, Y, Width, Height);
end;
function g_TraceVector(X1, Y1, X2, Y2: Integer): Boolean;
UID_MONSTER:
begin
- repeat
- Result := UID_MAX_PLAYER+$1+Random(UID_MAX_MONSTER-UID_MAX_GAME-UID_MAX_PLAYER+$1);
-
- ok := True;
- if gMonsters <> nil then
- for i := 0 to High(gMonsters) do
- if gMonsters[i] <> nil then
- if Result = gMonsters[i].UID then
- begin
- ok := False;
- Break;
- end;
- until ok;
+ //FIXME!!!
+ while true do
+ begin
+ result := UID_MAX_PLAYER+$1+Random(UID_MAX_MONSTER-UID_MAX_GAME-UID_MAX_PLAYER+$1);
+ if (g_Monsters_Get(result) = nil) then break;
+ end;
end;
end;
end;
diff --git a/src/game/g_game.pas b/src/game/g_game.pas
index 497567b23ccf7e36e3e8e5f011c411211d65502c..2a52eccfb90dd8b19c144ee23530224f9684315a 100644 (file)
--- a/src/game/g_game.pas
+++ b/src/game/g_game.pas
a: Byte;
w: Word;
i, b: Integer;
+
+ function sendMonsPos (monidx: Integer; mon: TMonster): Boolean;
+ begin
+ result := false; // don't stop
+ if (mon.MonsterType = MONSTER_BARREL) then
+ begin
+ if (mon.GameVelX <> 0) or (mon.GameVelY <> 0) then MH_SEND_MonsterPos(mon.UID);
+ end
+ else
+ if (mon.MonsterState <> MONSTATE_SLEEP) then
+ begin
+ if (mon.MonsterState <> MONSTATE_DEAD) or (mon.GameVelX <> 0) or (mon.GameVelY <> 0) then
+ begin
+ MH_SEND_MonsterPos(mon.UID);
+ end;
+ end;
+ end;
+
begin
g_ResetDynlights();
// Ïîðà âûêëþ÷àòü èãðó:
if gPlayers[I] <> nil then
MH_SEND_PlayerPos(True, gPlayers[I].UID);
- if gMonsters <> nil then
- for I := 0 to High(gMonsters) do
- if gMonsters[I] <> nil then
- begin
- if (gMonsters[I].MonsterType = MONSTER_BARREL) then
- begin
- if (gMonsters[I].GameVelX <> 0) or (gMonsters[I].GameVelY <> 0) then
- MH_SEND_MonsterPos(gMonsters[I].UID);
- end
- else
- if (gMonsters[I].MonsterState <> MONSTATE_SLEEP) then
- if (gMonsters[I].MonsterState <> MONSTATE_DEAD) or
- (gMonsters[I].GameVelX <> 0) or
- (gMonsters[I].GameVelY <> 0) then
- MH_SEND_MonsterPos(gMonsters[I].UID);
- end;
+ g_Mons_ForEach(sendMonsPos);
NetTimeToReliable := 0;
NetTimeToUpdate := NetUpdateRate;
if gPlayers[I] <> nil then
MH_SEND_PlayerPos(False, gPlayers[I].UID);
- if gMonsters <> nil then
- for I := 0 to High(gMonsters) do
- if gMonsters[I] <> nil then
- begin
- if (gMonsters[I].MonsterType = MONSTER_BARREL) then
- begin
- if (gMonsters[I].GameVelX <> 0) or (gMonsters[I].GameVelY <> 0) then
- MH_SEND_MonsterPos(gMonsters[I].UID);
- end
- else
- if (gMonsters[I].MonsterState <> MONSTATE_SLEEP) then
- if (gMonsters[I].MonsterState <> MONSTATE_DEAD) or
- (gMonsters[I].GameVelX <> 0) or
- (gMonsters[I].GameVelY <> 0) then
- MH_SEND_MonsterPos(gMonsters[I].UID);
- end;
+ g_Mons_ForEach(sendMonsPos);
NetTimeToUpdate := 0;
end;
procedure DrawMinimap(p: TPlayer; RenderRect: e_graphics.TRect);
var
a, aX, aY, aX2, aY2, Scale, ScaleSz: Integer;
+
+ function monDraw (monidx: Integer; mon: TMonster): Boolean;
+ begin
+ result := false; // don't stop
+ with mon do
+ begin
+ if Live then
+ begin
+ // Ëåâûé âåðõíèé óãîë
+ aX := Obj.X div ScaleSz + 1;
+ aY := Obj.Y div ScaleSz + 1;
+ // Ðàçìåðû
+ aX2 := max(Obj.Rect.Width div ScaleSz, 1);
+ aY2 := max(Obj.Rect.Height div ScaleSz, 1);
+ // Ïðàâûé íèæíèé óãîë
+ aX2 := aX + aX2 - 1;
+ aY2 := aY + aY2 - 1;
+ e_DrawFillQuad(aX, aY, aX2, aY2, 255, 255, 0, 0);
+ end;
+ end;
+ end;
+
begin
if (gMapInfo.Width > RenderRect.Right - RenderRect.Left) or
(gMapInfo.Height > RenderRect.Bottom - RenderRect.Top) then
end;
end;
end;
- if gMonsters <> nil then
- begin
- // Ðèñóåì ìîíñòðîâ:
- for a := 0 to High(gMonsters) do
- if gMonsters[a] <> nil then with gMonsters[a] do
- if Live then begin
- // Ëåâûé âåðõíèé óãîë:
- aX := Obj.X div ScaleSz + 1;
- aY := Obj.Y div ScaleSz + 1;
- // Ðàçìåðû:
- aX2 := max(Obj.Rect.Width div ScaleSz, 1);
- aY2 := max(Obj.Rect.Height div ScaleSz, 1);
- // Ïðàâûé íèæíèé óãîë:
- aX2 := aX + aX2 - 1;
- aY2 := aY + aY2 - 1;
-
- e_DrawFillQuad(aX, aY, aX2, aY2, 255, 255, 0, 0);
- end;
- end;
+ // Ðèñóåì ìîíñòðîâ
+ g_Mons_ForEach(monDraw);
end;
end;
procedure g_Game_RestartRound(NoMapRestart: Boolean = False);
var
i, n, nb, nr: Integer;
+
+ function monRespawn (monidx: Integer; mon: TMonster): Boolean;
+ begin
+ result := false; // don't stop
+ if not mon.FNoRespawn then mon.Respawn();
+ end;
+
begin
if not g_Game_IsServer then Exit;
if gLMSRespawn = LMS_RESPAWN_NONE then Exit;
g_Items_RestartRound();
- for i := Low(gMonsters) to High(gMonsters) do
- begin
- if (gMonsters[i] <> nil) and not gMonsters[i].FNoRespawn then
- gMonsters[i].Respawn;
- end;
+
+ g_Mons_ForEach(monRespawn);
gLMSSoftSpawn := False;
end;
a, b: Integer;
cmd: string;
//pt: TPoint;
+ mon: TMonster;
begin
// Êîìàíäû îòëàäî÷íîãî ðåæèìà:
if gDebugMode then
else
begin
with gPlayer1.Obj do
- b := g_Monsters_Create(a,
+ begin
+ mon := g_Monsters_Create(a,
X + Rect.X + (Rect.Width div 2),
Y + Rect.Y + Rect.Height,
gPlayer1.Direction, True);
- if (Length(P) > 2) and (b >= 0) then
- gMonsters[b].MonsterBehaviour := Min(Max(StrToIntDef(P[2], BH_NORMAL), BH_NORMAL), BH_GOOD);
+ end;
+ if (Length(P) > 2) and (mon <> nil) then
+ mon.MonsterBehaviour := Min(Max(StrToIntDef(P[2], BH_NORMAL), BH_NORMAL), BH_GOOD);
end;
end;
end
diff --git a/src/game/g_map.pas b/src/game/g_map.pas
index 0543abe30aa620cb0506c08d8e2c480dc06a0356..b79c972159203bd65018e370b88a54088893508e 100644 (file)
--- a/src/game/g_map.pas
+++ b/src/game/g_map.pas
procedure CreateMonster(monster: TMonsterRec_1);
var
- a, i: Integer;
+ a: Integer;
+ mon: TMonster;
begin
if g_Game_IsClient then Exit;
if (gGameSettings.GameType = GT_SINGLE)
or LongBool(gGameSettings.Options and GAME_OPTION_MONSTERS) then
begin
- i := g_Monsters_Create(monster.MonsterType, monster.X, monster.Y,
- TDirection(monster.Direction));
+ mon := g_Monsters_Create(monster.MonsterType, monster.X, monster.Y, TDirection(monster.Direction));
if gTriggers <> nil then
+ begin
for a := 0 to High(gTriggers) do
- if gTriggers[a].TriggerType in [TRIGGER_PRESS,
- TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF] then
- if (gTriggers[a].Data.MonsterID-1) = gMonsters[i].StartID then
- gMonsters[i].AddTrigger(a);
+ begin
+ if gTriggers[a].TriggerType in [TRIGGER_PRESS, TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF] then
+ begin
+ if (gTriggers[a].Data.MonsterID-1) = mon.StartID then mon.AddTrigger(a);
+ end;
+ end;
+ end;
- if monster.MonsterType <> MONSTER_BARREL then
- Inc(gTotalMonsters);
+ if monster.MonsterType <> MONSTER_BARREL then Inc(gTotalMonsters);
end;
end;
procedure g_Map_ReAdd_DieTriggers();
-var
- i, a: Integer;
-begin
- if g_Game_IsClient then Exit;
- for i := 0 to High(gMonsters) do
- if gMonsters[i] <> nil then
+ function monsDieTrig (monidx: Integer; mon: TMonster): Boolean;
+ var
+ a: Integer;
+ begin
+ result := false; // don't stop
+ mon.ClearTriggers();
+ for a := 0 to High(gTriggers) do
+ begin
+ if gTriggers[a].TriggerType in [TRIGGER_PRESS, TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF] then
begin
- gMonsters[i].ClearTriggers();
-
- for a := 0 to High(gTriggers) do
- if gTriggers[a].TriggerType in [TRIGGER_PRESS,
- TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF] then
- if (gTriggers[a].Data.MonsterID-1) = gMonsters[i].StartID then
- gMonsters[i].AddTrigger(a);
+ if (gTriggers[a].Data.MonsterID-1) = mon.StartID then mon.AddTrigger(a);
end;
+ end;
+ end;
+
+begin
+ if g_Game_IsClient then Exit;
+
+ g_Mons_ForEach(monsDieTrig);
end;
function extractWadName(resourceName: string): string;
index 690626078d17713d17936ec942a69007ca21ae1d..af98abae75f8936317a489592ebc0656dbb6e000 100644 (file)
--- a/src/game/g_monsters.pas
+++ b/src/game/g_monsters.pas
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): Integer;
+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_GetNameByID(MonsterType: Byte): String;
function g_Monsters_GetKilledBy(MonsterType: Byte): String;
-var
- gMonsters: array of TMonster;
+
+type
+ TEachMonsterCB = function (monidx: Integer; mon: TMonster): Boolean is nested; // return `true` to stop
+
+function g_Mons_ForEach (cb: TEachMonsterCB): Boolean;
+
+// throws on invalid uid
+function g_Mons_ByIdx (uid: Integer): TMonster; inline;
+
+// can return null
+function g_Mons_ByIdx_NC (uid: Integer): TMonster; inline;
+
+function g_Mons_AnyAt (x, y: Integer; width, height: Integer): Boolean;
+
implementation
MAX_ATM = 89; // Âðåìÿ îæèäàíèÿ ïîñëå ïîòåðè öåëè
MAX_SOUL = 512; // Îãðàíè÷åíèå Lost_Soul'îâ
+var
+ gMonsters: array of TMonster;
+
var
pt_x: Integer = 0;
pt_xs: Integer = 1;
end;
function g_Monsters_Create(MonsterType: Byte; X, Y: Integer;
- Direction: TDirection; AdjCoord: Boolean = False; ForcedUID: Integer = -1): Integer;
+ Direction: TDirection; AdjCoord: Boolean = False; ForcedUID: Integer = -1): TMonster;
var
find_id: DWORD;
begin
- Result := -1;
+ result := nil;
-// Íåò òàêîãî ìîíñòðà:
- if (MonsterType > MONSTER_MAN) or (MonsterType = 0) then
- Exit;
+ // Íåò òàêîãî ìîíñòðà
+ if (MonsterType > MONSTER_MAN) or (MonsterType = 0) then exit;
-// Ñîáëþäàåì îãðàíè÷åíèå Lost_Soul'îâ:
+ // Ñîáëþäàåì îãðàíè÷åíèå Lost_Soul'îâ
if MonsterType = MONSTER_SOUL then
- if soulcount > MAX_SOUL then
- Exit
- else
- soulcount := soulcount + 1;
+ begin
+ if soulcount > MAX_SOUL then exit;
+ soulcount := soulcount + 1;
+ end;
find_id := FindMonster();
gMonsters[find_id] := TMonster.Create(MonsterType, find_id, ForcedUID);
-// Íàñòðàèâàåì ïîëîæåíèå:
+ // Íàñòðàèâàåì ïîëîæåíèå
with gMonsters[find_id] do
begin
if AdjCoord then
- begin
- FObj.X := X-FObj.Rect.X - (FObj.Rect.Width div 2);
- FObj.Y := Y-FObj.Rect.Y - FObj.Rect.Height;
- end
+ begin
+ FObj.X := X-FObj.Rect.X - (FObj.Rect.Width div 2);
+ FObj.Y := Y-FObj.Rect.Y - FObj.Rect.Height;
+ end
else
- begin
- FObj.X := X-FObj.Rect.X;
- FObj.Y := Y-FObj.Rect.Y;
- end;
+ begin
+ FObj.X := X-FObj.Rect.X;
+ FObj.Y := Y-FObj.Rect.Y;
+ end;
FDirection := Direction;
FStartDirection := Direction;
FStartY := GameY;
end;
- Result := find_id;
+ result := {find_id}gMonsters[find_id];
end;
procedure g_Monsters_killedp();
procedure g_Monsters_LoadState(var Mem: TBinMemoryReader);
var
- count, i, a: Integer;
+ count, a: Integer;
b: Byte;
+ mon: TMonster;
begin
- if Mem = nil then
- Exit;
+ if Mem = nil then exit;
g_Monsters_Free();
-// Çàãðóæàåì èíôîðìàöèþ öåëåóêàçàòåëÿ:
+ // Çàãðóæàåì èíôîðìàöèþ öåëåóêàçàòåëÿ
Mem.ReadInt(pt_x);
Mem.ReadInt(pt_xs);
Mem.ReadInt(pt_y);
Mem.ReadInt(pt_ys);
-// Êîëè÷åñòâî ìîíñòðîâ:
+ // Êîëè÷åñòâî ìîíñòðîâ
Mem.ReadInt(count);
- if count = 0 then
- Exit;
+ if count = 0 then exit;
-// Çàãðóæàåì ìîíñòðîâ:
+ // Çàãðóæàåì ìîíñòðîâ
for a := 0 to count-1 do
begin
- // Òèï ìîíñòðà:
+ // Òèï ìîíñòðà
Mem.ReadByte(b);
- // Ñîçäàåì ìîíñòðà:
- i := g_Monsters_Create(b, 0, 0, D_LEFT);
- if i < 0 then
- begin
- raise EBinSizeError.Create('g_Monsters_LoadState: ID = -1 (Can''t create)');
- end;
- // Çàãðóæàåì äàííûå ìîíñòðà:
- gMonsters[i].LoadState(Mem);
+ // Ñîçäàåì ìîíñòðà
+ mon := g_Monsters_Create(b, 0, 0, D_LEFT);
+ if mon = nil then raise EBinSizeError.Create('g_Monsters_LoadState: ID = -1 (Can''t create)');
+ // Çàãðóæàåì äàííûå ìîíñòðà
+ mon.LoadState(Mem);
end;
end;
st: Word;
o, co: TObj;
fall: Boolean;
+ mon: TMonster;
label
_end;
begin
// Pain_Elemental ïðè ñìåðòè âûïóñêàåò 3 Lost_Soul'à:
if (FMonsterType = MONSTER_PAIN) then
begin
- sx := g_Monsters_Create(MONSTER_SOUL, FObj.X+FObj.Rect.X+(FObj.Rect.Width div 2)-30,
- FObj.Y+FObj.Rect.Y+20, D_LEFT);
- if sx <> -1 then
+ mon := g_Monsters_Create(MONSTER_SOUL, FObj.X+FObj.Rect.X+(FObj.Rect.Width div 2)-30,
+ FObj.Y+FObj.Rect.Y+20, D_LEFT);
+ if mon <> nil then
begin
- gMonsters[sx].SetState(STATE_GO);
- gMonsters[sx].FNoRespawn := True;
+ mon.SetState(STATE_GO);
+ mon.FNoRespawn := True;
Inc(gTotalMonsters);
if g_Game_IsNet then MH_SEND_MonsterSpawn(gMonsters[sx].UID);
end;
- sx := g_Monsters_Create(MONSTER_SOUL, FObj.X+FObj.Rect.X+(FObj.Rect.Width div 2),
- FObj.Y+FObj.Rect.Y+20, D_RIGHT);
- if sx <> -1 then
+ mon := g_Monsters_Create(MONSTER_SOUL, FObj.X+FObj.Rect.X+(FObj.Rect.Width div 2),
+ FObj.Y+FObj.Rect.Y+20, D_RIGHT);
+ if mon <> nil then
begin
- gMonsters[sx].SetState(STATE_GO);
- gMonsters[sx].FNoRespawn := True;
+ mon.SetState(STATE_GO);
+ mon.FNoRespawn := True;
Inc(gTotalMonsters);
if g_Game_IsNet then MH_SEND_MonsterSpawn(gMonsters[sx].UID);
end;
- sx := g_Monsters_Create(MONSTER_SOUL, FObj.X+FObj.Rect.X+(FObj.Rect.Width div 2)-15,
- FObj.Y+FObj.Rect.Y, D_RIGHT);
- if sx <> -1 then
+ mon := g_Monsters_Create(MONSTER_SOUL, FObj.X+FObj.Rect.X+(FObj.Rect.Width div 2)-15,
+ FObj.Y+FObj.Rect.Y, D_RIGHT);
+ if mon <> nil then
begin
- gMonsters[sx].SetState(STATE_GO);
- gMonsters[sx].FNoRespawn := True;
+ mon.SetState(STATE_GO);
+ mon.FNoRespawn := True;
Inc(gTotalMonsters);
if g_Game_IsNet then MH_SEND_MonsterSpawn(gMonsters[sx].UID);
end;
g_Weapon_ball2(wx, wy, tx, ty, FUID);
MONSTER_PAIN:
begin // Ñîçäàåì Lost_Soul:
- sx := g_Monsters_Create(MONSTER_SOUL, FObj.X+(FObj.Rect.Width div 2),
- FObj.Y+FObj.Rect.Y, FDirection);
+ mon := g_Monsters_Create(MONSTER_SOUL, FObj.X+(FObj.Rect.Width div 2),
+ FObj.Y+FObj.Rect.Y, FDirection);
- if sx <> -1 then
+ if mon <> nil then
begin // Öåëü - öåëü Pain_Elemental'à. Ëåòèì ê íåé:
- gMonsters[sx].FTargetUID := FTargetUID;
+ mon.FTargetUID := FTargetUID;
GetPos(FTargetUID, @o);
- gMonsters[sx].FTargetTime := 0;
- gMonsters[sx].FNoRespawn := True;
- gMonsters[sx].SetState(STATE_GO);
- gMonsters[sx].shoot(@o, True);
+ mon.FTargetTime := 0;
+ mon.FNoRespawn := True;
+ mon.SetState(STATE_GO);
+ mon.shoot(@o, True);
Inc(gTotalMonsters);
if g_Game_IsNet then MH_SEND_MonsterSpawn(gMonsters[sx].UID);
begin
end;
+
+// ////////////////////////////////////////////////////////////////////////// //
+function g_Mons_ForEach (cb: TEachMonsterCB): Boolean;
+var
+ idx: Integer;
+begin
+ result := false;
+ if (gMonsters = nil) or not assigned(cb) then exit;
+ for idx := 0 to High(gMonsters) do
+ begin
+ if (gMonsters[idx] <> nil) then
+ begin
+ result := cb(idx, gMonsters[idx]);
+ if result then exit;
+ end;
+ end;
+end;
+
+
+// throws on invalid uid
+function g_Mons_ByIdx (uid: Integer): TMonster; inline;
+begin
+ result := g_Mons_ByIdx_NC(uid);
+ if (result = nil) then raise Exception.Create('g_Mons_ByIdx: invalid monster id');
+end;
+
+
+// can return null
+function g_Mons_ByIdx_NC (uid: Integer): TMonster; inline;
+begin
+ if (uid < 0) or (uid > High(gMonsters)) then begin result := nil; exit; end;
+ result := gMonsters[uid];
+end;
+
+
+function g_Mons_AnyAt (x, y: Integer; width, height: Integer): Boolean;
+var
+ idx: Integer;
+begin
+ result := false;
+ if (width < 1) or (height < 1) then exit;
+
+ for idx := 0 to High(gMonsters) do
+ begin
+ if (gMonsters[idx] <> nil) and gMonsters[idx].Live then
+ begin
+ if g_Obj_Collide(x, y, width, height, @gMonsters[idx].Obj) then
+ begin
+ result := True;
+ exit;
+ end;
+ end;
+ end;
+end;
+
+
end.
diff --git a/src/game/g_netmsg.pas b/src/game/g_netmsg.pas
index 33273f896a9ab3e339d1ca731a0a4ec53a129959..a60f95fe10e2e313b1fd2512029fe5db397c2527 100644 (file)
--- a/src/game/g_netmsg.pas
+++ b/src/game/g_netmsg.pas
@@ -634,6 +634,12 @@ procedure MH_SEND_Everything(CreatePlayers: Boolean = False; ID: Integer = NET_E
MH_SEND_ItemSpawn(True, it.myid, ID);
end;
+ function sendMonSpawn (monidx: Integer; mon: TMonster): Boolean;
+ begin
+ result := false; // don't stop
+ MH_SEND_MonsterSpawn(mon.UID, ID);
+ end;
+
var
I: Integer;
begin
end;
g_Items_ForEachAlive(sendItemRespawn, true); // backwards
-
- if gMonsters <> nil then
- for I := 0 to High(gMonsters) do
- if gMonsters[I] <> nil then
- MH_SEND_MonsterSpawn(gMonsters[I].UID, ID);
+ g_Mons_ForEach(sendMonSpawn);
if gWalls <> nil then
for I := Low(gWalls) to High(gWalls) do
procedure MC_RECV_MonsterDelete(P: Pointer);
var
ID: Integer;
- M: TMonster;
+ M, mon: TMonster;
begin
ID := e_Raw_Read_Word(P);
M := g_Monsters_Get(ID);
if M = nil then Exit;
- gMonsters[ID].SetState(5);
- gMonsters[ID].MonsterRemoved := True;
+ mon := g_Mons_ByIdx(ID);
+ mon.SetState(5);
+ mon.MonsterRemoved := True;
end;
procedure MC_RECV_TimeSync(P: Pointer);
diff --git a/src/game/g_player.pas b/src/game/g_player.pas
index 0ee9365f2adbee0cf6183a774a83500781d6ea23..75366d34590e693d5c82b50f235ee20adcc27f04 100644 (file)
--- a/src/game/g_player.pas
+++ b/src/game/g_player.pas
mon: TMonster;
pla, tpla: TPlayer;
vsPlayer, vsMonster, ok: Boolean;
+
+
+ function monsUpdate (monidx: Integer; mon: TMonster): Boolean;
+ begin
+ result := false; // don't stop
+ if (mon <> nil) and (mon.Live) and (mon.MonsterType <> MONSTER_BARREL) then
+ begin
+ if not TargetOnScreen(mon.Obj.X+mon.Obj.Rect.X, mon.Obj.Y+mon.Obj.Rect.Y) then exit;
+
+ x2 := mon.Obj.X+mon.Obj.Rect.X+(mon.Obj.Rect.Width div 2);
+ y2 := mon.Obj.Y+mon.Obj.Rect.Y+(mon.Obj.Rect.Height div 2);
+
+ // Åñëè ìîíñòð íà ýêðàíå è íå ïðèêðûò ñòåíîé
+ if g_TraceVector(x1, y1, x2, y2) then
+ begin
+ // Äîáàâëÿåì ê ñïèñêó âîçìîæíûõ öåëåé
+ SetLength(targets, Length(targets)+1);
+ with targets[High(targets)] do
+ begin
+ UID := mon.UID;
+ X := mon.Obj.X;
+ Y := mon.Obj.Y;
+ cX := x2;
+ cY := y2;
+ Rect := mon.Obj.Rect;
+ Dist := g_PatchLength(x1, y1, x2, y2);
+ Line := (y1+4 < Target.Y + mon.Obj.Rect.Y + mon.Obj.Rect.Height) and
+ (y1-4 > Target.Y + mon.Obj.Rect.Y);
+ Visible := True;
+ IsPlayer := False;
+ end;
+ end;
+ end;
+ end;
+
begin
vsPlayer := LongBool(gGameSettings.Options and GAME_OPTION_BOTVSPLAYER);
vsMonster := LongBool(gGameSettings.Options and GAME_OPTION_BOTVSMONSTER);
end;
// Ìîíñòðû:
- if vsMonster and (gMonsters <> nil) then
- for a := 0 to High(gMonsters) do
- if (gMonsters[a] <> nil) and (gMonsters[a].Live) and
- (gMonsters[a].MonsterType <> MONSTER_BARREL) then
- begin
- mon := gMonsters[a];
-
- if not TargetOnScreen(mon.Obj.X + mon.Obj.Rect.X,
- mon.Obj.Y + mon.Obj.Rect.Y) then
- Continue;
-
- x2 := mon.Obj.X + mon.Obj.Rect.X + (mon.Obj.Rect.Width div 2);
- y2 := mon.Obj.Y + mon.Obj.Rect.Y + (mon.Obj.Rect.Height div 2);
-
- // Åñëè ìîíñòð íà ýêðàíå è íå ïðèêðûò ñòåíîé:
- if g_TraceVector(x1, y1, x2, y2) then
- begin
- // Äîáàâëÿåì ê ñïèñêó âîçìîæíûõ öåëåé:
- SetLength(targets, Length(targets)+1);
- with targets[High(targets)] do
- begin
- UID := mon.UID;
- X := mon.Obj.X;
- Y := mon.Obj.Y;
- cX := x2;
- cY := y2;
- Rect := mon.Obj.Rect;
- Dist := g_PatchLength(x1, y1, x2, y2);
- Line := (y1+4 < Target.Y + mon.Obj.Rect.Y + mon.Obj.Rect.Height) and
- (y1-4 > Target.Y + mon.Obj.Rect.Y);
- Visible := True;
- IsPlayer := False;
- end;
- end;
- end;
+ if vsMonster then g_Mons_ForEach(monsUpdate);
end;
// Åñëè åñòü âîçìîæíûå öåëè:
index 40cf5cc16040931f7480f06f890b1d15bf9fa4e8..aaf01b5efd86bcac97a56a56f64787127644bc6d 100644 (file)
--- a/src/game/g_saveload.pas
+++ b/src/game/g_saveload.pas
///// /////
// Èùåì òðèããåðû ñ óñëîâèåì ñìåðòè ìîíñòðîâ:
- if (gMonsters <> nil) and (gTriggers <> nil) then
+ if {(gMonsters <> nil) and} (gTriggers <> nil) then
g_Map_ReAdd_DieTriggers();
// Çàêðûâàåì ôàéë çàãðóçêè:
index 7238c8046c4bec7b4a75921f1de6f47b38a1807c..ec3bb7144f67e6ae7f1c2f05c62890134968af8a 100644 (file)
--- a/src/game/g_triggers.pas
+++ b/src/game/g_triggers.pas
procedure tr_CloseTrap(PanelID: Integer; NoSound: Boolean; d2d: Boolean);
var
a, b, c: Integer;
+ wx, wy, wh, ww: Integer;
+
+ function monsDamage (monidx: Integer; mon: TMonster): Boolean;
+ begin
+ result := false; // don't stop
+ if (mon <> nil) and mon.Live and g_Obj_Collide(wx, wy, ww, wh, @mon.Obj) then
+ begin
+ mon.Damage(TRAP_DAMAGE, 0, 0, 0, HIT_TRAP);
+ end;
+ end;
+
begin
if PanelID = -1 then Exit;
if not d2d then
begin
with gWalls[PanelID] do
+ begin
if (not NoSound) and (not Enabled) then
begin
g_Sound_PlayExAt('SOUND_GAME_SWITCH1', X, Y);
if g_Game_IsServer and g_Game_IsNet then
MH_SEND_Sound(X, Y, 'SOUND_GAME_SWITCH1');
end;
+ end;
+
+ wx := gWalls[PanelID].X;
+ wy := gWalls[PanelID].Y;
+ ww := gWalls[PanelID].Width;
+ wh := gWalls[PanelID].Height;
with gWalls[PanelID] do
begin
gPlayers[a].Collide(X, Y, Width, Height) then
gPlayers[a].Damage(TRAP_DAMAGE, 0, 0, 0, HIT_TRAP);
- if gMonsters <> nil then
- for a := 0 to High(gMonsters) do
- if (gMonsters[a] <> nil) and gMonsters[a].Live and
- g_Obj_Collide(X, Y, Width, Height, @gMonsters[a].Obj) then
- gMonsters[a].Damage(TRAP_DAMAGE, 0, 0, 0, HIT_TRAP);
+ g_Mons_ForEach(monsDamage);
if not Enabled then g_Map_EnableWall(PanelID);
end;
for a := 0 to High(gDoorMap) do
begin
for b := 0 to High(gDoorMap[a]) do
+ begin
if gDoorMap[a, b] = DWORD(PanelID) then
begin
c := a;
Break;
end;
+ end;
if c <> -1 then Break;
end;
if c = -1 then Exit;
if not NoSound then
+ begin
for b := 0 to High(gDoorMap[c]) do
+ begin
if not gWalls[gDoorMap[c, b]].Enabled then
begin
with gWalls[PanelID] do
begin
g_Sound_PlayExAt('SOUND_GAME_SWITCH1', X, Y);
- if g_Game_IsServer and g_Game_IsNet then
- MH_SEND_Sound(X, Y, 'SOUND_GAME_SWITCH1');
+ if g_Game_IsServer and g_Game_IsNet then MH_SEND_Sound(X, Y, 'SOUND_GAME_SWITCH1');
end;
Break;
end;
+ end;
+ end;
for b := 0 to High(gDoorMap[c]) do
+ begin
+ wx := gWalls[gDoorMap[c, b]].X;
+ wy := gWalls[gDoorMap[c, b]].Y;
+ ww := gWalls[gDoorMap[c, b]].Width;
+ wh := gWalls[gDoorMap[c, b]].Height;
+
with gWalls[gDoorMap[c, b]] do
begin
if gPlayers <> nil then
gPlayers[a].Collide(X, Y, Width, Height) then
gPlayers[a].Damage(TRAP_DAMAGE, 0, 0, 0, HIT_TRAP);
+ g_Mons_ForEach(monsDamage);
+ (*
if gMonsters <> nil then
for a := 0 to High(gMonsters) do
if (gMonsters[a] <> nil) and gMonsters[a].Live and
g_Obj_Collide(X, Y, Width, Height, @gMonsters[a].Obj) then
gMonsters[a].Damage(TRAP_DAMAGE, 0, 0, 0, HIT_TRAP);
+ *)
if not Enabled then g_Map_EnableWall(gDoorMap[c, b]);
end;
+ end;
end;
end;
animonce: Boolean;
p: TPlayer;
m: TMonster;
- i, k, wx, wy, xd, yd: Integer;
+ idx, k, wx, wy, xd, yd: Integer;
iid: LongWord;
coolDown: Boolean;
pAngle: Real;
UIDType: Byte;
TargetUID: Word;
it: PItem;
+ mon: TMonster;
+
+ function monsShotTarget (monidx: Integer; mon: TMonster): Boolean;
+ begin
+ result := false; // don't stop
+ if (mon <> nil) and mon.Live and tr_ShotAimCheck(Trigger, @(mon.Obj)) then
+ begin
+ xd := mon.GameX + mon.Obj.Rect.Width div 2;
+ yd := mon.GameY + mon.Obj.Rect.Height div 2;
+ TargetUID := mon.UID;
+ result := true; // stop
+ end;
+ end;
+
+ function monsShotTargetMonPlr (monidx: Integer; mon: TMonster): Boolean;
+ begin
+ result := false; // don't stop
+ if (mon <> nil) and mon.Live and tr_ShotAimCheck(Trigger, @(mon.Obj)) then
+ begin
+ xd := mon.GameX + mon.Obj.Rect.Width div 2;
+ yd := mon.GameY + mon.Obj.Rect.Height div 2;
+ TargetUID := mon.UID;
+ result := true; // stop
+ end;
+ end;
+
+ function monShotTargetPlrMon (monidx: Integer; mon: TMonster): Boolean;
+ begin
+ result := false; // don't stop
+ if (mon <> nil) and mon.Live and tr_ShotAimCheck(Trigger, @(mon.Obj)) then
+ begin
+ xd := mon.GameX + mon.Obj.Rect.Width div 2;
+ yd := mon.GameY + mon.Obj.Rect.Height div 2;
+ TargetUID := mon.UID;
+ result := true; // stop
+ end;
+ end;
+
begin
Result := False;
if g_Game_IsClient then
if (Data.MonMax > 0) and (SpawnedCount >= Data.MonMax) then
Break;
- i := g_Monsters_Create(Data.MonType,
+ mon := g_Monsters_Create(Data.MonType,
Data.MonPos.X, Data.MonPos.Y,
TDirection(Data.MonDir), True);
// Çäîðîâüå:
if (Data.MonHealth > 0) then
- gMonsters[i].SetHealth(Data.MonHealth);
+ mon.SetHealth(Data.MonHealth);
// Óñòàíàâëèâàåì ïîâåäåíèå:
- gMonsters[i].MonsterBehaviour := Data.MonBehav;
- gMonsters[i].FNoRespawn := True;
+ mon.MonsterBehaviour := Data.MonBehav;
+ mon.FNoRespawn := True;
if g_Game_IsNet then
- MH_SEND_MonsterSpawn(gMonsters[i].UID);
+ MH_SEND_MonsterSpawn(mon.UID);
// Èäåì èñêàòü öåëü, åñëè íàäî:
if Data.MonActive then
- gMonsters[i].WakeUp();
+ mon.WakeUp();
if Data.MonType <> MONSTER_BARREL then Inc(gTotalMonsters);
if g_Game_IsNet then
begin
SetLength(gMonstersSpawned, Length(gMonstersSpawned)+1);
- gMonstersSpawned[High(gMonstersSpawned)] := gMonsters[i].UID;
+ gMonstersSpawned[High(gMonstersSpawned)] := mon.UID;
end;
if Data.MonMax > 0 then
begin
- gMonsters[i].SpawnTrigger := ID;
+ mon.SpawnTrigger := ID;
Inc(SpawnedCount);
end;
begin
Anim := TAnimation.Create(FramesID, False, 3);
g_Sound_PlayExAt('SOUND_GAME_TELEPORT', Data.MonPos.X, Data.MonPos.Y);
- g_GFX_OnceAnim(gMonsters[i].Obj.X+gMonsters[i].Obj.Rect.X+(gMonsters[i].Obj.Rect.Width div 2)-32,
- gMonsters[i].Obj.Y+gMonsters[i].Obj.Rect.Y+(gMonsters[i].Obj.Rect.Height div 2)-32, Anim);
+ g_GFX_OnceAnim(mon.Obj.X+mon.Obj.Rect.X+(mon.Obj.Rect.Width div 2)-32,
+ mon.Obj.Y+mon.Obj.Rect.Y+(mon.Obj.Rect.Height div 2)-32, Anim);
Anim.Free();
end;
if g_Game_IsServer and g_Game_IsNet then
- MH_SEND_Effect(gMonsters[i].Obj.X+gMonsters[i].Obj.Rect.X+(gMonsters[i].Obj.Rect.Width div 2)-32,
- gMonsters[i].Obj.Y+gMonsters[i].Obj.Rect.Y+(gMonsters[i].Obj.Rect.Height div 2)-32, 1,
+ MH_SEND_Effect(mon.Obj.X+mon.Obj.Rect.X+(mon.Obj.Rect.Width div 2)-32,
+ mon.Obj.Y+mon.Obj.Rect.Y+(mon.Obj.Rect.Height div 2)-32, 1,
NET_GFX_TELE);
end;
EFFECT_RESPAWN: begin
begin
Anim := TAnimation.Create(FramesID, False, 4);
g_Sound_PlayExAt('SOUND_ITEM_RESPAWNITEM', Data.MonPos.X, Data.MonPos.Y);
- g_GFX_OnceAnim(gMonsters[i].Obj.X+gMonsters[i].Obj.Rect.X+(gMonsters[i].Obj.Rect.Width div 2)-16,
- gMonsters[i].Obj.Y+gMonsters[i].Obj.Rect.Y+(gMonsters[i].Obj.Rect.Height div 2)-16, Anim);
+ g_GFX_OnceAnim(mon.Obj.X+mon.Obj.Rect.X+(mon.Obj.Rect.Width div 2)-16,
+ mon.Obj.Y+mon.Obj.Rect.Y+(mon.Obj.Rect.Height div 2)-16, Anim);
Anim.Free();
end;
if g_Game_IsServer and g_Game_IsNet then
- MH_SEND_Effect(gMonsters[i].Obj.X+gMonsters[i].Obj.Rect.X+(gMonsters[i].Obj.Rect.Width div 2)-16,
- gMonsters[i].Obj.Y+gMonsters[i].Obj.Rect.Y+(gMonsters[i].Obj.Rect.Height div 2)-16, 1,
+ MH_SEND_Effect(mon.Obj.X+mon.Obj.Rect.X+(mon.Obj.Rect.Width div 2)-16,
+ mon.Obj.Y+mon.Obj.Rect.Y+(mon.Obj.Rect.Height div 2)-16, 1,
NET_GFX_RESPAWN);
end;
EFFECT_FIRE: begin
begin
Anim := TAnimation.Create(FramesID, False, 4);
g_Sound_PlayExAt('SOUND_FIRE', Data.MonPos.X, Data.MonPos.Y);
- g_GFX_OnceAnim(gMonsters[i].Obj.X+gMonsters[i].Obj.Rect.X+(gMonsters[i].Obj.Rect.Width div 2)-32,
- gMonsters[i].Obj.Y+gMonsters[i].Obj.Rect.Y+gMonsters[i].Obj.Rect.Height-128, Anim);
+ g_GFX_OnceAnim(mon.Obj.X+mon.Obj.Rect.X+(mon.Obj.Rect.Width div 2)-32,
+ mon.Obj.Y+mon.Obj.Rect.Y+mon.Obj.Rect.Height-128, Anim);
Anim.Free();
end;
if g_Game_IsServer and g_Game_IsNet then
- MH_SEND_Effect(gMonsters[i].Obj.X+gMonsters[i].Obj.Rect.X+(gMonsters[i].Obj.Rect.Width div 2)-32,
- gMonsters[i].Obj.Y+gMonsters[i].Obj.Rect.Y+gMonsters[i].Obj.Rect.Height-128, 1,
+ MH_SEND_Effect(mon.Obj.X+mon.Obj.Rect.X+(mon.Obj.Rect.Width div 2)-32,
+ mon.Obj.Y+mon.Obj.Rect.Y+mon.Obj.Rect.Height-128, 1,
NET_GFX_FIRE);
end;
end;
if coolDown then
begin
// Âñïîìèíàåì, àêòèâèðîâàë ëè îí ìåíÿ ðàíüøå
- for i := 0 to High(Activators) do
- if Activators[i].UID = ActivateUID then
+ for idx := 0 to High(Activators) do
+ if Activators[idx].UID = ActivateUID then
begin
- k := i;
+ k := idx;
Break;
end;
if k = -1 then
end;
// Íàçíà÷àåì âðåìÿ ñëåäóþùåãî âîçäåéñòâèÿ
if TriggerType = TRIGGER_DAMAGE then
- i := Data.DamageInterval
+ idx := Data.DamageInterval
else
- i := Data.HealInterval;
+ idx := Data.HealInterval;
if coolDown then
- if i > 0 then
- Activators[k].TimeOut := i
+ if idx > 0 then
+ Activators[k].TimeOut := idx
else
Activators[k].TimeOut := 65535;
end;
case Data.ShotTarget of
TRIGGER_SHOT_TARGET_MON: // monsters
- if gMonsters <> nil then
- for i := Low(gMonsters) to High(gMonsters) do
- if (gMonsters[i] <> nil) and gMonsters[i].Live and
- tr_ShotAimCheck(Trigger, @(gMonsters[i].Obj)) then
- begin
- xd := gMonsters[i].GameX + gMonsters[i].Obj.Rect.Width div 2;
- yd := gMonsters[i].GameY + gMonsters[i].Obj.Rect.Height div 2;
- TargetUID := gMonsters[i].UID;
- break;
- end;
+ g_Mons_ForEach(monsShotTarget);
TRIGGER_SHOT_TARGET_PLR: // players
if gPlayers <> nil then
- for i := Low(gPlayers) to High(gPlayers) do
- if (gPlayers[i] <> nil) and gPlayers[i].Live and
- tr_ShotAimCheck(Trigger, @(gPlayers[i].Obj)) then
+ for idx := Low(gPlayers) to High(gPlayers) do
+ if (gPlayers[idx] <> nil) and gPlayers[idx].Live and
+ tr_ShotAimCheck(Trigger, @(gPlayers[idx].Obj)) then
begin
- xd := gPlayers[i].GameX + PLAYER_RECT_CX;
- yd := gPlayers[i].GameY + PLAYER_RECT_CY;
- TargetUID := gPlayers[i].UID;
+ xd := gPlayers[idx].GameX + PLAYER_RECT_CX;
+ yd := gPlayers[idx].GameY + PLAYER_RECT_CY;
+ TargetUID := gPlayers[idx].UID;
break;
end;
TRIGGER_SHOT_TARGET_RED: // red team
if gPlayers <> nil then
- for i := Low(gPlayers) to High(gPlayers) do
- if (gPlayers[i] <> nil) and gPlayers[i].Live and
- (gPlayers[i].Team = TEAM_RED) and
- tr_ShotAimCheck(Trigger, @(gPlayers[i].Obj)) then
+ for idx := Low(gPlayers) to High(gPlayers) do
+ if (gPlayers[idx] <> nil) and gPlayers[idx].Live and
+ (gPlayers[idx].Team = TEAM_RED) and
+ tr_ShotAimCheck(Trigger, @(gPlayers[idx].Obj)) then
begin
- xd := gPlayers[i].GameX + PLAYER_RECT_CX;
- yd := gPlayers[i].GameY + PLAYER_RECT_CY;
- TargetUID := gPlayers[i].UID;
+ xd := gPlayers[idx].GameX + PLAYER_RECT_CX;
+ yd := gPlayers[idx].GameY + PLAYER_RECT_CY;
+ TargetUID := gPlayers[idx].UID;
break;
end;
TRIGGER_SHOT_TARGET_BLUE: // blue team
if gPlayers <> nil then
- for i := Low(gPlayers) to High(gPlayers) do
- if (gPlayers[i] <> nil) and gPlayers[i].Live and
- (gPlayers[i].Team = TEAM_BLUE) and
- tr_ShotAimCheck(Trigger, @(gPlayers[i].Obj)) then
+ for idx := Low(gPlayers) to High(gPlayers) do
+ if (gPlayers[idx] <> nil) and gPlayers[idx].Live and
+ (gPlayers[idx].Team = TEAM_BLUE) and
+ tr_ShotAimCheck(Trigger, @(gPlayers[idx].Obj)) then
begin
- xd := gPlayers[i].GameX + PLAYER_RECT_CX;
- yd := gPlayers[i].GameY + PLAYER_RECT_CY;
- TargetUID := gPlayers[i].UID;
+ xd := gPlayers[idx].GameX + PLAYER_RECT_CX;
+ yd := gPlayers[idx].GameY + PLAYER_RECT_CY;
+ TargetUID := gPlayers[idx].UID;
break;
end;
TRIGGER_SHOT_TARGET_MONPLR: // monsters then players
begin
- if gMonsters <> nil then
- for i := Low(gMonsters) to High(gMonsters) do
- if (gMonsters[i] <> nil) and gMonsters[i].Live and
- tr_ShotAimCheck(Trigger, @(gMonsters[i].Obj)) then
- begin
- xd := gMonsters[i].GameX + gMonsters[i].Obj.Rect.Width div 2;
- yd := gMonsters[i].GameY + gMonsters[i].Obj.Rect.Height div 2;
- TargetUID := gMonsters[i].UID;
- break;
- end;
+ g_Mons_ForEach(monsShotTargetMonPlr);
+
if (TargetUID = 0) and (gPlayers <> nil) then
- for i := Low(gPlayers) to High(gPlayers) do
- if (gPlayers[i] <> nil) and gPlayers[i].Live and
- tr_ShotAimCheck(Trigger, @(gPlayers[i].Obj)) then
+ for idx := Low(gPlayers) to High(gPlayers) do
+ if (gPlayers[idx] <> nil) and gPlayers[idx].Live and
+ tr_ShotAimCheck(Trigger, @(gPlayers[idx].Obj)) then
begin
- xd := gPlayers[i].GameX + PLAYER_RECT_CX;
- yd := gPlayers[i].GameY + PLAYER_RECT_CY;
- TargetUID := gPlayers[i].UID;
+ xd := gPlayers[idx].GameX + PLAYER_RECT_CX;
+ yd := gPlayers[idx].GameY + PLAYER_RECT_CY;
+ TargetUID := gPlayers[idx].UID;
break;
end;
end;
TRIGGER_SHOT_TARGET_PLRMON: // players then monsters
begin
if gPlayers <> nil then
- for i := Low(gPlayers) to High(gPlayers) do
- if (gPlayers[i] <> nil) and gPlayers[i].Live and
- tr_ShotAimCheck(Trigger, @(gPlayers[i].Obj)) then
+ for idx := Low(gPlayers) to High(gPlayers) do
+ if (gPlayers[idx] <> nil) and gPlayers[idx].Live and
+ tr_ShotAimCheck(Trigger, @(gPlayers[idx].Obj)) then
begin
- xd := gPlayers[i].GameX + PLAYER_RECT_CX;
- yd := gPlayers[i].GameY + PLAYER_RECT_CY;
- TargetUID := gPlayers[i].UID;
- break;
- end;
- if (TargetUID = 0) and (gMonsters <> nil) then
- for i := Low(gMonsters) to High(gMonsters) do
- if (gMonsters[i] <> nil) and gMonsters[i].Live and
- tr_ShotAimCheck(Trigger, @(gMonsters[i].Obj)) then
- begin
- xd := gMonsters[i].GameX + gMonsters[i].Obj.Rect.Width div 2;
- yd := gMonsters[i].GameY + gMonsters[i].Obj.Rect.Height div 2;
- TargetUID := gMonsters[i].UID;
+ xd := gPlayers[idx].GameX + PLAYER_RECT_CX;
+ yd := gPlayers[idx].GameY + PLAYER_RECT_CY;
+ TargetUID := gPlayers[idx].UID;
break;
end;
+ if TargetUID = 0 then g_Mons_ForEach(monShotTargetPlrMon);
end;
else begin
TRIGGER_EFFECT:
begin
- i := Data.FXCount;
+ idx := Data.FXCount;
- while i > 0 do
+ while idx > 0 do
begin
case Data.FXPos of
TRIGGER_EFFECT_POS_CENTER:
tr_MakeEffect(wx, wy, xd, yd,
Data.FXType, Data.FXSubType,
Data.FXColorR, Data.FXColorG, Data.FXColorB, True, False);
- Dec(i);
+ Dec(idx);
end;
TimeOut := Data.FXWait;
end;
var
a, b, i: Integer;
Affected: array of Integer;
+
+ function monsNear (monidx: Integer; 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;
+
begin
if gTriggers = nil then
Exit;
ActivateTrigger(gTriggers[a], 0);
end else
begin
- // "Ìîíñòð áëèçêî":
+ // "Ìîíñòð áëèçêî"
if ByteBool(ActivateType and ACTIVATE_MONSTERCOLLIDE) and
(TimeOut = 0) and (Keys = 0) then // Åñëè íå íóæíû êëþ÷è
- if gMonsters <> nil then
- for b := 0 to High(gMonsters) do
- if (gMonsters[b] <> nil) then
- with gMonsters[b] do
- if Collide(X, Y, Width, Height) then
- begin
- gTriggers[a].ActivateUID := UID;
- ActivateTrigger(gTriggers[a], ACTIVATE_MONSTERCOLLIDE);
- end;
+ begin
+ g_Mons_ForEach(monsNear);
+ end;
- // "Ìîíñòðîâ íåò":
+ // "Ìîíñòðîâ íåò"
if ByteBool(ActivateType and ACTIVATE_NOMONSTER) and
(TimeOut = 0) and (Keys = 0) then
if not g_CollideMonster(X, Y, Width, Height) then
diff --git a/src/game/g_weapons.pas b/src/game/g_weapons.pas
index 3585ef2b4d136f148003fcc717d9a172bc28f4e6..2cdfe87a09935a9dac8cebba83412243a47ed6cf 100644 (file)
--- a/src/game/g_weapons.pas
+++ b/src/game/g_weapons.pas
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
+ if mon.Live and mon.Collide(gWater[WaterMap[a][c]]) and (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;
- if gMonsters <> nil then
- begin
- for d := 0 to High(gMonsters) do
- if (gMonsters[d] <> nil) and (gMonsters[d].Live) then
- if gMonsters[d].Collide(gWater[WaterMap[a][c]]) then
- if not InWArray(d, mn) then
- if i2 < 1023 then
- begin
- i2 := i2+1;
- mn[i2] := d;
- end;
- end;
+ g_Mons_ForEach(monsWaterCheck);
end;
if i1 <> -1 then
if i2 <> -1 then
for d := 0 to i2 do
- gMonsters[mn[d]].Damage(dm, 0, 0, Shots[ID].SpawnerUID, t);
+ g_Mons_ByIdx(mn[d]).Damage(dm, 0, 0, Shots[ID].SpawnerUID, t);
end;
pl := nil;
if (p.UID = SpawnerUID) and (t <> HIT_ROCKET) and (t <> HIT_ELECTRO) then
Exit;
- if g_Game_IsServer then
+ if g_Game_IsServer then
begin
if (t <> HIT_FLAME) or (p.FFireTime = 0) or (vx <> 0) or (vy <> 0) then
p.Damage(d, SpawnerUID, vx, vy, t);
function GunHit(X, Y: Integer; vx, vy: Integer; dmg: Integer;
SpawnerUID: Word; AllowPush: Boolean): Byte;
+
+ function monsCheck (monidx: Integer; mon: TMonster): Boolean;
+ begin
+ result := false; // don't stop
+ if (mon <> nil) and mon.Live and mon.Collide(X, Y) then
+ begin
+ if HitMonster(mon, dmg, vx*10, vy*10-3, SpawnerUID, HIT_SOME) then
+ begin
+ if AllowPush then mon.Push(vx, vy);
+ result := true;
+ end;
+ end;
+ end;
+
var
i, h: Integer;
begin
if Result <> 0 then Exit;
- h := High(gMonsters);
+ if g_Mons_ForEach(monsCheck) then result := 2;
+end;
- if h <> -1 then
- for i := 0 to h do
- if (gMonsters[i] <> nil) and gMonsters[i].Live and gMonsters[i].Collide(X, Y) then
- if HitMonster(gMonsters[i], dmg, vx*10, vy*10-3, SpawnerUID, HIT_SOME) then
+procedure g_Weapon_BFG9000(X, Y: Integer; SpawnerUID: Word);
+
+ function monsCheck (monidx: Integer; mon: TMonster): Boolean;
+ begin
+ result := false; // don't stop
+ if (mon <> nil) and (mon.Live) and (mon.UID <> SpawnerUID) then
+ begin
+ with mon do
+ begin
+ if (g_PatchLength(X, Y, Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2),
+ Obj.Y+Obj.Rect.Y+(Obj.Rect.Height div 2)) <= SHOT_BFG_RADIUS) and
+ g_TraceVector(X, Y, Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2),
+ Obj.Y+Obj.Rect.Y+(Obj.Rect.Height div 2)) then
begin
- if AllowPush then gMonsters[i].Push(vx, vy);
- Result := 2;
- Exit;
+ if HitMonster(mon, 50, 0, 0, SpawnerUID, HIT_SOME) then mon.BFGHit();
end;
-end;
+ end;
+ end;
+ end;
-procedure g_Weapon_BFG9000(X, Y: Integer; SpawnerUID: Word);
var
i, h: Integer;
st: Byte;
gPlayers[i].BFGHit();
end;
- h := High(gMonsters);
-
- if h <> -1 then
- for i := 0 to h do
- if (gMonsters[i] <> nil) and (gMonsters[i].Live) and (gMonsters[i].UID <> SpawnerUID) then
- with gMonsters[i] do
- if (g_PatchLength(X, Y, Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2),
- Obj.Y+Obj.Rect.Y+(Obj.Rect.Height div 2)) <= SHOT_BFG_RADIUS) and
- g_TraceVector(X, Y, Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2),
- Obj.Y+Obj.Rect.Y+(Obj.Rect.Height div 2)) then
- if HitMonster(gMonsters[i], 50, 0, 0, SpawnerUID, HIT_SOME) then gMonsters[i].BFGHit();
+ g_Mons_ForEach(monsCheck);
end;
function g_Weapon_CreateShot(I: Integer; ShotType: Byte; Spawner, TargetUID: Word; X, Y, XV, YV: Integer): LongWord;
Shots[i].Stopped := 0;
if Shots[i].ShotType in [WEAPON_ROCKETLAUNCHER, WEAPON_BFG] then
Shots[i].Timeout := 900 // ~25 sec
- else
+ else
begin
if Shots[i].ShotType = WEAPON_FLAMETHROWER then
Shots[i].Timeout := SHOT_FLAME_LIFETIME
end;
end;
end;
- function MonsterHit(): Boolean;
- var
- i: Integer;
+
+ function monsCheckHit (monidx: Integer; mon: TMonster): Boolean;
begin
- Result := False;
- h := High(gMonsters);
+ result := false; // don't stop
+ if (mon <> nil) and mon.Live and g_Obj_Collide(obj, @mon.Obj) then
+ begin
+ if HitMonster(mon, d, obj^.Vel.X, obj^.Vel.Y, SpawnerUID, t) then
+ begin
+ if (t <> HIT_FLAME) then
+ begin
+ mon.Push((obj^.Vel.X+obj^.Accel.X)*IfThen(t = HIT_BFG, 8, 1) div 4,
+ (obj^.Vel.Y+obj^.Accel.Y)*IfThen(t = HIT_BFG, 8, 1) div 4);
+ end;
+ result := True;
+ end;
+ end;
+ end;
- if h <> -1 then
- for i := 0 to h do
- if (gMonsters[i] <> nil) and gMonsters[i].Live and g_Obj_Collide(obj, @gMonsters[i].Obj) then
- if HitMonster(gMonsters[i], d, obj^.Vel.X, obj^.Vel.Y, SpawnerUID, t) then
- begin
- if t <> HIT_FLAME then
- gMonsters[i].Push((obj^.Vel.X+obj^.Accel.X)*IfThen(t = HIT_BFG, 8, 1) div 4,
- (obj^.Vel.Y+obj^.Accel.Y)*IfThen(t = HIT_BFG, 8, 1) div 4);
- Result := True;
- break;
- end;
+ function MonsterHit(): Boolean;
+ begin
+ result := g_Mons_ForEach(monsCheckHit);
end;
+
begin
Result := 0;
function g_Weapon_Explode(X, Y: Integer; rad: Integer; SpawnerUID: Word): Boolean;
var
- i, h, r, dx, dy, m, mm: Integer;
+ r: Integer;
+
+ function monsExCheck (monidx: Integer; mon: TMonster): Boolean;
+ var
+ dx, dy, mm: Integer;
+ begin
+ result := false; // don't stop
+ if mon <> nil then
+ begin
+ with mon do
+ begin
+ dx := Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2)-X;
+ dy := Obj.Y+Obj.Rect.Y+(Obj.Rect.Height div 2)-Y;
+
+ if dx > 1000 then dx := 1000;
+ if dy > 1000 then dy := 1000;
+
+ if (dx*dx+dy*dy < r) then
+ begin
+ //m := PointToRect(X, Y, Obj.X+Obj.Rect.X, Obj.Y+Obj.Rect.Y, Obj.Rect.Width, Obj.Rect.Height);
+
+ mm := Max(abs(dx), abs(dy));
+ if mm = 0 then mm := 1;
+
+ if mon.Live then
+ HitMonster(mon, ((mon.Obj.Rect.Width div 4)*10*(rad-mm)) div rad,
+ 0, 0, SpawnerUID, HIT_ROCKET);
+
+ mon.Push((dx*7) div mm, (dy*7) div mm);
+ end;
+ end;
+ end;
+ end;
+
+var
+ i, h, dx, dy, m, mm: Integer;
_angle: SmallInt;
+
begin
Result := False;
end;
end;
- h := High(gMonsters);
-
- if h <> -1 then
- for i := 0 to h do
- if gMonsters[i] <> nil then
- with gMonsters[i] do
- begin
- dx := Obj.X+Obj.Rect.X+(Obj.Rect.Width div 2)-X;
- dy := Obj.Y+Obj.Rect.Y+(Obj.Rect.Height div 2)-Y;
-
- if dx > 1000 then dx := 1000;
- if dy > 1000 then dy := 1000;
-
- if dx*dx+dy*dy < r then
- begin
- //m := PointToRect(X, Y, Obj.X+Obj.Rect.X, Obj.Y+Obj.Rect.Y,
- // Obj.Rect.Width, Obj.Rect.Height);
-
- mm := Max(abs(dx), abs(dy));
- if mm = 0 then mm := 1;
-
- if gMonsters[i].Live then
- HitMonster(gMonsters[i], ((gMonsters[i].Obj.Rect.Width div 4)*10*(rad-mm)) div rad,
- 0, 0, SpawnerUID, HIT_ROCKET);
+ g_Mons_ForEach(monsExCheck);
- gMonsters[i].Push((dx*7) div mm, (dy*7) div mm);
- end;
- end;
h := High(gCorpses);
throw(find_id, x+dx, y+dy, xd+dx, yd+dy, 16);
triggers := nil;
-
+
g_Frames_Get(FramesID, 'FRAMES_WEAPON_BSPFIRE');
Animation := TAnimation.Create(FramesID, True, 4);
end;