index 2ff21708160b0e1e063545a508f405f87453be4a..e39b8c66a3dfdd7b6a2491f85087cae51e119ddb 100644 (file)
--- a/src/game/g_triggers.pas
+++ b/src/game/g_triggers.pas
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*)
-{$MODE DELPHI}
+{$INCLUDE ../shared/a_modes.inc}
unit g_triggers;
interface
function g_Triggers_Create(Trigger: TTrigger): DWORD;
procedure g_Triggers_Update();
-procedure g_Triggers_Press(ID: DWORD; ActivateType: Byte);
+procedure g_Triggers_Press(ID: DWORD; ActivateType: Byte; ActivateUID: Word = 0);
function g_Triggers_PressR(X, Y: Integer; Width, Height: Word; UID: Word;
ActivateType: Byte; IgnoreList: DWArray = nil): DWArray;
procedure g_Triggers_PressL(X1, Y1, X2, Y2: Integer; UID: DWORD; ActivateType: Byte);
-procedure g_Triggers_PressC(CX, CY: Integer; Radius: Word; UID: Word; ActivateType: Byte);
+procedure g_Triggers_PressC(CX, CY: Integer; Radius: Word; UID: Word; ActivateType: Byte; IgnoreTrigger: Integer = -1);
procedure g_Triggers_OpenAll();
procedure g_Triggers_DecreaseSpawner(ID: DWORD);
procedure g_Triggers_Free();
procedure g_Triggers_SaveState(var Mem: TBinMemoryWriter);
procedure g_Triggers_LoadState(var Mem: TBinMemoryReader);
+function tr_Message(MKind: Integer; MText: string; MSendTo: Integer; MTime: Integer; ActivateUID: Integer): Boolean;
+
+function tr_CloseDoor(PanelID: Integer; NoSound: Boolean; d2d: Boolean): Boolean;
+function tr_OpenDoor(PanelID: Integer; NoSound: Boolean; d2d: Boolean): Boolean;
+procedure tr_CloseTrap(PanelID: Integer; NoSound: Boolean; d2d: Boolean);
+function tr_SetLift(PanelID: Integer; d: Integer; NoSound: Boolean; d2d: Boolean): Boolean;
+
+function tr_Teleport(ActivateUID: Integer; TX, TY: Integer; TDir: Integer; Silent: Boolean; D2D: Boolean): Boolean;
+function tr_Push(ActivateUID: Integer; VX, VY: Integer; ResetVel: Boolean): Boolean;
+
+procedure tr_MakeEffect(X, Y, VX, VY: Integer; T, ST, CR, CG, CB: Byte; Silent, Send: Boolean);
+function tr_SpawnShot(ShotType: Integer; wx, wy, dx, dy: Integer; ShotSound: Boolean; ShotTarget: Word): Integer;
+
var
gTriggerClientID: Integer = 0;
gTriggers: array of TTrigger;
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_scripts;
+ g_options, g_net, g_netmsg;
const
TRIGGER_SIGNATURE = $52475254; // 'TRGR'
end;
end;
-function CloseDoor(PanelID: Integer; NoSound: Boolean; d2d: Boolean): Boolean;
+function tr_CloseDoor(PanelID: Integer; NoSound: Boolean; d2d: Boolean): Boolean;
var
a, b, c: Integer;
begin
with gWalls[PanelID] do
begin
if g_CollidePlayer(X, Y, Width, Height) or
- g_CollideMonster(X, Y, Width, Height) then Exit;
+ g_Mons_IsAnyAliveAt(X, Y, Width, Height) then Exit;
if not Enabled then
begin
with gWalls[gDoorMap[c, b]] do
begin
if g_CollidePlayer(X, Y, Width, Height) or
- g_CollideMonster(X, Y, Width, Height) then Exit;
+ g_Mons_IsAnyAliveAt(X, Y, Width, Height) then Exit;
end;
if not NoSound then
end;
end;
-procedure CloseTrap(PanelID: Integer; NoSound: Boolean; d2d: Boolean);
+procedure tr_CloseTrap(PanelID: Integer; NoSound: Boolean; d2d: Boolean);
var
a, b, c: Integer;
+ wx, wy, wh, ww: Integer;
+
+ function monsDamage (mon: TMonster): Boolean;
+ begin
+ result := false; // don't stop
+ if g_Obj_Collide(wx, wy, ww, wh, @mon.Obj) then mon.Damage(TRAP_DAMAGE, 0, 0, 0, HIT_TRAP);
+ 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);
+ g_Mons_ForEachAliveAt(wx, wy, ww, wh, 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);
+ g_Mons_ForEachAliveAt(wx, wy, ww, wh, 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;
-function OpenDoor(PanelID: Integer; NoSound: Boolean; d2d: Boolean): Boolean;
+function tr_OpenDoor(PanelID: Integer; NoSound: Boolean; d2d: Boolean): Boolean;
var
a, b, c: Integer;
begin
end;
end;
-function SetLift(PanelID: Integer; d: Integer; NoSound: Boolean; d2d: Boolean): Boolean;
+function tr_SetLift(PanelID: Integer; d: Integer; NoSound: Boolean; d2d: Boolean): Boolean;
var
a, b, c, t: Integer;
begin
end;
end;
-procedure MakeShot(var Trigger: TTrigger; wx, wy, dx, dy: Integer; TargetUID: Word);
+function tr_SpawnShot(ShotType: Integer; wx, wy, dx, dy: Integer; ShotSound: Boolean; ShotTarget: Word): Integer;
var
- Projectile: Boolean;
snd: string;
+ Projectile: Boolean;
TextureID: DWORD;
Anim: TAnimation;
begin
- with Trigger do
- if (Data.ShotAmmo = 0) or
- ((Data.ShotAmmo > 0) and (ShotAmmoCount > 0)) then
- begin
- if (Data.ShotPanelID <> -1) and (ShotPanelTime = 0) then
+ Result := -1;
+ TextureID := DWORD(-1);
+ snd := 'SOUND_WEAPON_FIREROCKET';
+ Projectile := True;
+ case ShotType of
+ TRIGGER_SHOT_PISTOL:
begin
- g_Map_SwitchTexture(ShotPanelType, Data.ShotPanelID);
- ShotPanelTime := 4; // òèêîâ íà âñïûøêó âûñòðåëà
+ g_Weapon_pistol(wx, wy, dx, dy, 0, True);
+ snd := 'SOUND_WEAPON_FIREPISTOL';
+ Projectile := False;
+ if ShotSound then
+ begin
+ g_Player_CreateShell(wx, wy, 0, -2, SHELL_BULLET);
+ if g_Game_IsNet then
+ MH_SEND_Effect(wx, wy, 0, NET_GFX_SHELL1);
+ end;
end;
- if Data.ShotIntSight > 0 then
- ShotSightTimeout := 180; // ~= 5 ñåêóíä
+ TRIGGER_SHOT_BULLET:
+ begin
+ g_Weapon_mgun(wx, wy, dx, dy, 0, True);
+ if gSoundEffectsDF then snd := 'SOUND_WEAPON_FIRECGUN'
+ else snd := 'SOUND_WEAPON_FIREPISTOL';
+ Projectile := False;
+ if ShotSound then
+ begin
+ g_Player_CreateShell(wx, wy, 0, -2, SHELL_BULLET);
+ if g_Game_IsNet then
+ MH_SEND_Effect(wx, wy, 0, NET_GFX_SHELL1);
+ end;
+ end;
- if ShotAmmoCount > 0 then Dec(ShotAmmoCount);
- Projectile := True;
- snd := 'SOUND_WEAPON_FIREROCKET';
+ TRIGGER_SHOT_SHOTGUN:
+ begin
+ g_Weapon_Shotgun(wx, wy, dx, dy, 0, True);
+ snd := 'SOUND_WEAPON_FIRESHOTGUN';
+ Projectile := False;
+ if ShotSound then
+ begin
+ g_Player_CreateShell(wx, wy, 0, -2, SHELL_SHELL);
+ if g_Game_IsNet then
+ MH_SEND_Effect(wx, wy, 0, NET_GFX_SHELL2);
+ end;
+ end;
- dx := dx + Random(Data.ShotAccuracy) - Random(Data.ShotAccuracy);
- dy := dy + Random(Data.ShotAccuracy) - Random(Data.ShotAccuracy);
+ TRIGGER_SHOT_SSG:
+ begin
+ g_Weapon_DShotgun(wx, wy, dx, dy, 0, True);
+ snd := 'SOUND_WEAPON_FIRESHOTGUN2';
+ Projectile := False;
+ if ShotSound then
+ begin
+ g_Player_CreateShell(wx, wy, 0, -2, SHELL_SHELL);
+ g_Player_CreateShell(wx, wy, 0, -2, SHELL_SHELL);
+ if g_Game_IsNet then
+ MH_SEND_Effect(wx, wy, 0, NET_GFX_SHELL3);
+ end;
+ end;
- case Data.ShotType of
- TRIGGER_SHOT_PISTOL:
- begin
- g_Weapon_pistol(wx, wy, dx, dy, 0, True);
- Projectile := False;
- snd := 'SOUND_WEAPON_FIREPISTOL';
- if Data.ShotSound then
- begin
- g_Player_CreateShell(wx, wy, 0, -2, SHELL_BULLET);
- if g_Game_IsNet then
- MH_SEND_Effect(wx, wy, 0, NET_GFX_SHELL1);
- end;
- end;
+ TRIGGER_SHOT_IMP:
+ begin
+ g_Weapon_ball1(wx, wy, dx, dy, 0, -1, True);
+ snd := 'SOUND_WEAPON_FIREBALL';
+ end;
- TRIGGER_SHOT_BULLET:
- begin
- g_Weapon_mgun(wx, wy, dx, dy, 0, True);
- Projectile := False;
- if gSoundEffectsDF then snd := 'SOUND_WEAPON_FIRECGUN'
- else snd := 'SOUND_WEAPON_FIREPISTOL';
- if Data.ShotSound then
- begin
- g_Player_CreateShell(wx, wy, 0, -2, SHELL_BULLET);
- if g_Game_IsNet then
- MH_SEND_Effect(wx, wy, 0, NET_GFX_SHELL1);
- end;
- end;
+ TRIGGER_SHOT_PLASMA:
+ begin
+ g_Weapon_Plasma(wx, wy, dx, dy, 0, -1, True);
+ snd := 'SOUND_WEAPON_FIREPLASMA';
+ end;
- TRIGGER_SHOT_SHOTGUN:
- begin
- g_Weapon_Shotgun(wx, wy, dx, dy, 0, True);
- Projectile := False;
- snd := 'SOUND_WEAPON_FIRESHOTGUN';
- if Data.ShotSound then
- begin
- g_Player_CreateShell(wx, wy, 0, -2, SHELL_SHELL);
- if g_Game_IsNet then
- MH_SEND_Effect(wx, wy, 0, NET_GFX_SHELL2);
- end;
- end;
+ TRIGGER_SHOT_SPIDER:
+ begin
+ g_Weapon_aplasma(wx, wy, dx, dy, 0, -1, True);
+ snd := 'SOUND_WEAPON_FIREPLASMA';
+ end;
- TRIGGER_SHOT_SSG:
- begin
- g_Weapon_DShotgun(wx, wy, dx, dy, 0, True);
- Projectile := False;
- snd := 'SOUND_WEAPON_FIRESHOTGUN2';
- if Data.ShotSound then
- begin
- g_Player_CreateShell(wx, wy, 0, -2, SHELL_SHELL);
- g_Player_CreateShell(wx, wy, 0, -2, SHELL_SHELL);
- if g_Game_IsNet then
- MH_SEND_Effect(wx, wy, 0, NET_GFX_SHELL3);
- end;
- end;
+ TRIGGER_SHOT_CACO:
+ begin
+ g_Weapon_ball2(wx, wy, dx, dy, 0, -1, True);
+ snd := 'SOUND_WEAPON_FIREBALL';
+ end;
- TRIGGER_SHOT_IMP:
- begin
- g_Weapon_ball1(wx, wy, dx, dy, 0, -1, True);
- snd := 'SOUND_WEAPON_FIREBALL';
- end;
+ TRIGGER_SHOT_BARON:
+ begin
+ g_Weapon_ball7(wx, wy, dx, dy, 0, -1, True);
+ snd := 'SOUND_WEAPON_FIREBALL';
+ end;
- TRIGGER_SHOT_PLASMA:
- begin
- g_Weapon_Plasma(wx, wy, dx, dy, 0, -1, True);
- snd := 'SOUND_WEAPON_FIREPLASMA';
- end;
+ TRIGGER_SHOT_MANCUB:
+ begin
+ g_Weapon_manfire(wx, wy, dx, dy, 0, -1, True);
+ snd := 'SOUND_WEAPON_FIREBALL';
+ end;
- TRIGGER_SHOT_SPIDER:
- begin
- g_Weapon_aplasma(wx, wy, dx, dy, 0, -1, True);
- snd := 'SOUND_WEAPON_FIREPLASMA';
- end;
+ TRIGGER_SHOT_REV:
+ begin
+ g_Weapon_revf(wx, wy, dx, dy, 0, ShotTarget, -1, True);
+ snd := 'SOUND_WEAPON_FIREREV';
+ end;
- TRIGGER_SHOT_CACO:
- begin
- g_Weapon_ball2(wx, wy, dx, dy, 0, -1, True);
- snd := 'SOUND_WEAPON_FIREBALL';
- end;
+ TRIGGER_SHOT_ROCKET:
+ begin
+ g_Weapon_Rocket(wx, wy, dx, dy, 0, -1, True);
+ snd := 'SOUND_WEAPON_FIREROCKET';
+ end;
- TRIGGER_SHOT_BARON:
- begin
- g_Weapon_ball7(wx, wy, dx, dy, 0, -1, True);
- snd := 'SOUND_WEAPON_FIREBALL';
- end;
+ TRIGGER_SHOT_BFG:
+ begin
+ g_Weapon_BFGShot(wx, wy, dx, dy, 0, -1, True);
+ snd := 'SOUND_WEAPON_FIREBFG';
+ end;
- TRIGGER_SHOT_MANCUB:
- begin
- g_Weapon_manfire(wx, wy, dx, dy, 0, -1, True);
- snd := 'SOUND_WEAPON_FIREBALL';
- end;
+ TRIGGER_SHOT_EXPL:
+ begin
+ if g_Frames_Get(TextureID, 'FRAMES_EXPLODE_ROCKET') then
+ begin
+ Anim := TAnimation.Create(TextureID, False, 6);
+ Anim.Blending := False;
+ g_GFX_OnceAnim(wx-64, wy-64, Anim);
+ Anim.Free();
+ end;
+ Projectile := False;
+ g_Weapon_Explode(wx, wy, 60, 0);
+ snd := 'SOUND_WEAPON_EXPLODEROCKET';
+ end;
- TRIGGER_SHOT_REV:
- begin
- g_Weapon_revf(wx, wy, dx, dy, 0, TargetUID, -1, True);
- snd := 'SOUND_WEAPON_FIREREV';
- end;
+ TRIGGER_SHOT_BFGEXPL:
+ begin
+ if g_Frames_Get(TextureID, 'FRAMES_EXPLODE_BFG') then
+ begin
+ Anim := TAnimation.Create(TextureID, False, 6);
+ Anim.Blending := False;
+ g_GFX_OnceAnim(wx-64, wy-64, Anim);
+ Anim.Free();
+ end;
+ Projectile := False;
+ g_Weapon_BFG9000(wx, wy, 0);
+ snd := 'SOUND_WEAPON_EXPLODEBFG';
+ end;
- TRIGGER_SHOT_ROCKET:
- begin
- g_Weapon_Rocket(wx, wy, dx, dy, 0, -1, True);
- snd := 'SOUND_WEAPON_FIREROCKET';
- end;
+ else exit;
+ end;
- TRIGGER_SHOT_BFG:
- begin
- g_Weapon_BFGShot(wx, wy, dx, dy, 0, -1, True);
- snd := 'SOUND_WEAPON_FIREBFG';
- end;
+ if g_Game_IsNet and g_Game_IsServer then
+ case ShotType of
+ TRIGGER_SHOT_EXPL:
+ MH_SEND_Effect(wx, wy, Byte(ShotSound), NET_GFX_EXPLODE);
+ TRIGGER_SHOT_BFGEXPL:
+ MH_SEND_Effect(wx, wy, Byte(ShotSound), NET_GFX_BFGEXPL);
+ else
+ begin
+ if Projectile then
+ MH_SEND_CreateShot(LastShotID);
+ if ShotSound then
+ MH_SEND_Sound(wx, wy, snd);
+ end;
+ end;
- TRIGGER_SHOT_EXPL:
- begin
- if g_Frames_Get(TextureID, 'FRAMES_EXPLODE_ROCKET') then
- begin
- Anim := TAnimation.Create(TextureID, False, 6);
- Anim.Blending := False;
- g_GFX_OnceAnim(wx-64, wy-64, Anim);
- Anim.Free();
- end;
- Projectile := False;
- g_Weapon_Explode(wx, wy, 60, 0);
- snd := 'SOUND_WEAPON_EXPLODEROCKET';
- end;
+ if ShotSound then
+ g_Sound_PlayExAt(snd, wx, wy);
- TRIGGER_SHOT_BFGEXPL:
- begin
- if g_Frames_Get(TextureID, 'FRAMES_EXPLODE_BFG') then
- begin
- Anim := TAnimation.Create(TextureID, False, 6);
- Anim.Blending := False;
- g_GFX_OnceAnim(wx-64, wy-64, Anim);
- Anim.Free();
- end;
- Projectile := False;
- g_Weapon_BFG9000(wx, wy, 0);
- snd := 'SOUND_WEAPON_EXPLODEBFG';
- end;
+ if Projectile then
+ Result := LastShotID;
+end;
+
+procedure MakeShot(var Trigger: TTrigger; wx, wy, dx, dy: Integer; TargetUID: Word);
+begin
+ with Trigger do
+ if (Data.ShotAmmo = 0) or
+ ((Data.ShotAmmo > 0) and (ShotAmmoCount > 0)) then
+ begin
+ if (Data.ShotPanelID <> -1) and (ShotPanelTime = 0) then
+ begin
+ g_Map_SwitchTexture(ShotPanelType, Data.ShotPanelID);
+ ShotPanelTime := 4; // òèêîâ íà âñïûøêó âûñòðåëà
end;
- if g_Game_IsNet and g_Game_IsServer then
- case Data.ShotType of
- TRIGGER_SHOT_EXPL:
- MH_SEND_Effect(wx, wy, Byte(Data.ShotSound), NET_GFX_EXPLODE);
- TRIGGER_SHOT_BFGEXPL:
- MH_SEND_Effect(wx, wy, Byte(Data.ShotSound), NET_GFX_BFGEXPL);
- else
- begin
- if Projectile then
- MH_SEND_CreateShot(LastShotID);
- if Data.ShotSound then
- MH_SEND_Sound(wx, wy, snd);
- end;
- end;
+ if Data.ShotIntSight > 0 then
+ ShotSightTimeout := 180; // ~= 5 ñåêóíä
+
+ if ShotAmmoCount > 0 then Dec(ShotAmmoCount);
+
+ dx := dx + Random(Data.ShotAccuracy) - Random(Data.ShotAccuracy);
+ dy := dy + Random(Data.ShotAccuracy) - Random(Data.ShotAccuracy);
- if Data.ShotSound then
- g_Sound_PlayExAt(snd, wx, wy);
+ tr_SpawnShot(Data.ShotType, wx, wy, dx, dy, Data.ShotSound, TargetUID);
end
else
if (Data.ShotIntReload > 0) and (ShotReloadTime = 0) then
ShotReloadTime := Data.ShotIntReload; // òèêîâ íà ïåðåçàðÿäêó ïóøêè
end;
-procedure MakeEffect(X, Y, VX, VY: Integer; T, ST, CR, CG, CB: Byte; Silent, Send: Boolean);
+procedure tr_MakeEffect(X, Y, VX, VY: Integer; T, ST, CR, CG, CB: Byte; Silent, Send: Boolean);
var
FramesID: DWORD;
Anim: TAnimation;
end;
end;
+function tr_Teleport(ActivateUID: Integer; TX, TY: Integer; TDir: Integer; Silent: Boolean; D2D: Boolean): Boolean;
+var
+ p: TPlayer;
+ m: TMonster;
+begin
+ Result := False;
+ if (ActivateUID < 0) or (ActivateUID > $FFFF) then Exit;
+ case g_GetUIDType(ActivateUID) of
+ UID_PLAYER:
+ begin
+ p := g_Player_Get(ActivateUID);
+ if p = nil then
+ Exit;
+
+ if D2D then
+ begin
+ if p.TeleportTo(TX-(p.Obj.Rect.Width div 2),
+ TY-p.Obj.Rect.Height,
+ Silent,
+ TDir) then
+ Result := True;
+ end
+ else
+ if p.TeleportTo(TX, TY, Silent, TDir) then
+ Result := True;
+ end;
+
+ UID_MONSTER:
+ begin
+ m := g_Monsters_ByUID(ActivateUID);
+ if m = nil then
+ Exit;
+
+ if D2D then
+ begin
+ if m.TeleportTo(TX-(m.Obj.Rect.Width div 2),
+ TY-m.Obj.Rect.Height,
+ Silent,
+ TDir) then
+ Result := True;
+ end
+ else
+ if m.TeleportTo(TX, TY, Silent, TDir) then
+ Result := True;
+ end;
+ end;
+end;
+
+function tr_Push(ActivateUID: Integer; VX, VY: Integer; ResetVel: Boolean): Boolean;
+var
+ p: TPlayer;
+ m: TMonster;
+begin
+ Result := True;
+ if (ActivateUID < 0) or (ActivateUID > $FFFF) then Exit;
+ case g_GetUIDType(ActivateUID) of
+ UID_PLAYER:
+ begin
+ p := g_Player_Get(ActivateUID);
+ if p = nil then
+ Exit;
+
+ if ResetVel then
+ begin
+ p.GameVelX := 0;
+ p.GameVelY := 0;
+ p.GameAccelX := 0;
+ p.GameAccelY := 0;
+ end;
+
+ p.Push(VX, VY);
+ end;
+
+ UID_MONSTER:
+ begin
+ m := g_Monsters_ByUID(ActivateUID);
+ if m = nil then
+ Exit;
+
+ if ResetVel then
+ begin
+ m.GameVelX := 0;
+ m.GameVelY := 0;
+ m.GameAccelX := 0;
+ m.GameAccelY := 0;
+ end;
+
+ m.Push(VX, VY);
+ end;
+ end;
+end;
+
+function tr_Message(MKind: Integer; MText: string; MSendTo: Integer; MTime: Integer; ActivateUID: Integer): Boolean;
+var
+ msg: string;
+ p: TPlayer;
+ i: Integer;
+begin
+ Result := True;
+ if (ActivateUID < 0) or (ActivateUID > $FFFF) then Exit;
+ msg := b_Text_Format(MText);
+ case MSendTo of
+ 0: // activator
+ begin
+ if g_GetUIDType(ActivateUID) = UID_PLAYER then
+ begin
+ if g_Game_IsWatchedPlayer(ActivateUID) then
+ begin
+ if MKind = 0 then
+ g_Console_Add(msg, True)
+ else if MKind = 1 then
+ g_Game_Message(msg, MTime);
+ end
+ else
+ begin
+ p := g_Player_Get(ActivateUID);
+ if g_Game_IsNet and (p.FClientID >= 0) then
+ if MKind = 0 then
+ MH_SEND_Chat(msg, NET_CHAT_SYSTEM, p.FClientID)
+ else if MKind = 1 then
+ MH_SEND_GameEvent(NET_EV_BIGTEXT, MTime, msg, p.FClientID);
+ end;
+ end;
+ end;
+
+ 1: // activator's team
+ begin
+ if g_GetUIDType(ActivateUID) = UID_PLAYER then
+ begin
+ p := g_Player_Get(ActivateUID);
+ if g_Game_IsWatchedTeam(p.Team) then
+ if MKind = 0 then
+ g_Console_Add(msg, True)
+ else if MKind = 1 then
+ g_Game_Message(msg, MTime);
+
+ if g_Game_IsNet then
+ begin
+ for i := Low(gPlayers) to High(gPlayers) do
+ if (gPlayers[i].Team = p.Team) and (gPlayers[i].FClientID >= 0) then
+ if MKind = 0 then
+ MH_SEND_Chat(msg, NET_CHAT_SYSTEM, gPlayers[i].FClientID)
+ else if MKind = 1 then
+ MH_SEND_GameEvent(NET_EV_BIGTEXT, MTime, msg, gPlayers[i].FClientID);
+ end;
+ end;
+ end;
+
+ 2: // activator's enemy team
+ begin
+ if g_GetUIDType(ActivateUID) = UID_PLAYER then
+ begin
+ p := g_Player_Get(ActivateUID);
+ if g_Game_IsWatchedTeam(p.Team) then
+ if MKind = 0 then
+ g_Console_Add(msg, True)
+ else if MKind = 1 then
+ g_Game_Message(msg, MTime);
+
+ if g_Game_IsNet then
+ begin
+ for i := Low(gPlayers) to High(gPlayers) do
+ if (gPlayers[i].Team <> p.Team) and (gPlayers[i].FClientID >= 0) then
+ if MKind = 0 then
+ MH_SEND_Chat(msg, NET_CHAT_SYSTEM, gPlayers[i].FClientID)
+ else if MKind = 1 then
+ MH_SEND_GameEvent(NET_EV_BIGTEXT, MTime, msg, gPlayers[i].FClientID);
+ end;
+ end;
+ end;
+
+ 3: // red team
+ begin
+ if g_Game_IsWatchedTeam(TEAM_RED) then
+ if MKind = 0 then
+ g_Console_Add(msg, True)
+ else if MKind = 1 then
+ g_Game_Message(msg, MTime);
+
+ if g_Game_IsNet then
+ begin
+ for i := Low(gPlayers) to High(gPlayers) do
+ if (gPlayers[i].Team = TEAM_RED) and (gPlayers[i].FClientID >= 0) then
+ if MKind = 0 then
+ MH_SEND_Chat(msg, NET_CHAT_SYSTEM, gPlayers[i].FClientID)
+ else if MKind = 1 then
+ MH_SEND_GameEvent(NET_EV_BIGTEXT, MTime, msg, gPlayers[i].FClientID);
+ end;
+ end;
+
+ 4: // blue team
+ begin
+ if g_Game_IsWatchedTeam(TEAM_BLUE) then
+ if MKind = 0 then
+ g_Console_Add(msg, True)
+ else if MKind = 1 then
+ g_Game_Message(msg, MTime);
+
+ if g_Game_IsNet then
+ begin
+ for i := Low(gPlayers) to High(gPlayers) do
+ if (gPlayers[i].Team = TEAM_BLUE) and (gPlayers[i].FClientID >= 0) then
+ if MKind = 0 then
+ MH_SEND_Chat(msg, NET_CHAT_SYSTEM, gPlayers[i].FClientID)
+ else if MKind = 1 then
+ MH_SEND_GameEvent(NET_EV_BIGTEXT, MTime, msg, gPlayers[i].FClientID);
+ end;
+ end;
+
+ 5: // everyone
+ begin
+ if MKind = 0 then
+ g_Console_Add(msg, True)
+ else if MKind = 1 then
+ g_Game_Message(msg, MTime);
+
+ if g_Game_IsNet then
+ begin
+ if MKind = 0 then
+ MH_SEND_Chat(msg, NET_CHAT_SYSTEM)
+ else if MKind = 1 then
+ MH_SEND_GameEvent(NET_EV_BIGTEXT, MTime, msg);
+ end;
+ end;
+ end;
+end;
+
+function tr_ShotAimCheck(var Trigger: TTrigger; Obj: PObj): Boolean;
+begin
+ result := false;
+ with Trigger do
+ begin
+ if TriggerType <> TRIGGER_SHOT then
+ Exit;
+ Result := (Data.ShotAim and TRIGGER_SHOT_AIM_ALLMAP > 0)
+ or g_Obj_Collide(X, Y, Width, Height, Obj);
+ if Result and (Data.ShotAim and TRIGGER_SHOT_AIM_TRACE > 0) then
+ Result := g_TraceVector(Data.ShotPos.X,
+ Data.ShotPos.Y,
+ Obj^.X + Obj^.Rect.X + (Obj^.Rect.Width div 2),
+ Obj^.Y + Obj^.Rect.Y + (Obj^.Rect.Height div 2));
+ end;
+end;
+
function ActivateTrigger(var Trigger: TTrigger; actType: Byte): Boolean;
var
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;
Anim: TAnimation;
UIDType: Byte;
TargetUID: Word;
- msg: string;
+ it: PItem;
+ mon: TMonster;
+
+ function monsShotTarget (mon: TMonster): Boolean;
+ begin
+ result := false; // don't stop
+ if 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 (mon: TMonster): Boolean;
+ begin
+ result := false; // don't stop
+ if 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 (mon: TMonster): Boolean;
+ begin
+ result := false; // don't stop
+ if 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
TRIGGER_TELEPORT:
begin
- case g_GetUIDType(ActivateUID) of
- UID_PLAYER:
- begin
- p := g_Player_Get(ActivateUID);
- if p = nil then
- Exit;
-
- if Data.d2d_teleport then
- begin
- if p.TeleportTo(Data.TargetPoint.X-(p.Obj.Rect.Width div 2),
- Data.TargetPoint.Y-p.Obj.Rect.Height,
- Data.silent_teleport,
- Data.TlpDir) then
- Result := True;
- end
- else
- if p.TeleportTo(Data.TargetPoint.X,
- Data.TargetPoint.Y,
- Data.silent_teleport,
- Data.TlpDir) then
- Result := True;
- end;
-
- UID_MONSTER:
- begin
- m := g_Monsters_Get(ActivateUID);
- if m = nil then
- Exit;
-
- if Data.d2d_teleport then
- begin
- if m.TeleportTo(Data.TargetPoint.X-(m.Obj.Rect.Width div 2),
- Data.TargetPoint.Y-m.Obj.Rect.Height,
- Data.silent_teleport,
- Data.TlpDir) then
- Result := True;
- end
- else
- if m.TeleportTo(Data.TargetPoint.X,
- Data.TargetPoint.Y,
- Data.silent_teleport,
- Data.TlpDir) then
- Result := True;
- end;
- end;
-
+ Result := tr_Teleport(ActivateUID,
+ Data.TargetPoint.X, Data.TargetPoint.Y,
+ Data.TlpDir, Data.silent_teleport,
+ Data.d2d_teleport);
TimeOut := 0;
end;
TRIGGER_OPENDOOR:
begin
- Result := OpenDoor(Data.PanelID, Data.NoSound, Data.d2d_doors);
+ Result := tr_OpenDoor(Data.PanelID, Data.NoSound, Data.d2d_doors);
TimeOut := 0;
end;
TRIGGER_CLOSEDOOR:
begin
- Result := CloseDoor(Data.PanelID, Data.NoSound, Data.d2d_doors);
+ Result := tr_CloseDoor(Data.PanelID, Data.NoSound, Data.d2d_doors);
TimeOut := 0;
end;
begin
if gWalls[Data.PanelID].Enabled then
begin
- Result := OpenDoor(Data.PanelID, Data.NoSound, Data.d2d_doors);
+ Result := tr_OpenDoor(Data.PanelID, Data.NoSound, Data.d2d_doors);
if TriggerType = TRIGGER_DOOR5 then
DoorTime := 180;
end
else
- Result := CloseDoor(Data.PanelID, Data.NoSound, Data.d2d_doors);
+ Result := tr_CloseDoor(Data.PanelID, Data.NoSound, Data.d2d_doors);
if Result then
TimeOut := 18;
TRIGGER_CLOSETRAP, TRIGGER_TRAP:
begin
- CloseTrap(Data.PanelID, Data.NoSound, Data.d2d_doors);
+ tr_CloseTrap(Data.PanelID, Data.NoSound, Data.d2d_doors);
if TriggerType = TRIGGER_TRAP then
begin
TRIGGER_LIFTUP:
begin
- Result := SetLift(Data.PanelID, 0, Data.NoSound, Data.d2d_doors);
+ Result := tr_SetLift(Data.PanelID, 0, Data.NoSound, Data.d2d_doors);
TimeOut := 0;
if (not Data.NoSound) and Result then begin
TRIGGER_LIFTDOWN:
begin
- Result := SetLift(Data.PanelID, 1, Data.NoSound, Data.d2d_doors);
+ Result := tr_SetLift(Data.PanelID, 1, Data.NoSound, Data.d2d_doors);
TimeOut := 0;
if (not Data.NoSound) and Result then begin
TRIGGER_LIFT:
begin
- Result := SetLift(Data.PanelID, 3, Data.NoSound, Data.d2d_doors);
+ Result := tr_SetLift(Data.PanelID, 3, Data.NoSound, Data.d2d_doors);
if Result then
begin
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;
+ mon.MonsterBehaviour := Data.MonBehav;
+ mon.FNoRespawn := True;
+ if g_Game_IsNet then
+ MH_SEND_MonsterSpawn(mon.UID);
// Èäåì èñêàòü öåëü, åñëè íàäî:
if Data.MonActive then
- gMonsters[i].WakeUp();
- gMonsters[i].FNoRespawn := True;
+ 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 g_Game_IsNet then
- MH_SEND_MonsterSpawn(gMonsters[i].UID);
end;
if g_Game_IsNet then
begin
if Data.ItemMax > 0 then
begin
- gItems[iid].SpawnTrigger := ID;
+ it := g_Items_ByIdx(iid);
+ it.SpawnTrigger := ID;
Inc(SpawnedCount);
end;
case Data.ItemEffect of
EFFECT_TELEPORT: begin
+ it := g_Items_ByIdx(iid);
if g_Frames_Get(FramesID, 'FRAMES_TELEPORT') then
begin
Anim := TAnimation.Create(FramesID, False, 3);
g_Sound_PlayExAt('SOUND_GAME_TELEPORT', Data.ItemPos.X, Data.ItemPos.Y);
- g_GFX_OnceAnim(gItems[iid].Obj.X+gItems[iid].Obj.Rect.X+(gItems[iid].Obj.Rect.Width div 2)-32,
- gItems[iid].Obj.Y+gItems[iid].Obj.Rect.Y+(gItems[iid].Obj.Rect.Height div 2)-32, Anim);
+ g_GFX_OnceAnim(it.Obj.X+it.Obj.Rect.X+(it.Obj.Rect.Width div 2)-32,
+ it.Obj.Y+it.Obj.Rect.Y+(it.Obj.Rect.Height div 2)-32, Anim);
Anim.Free();
end;
if g_Game_IsServer and g_Game_IsNet then
- MH_SEND_Effect(gItems[iid].Obj.X+gItems[iid].Obj.Rect.X+(gItems[iid].Obj.Rect.Width div 2)-32,
- gItems[iid].Obj.Y+gItems[iid].Obj.Rect.Y+(gItems[iid].Obj.Rect.Height div 2)-32, 1,
+ MH_SEND_Effect(it.Obj.X+it.Obj.Rect.X+(it.Obj.Rect.Width div 2)-32,
+ it.Obj.Y+it.Obj.Rect.Y+(it.Obj.Rect.Height div 2)-32, 1,
NET_GFX_TELE);
end;
EFFECT_RESPAWN: begin
+ it := g_Items_ByIdx(iid);
if g_Frames_Get(FramesID, 'FRAMES_ITEM_RESPAWN') then
begin
Anim := TAnimation.Create(FramesID, False, 4);
g_Sound_PlayExAt('SOUND_ITEM_RESPAWNITEM', Data.ItemPos.X, Data.ItemPos.Y);
- g_GFX_OnceAnim(gItems[iid].Obj.X+gItems[iid].Obj.Rect.X+(gItems[iid].Obj.Rect.Width div 2)-16,
- gItems[iid].Obj.Y+gItems[iid].Obj.Rect.Y+(gItems[iid].Obj.Rect.Height div 2)-16, Anim);
+ g_GFX_OnceAnim(it.Obj.X+it.Obj.Rect.X+(it.Obj.Rect.Width div 2)-16,
+ it.Obj.Y+it.Obj.Rect.Y+(it.Obj.Rect.Height div 2)-16, Anim);
Anim.Free();
end;
if g_Game_IsServer and g_Game_IsNet then
- MH_SEND_Effect(gItems[iid].Obj.X+gItems[iid].Obj.Rect.X+(gItems[iid].Obj.Rect.Width div 2)-16,
- gItems[iid].Obj.Y+gItems[iid].Obj.Rect.Y+(gItems[iid].Obj.Rect.Height div 2)-16, 1,
+ MH_SEND_Effect(it.Obj.X+it.Obj.Rect.X+(it.Obj.Rect.Width div 2)-16,
+ it.Obj.Y+it.Obj.Rect.Y+(it.Obj.Rect.Height div 2)-16, 1,
NET_GFX_RESPAWN);
end;
EFFECT_FIRE: begin
+ it := g_Items_ByIdx(iid);
if g_Frames_Get(FramesID, 'FRAMES_FIRE') then
begin
Anim := TAnimation.Create(FramesID, False, 4);
g_Sound_PlayExAt('SOUND_FIRE', Data.ItemPos.X, Data.ItemPos.Y);
- g_GFX_OnceAnim(gItems[iid].Obj.X+gItems[iid].Obj.Rect.X+(gItems[iid].Obj.Rect.Width div 2)-32,
- gItems[iid].Obj.Y+gItems[iid].Obj.Rect.Y+gItems[iid].Obj.Rect.Height-128, Anim);
+ g_GFX_OnceAnim(it.Obj.X+it.Obj.Rect.X+(it.Obj.Rect.Width div 2)-32,
+ it.Obj.Y+it.Obj.Rect.Y+it.Obj.Rect.Height-128, Anim);
Anim.Free();
end;
if g_Game_IsServer and g_Game_IsNet then
- MH_SEND_Effect(gItems[iid].Obj.X+gItems[iid].Obj.Rect.X+(gItems[iid].Obj.Rect.Width div 2)-32,
- gItems[iid].Obj.Y+gItems[iid].Obj.Rect.Y+gItems[iid].Obj.Rect.Height-128, 1,
+ MH_SEND_Effect(it.Obj.X+it.Obj.Rect.X+(it.Obj.Rect.Width div 2)-32,
+ it.Obj.Y+it.Obj.Rect.Y+it.Obj.Rect.Height-128, 1,
NET_GFX_FIRE);
end;
end;
TRIGGER_PUSH:
begin
- case g_GetUIDType(ActivateUID) of
- UID_PLAYER:
- begin
- p := g_Player_Get(ActivateUID);
- if p = nil then
- Exit;
-
- if Data.ResetVel then
- begin
- p.GameVelX := 0;
- p.GameVelY := 0;
- p.GameAccelX := 0;
- p.GameAccelY := 0;
- end;
-
- pAngle := -DegToRad(Data.PushAngle);
- p.Push(Floor(Cos(pAngle)*Data.PushForce),
- Floor(Sin(pAngle)*Data.PushForce));
- end;
-
- UID_MONSTER:
- begin
- m := g_Monsters_Get(ActivateUID);
- if m = nil then
- Exit;
- if Data.ResetVel then
- begin
- m.GameVelX := 0;
- m.GameVelY := 0;
- m.GameAccelX := 0;
- m.GameAccelY := 0;
- end;
-
- pAngle := -DegToRad(Data.PushAngle);
- m.Push(Floor(Cos(pAngle)*Data.PushForce),
- Floor(Sin(pAngle)*Data.PushForce));
- end;
- end;
-
+ pAngle := -DegToRad(Data.PushAngle);
+ Result := tr_Push(ActivateUID,
+ Floor(Cos(pAngle)*Data.PushForce),
+ Floor(Sin(pAngle)*Data.PushForce),
+ Data.ResetVel);
TimeOut := 0;
- Result := True;
end;
TRIGGER_SCORE:
TRIGGER_MESSAGE:
begin
- msg := b_Text_Format(Data.MessageText);
- case Data.MessageSendTo of
- 0: // activator
- begin
- if g_GetUIDType(ActivateUID) = UID_PLAYER then
- begin
- if g_Game_IsWatchedPlayer(ActivateUID) then
- begin
- if Data.MessageKind = 0 then
- g_Console_Add(msg, True)
- else if Data.MessageKind = 1 then
- g_Game_Message(msg, Data.MessageTime);
- end
- else
- begin
- p := g_Player_Get(ActivateUID);
- if g_Game_IsNet and (p.FClientID >= 0) then
- if Data.MessageKind = 0 then
- MH_SEND_Chat(msg, NET_CHAT_SYSTEM, p.FClientID)
- else if Data.MessageKind = 1 then
- MH_SEND_GameEvent(NET_EV_BIGTEXT, Data.MessageTime, msg, p.FClientID);
- end;
- end;
- end;
-
- 1: // activator's team
- begin
- if g_GetUIDType(ActivateUID) = UID_PLAYER then
- begin
- p := g_Player_Get(ActivateUID);
- if g_Game_IsWatchedTeam(p.Team) then
- if Data.MessageKind = 0 then
- g_Console_Add(msg, True)
- else if Data.MessageKind = 1 then
- g_Game_Message(msg, Data.MessageTime);
-
- if g_Game_IsNet then
- begin
- for i := Low(gPlayers) to High(gPlayers) do
- if (gPlayers[i].Team = p.Team) and (gPlayers[i].FClientID >= 0) then
- if Data.MessageKind = 0 then
- MH_SEND_Chat(msg, NET_CHAT_SYSTEM, gPlayers[i].FClientID)
- else if Data.MessageKind = 1 then
- MH_SEND_GameEvent(NET_EV_BIGTEXT, Data.MessageTime, msg, gPlayers[i].FClientID);
- end;
- end;
- end;
-
- 2: // activator's enemy team
- begin
- if g_GetUIDType(ActivateUID) = UID_PLAYER then
- begin
- p := g_Player_Get(ActivateUID);
- if g_Game_IsWatchedTeam(p.Team) then
- if Data.MessageKind = 0 then
- g_Console_Add(msg, True)
- else if Data.MessageKind = 1 then
- g_Game_Message(msg, Data.MessageTime);
-
- if g_Game_IsNet then
- begin
- for i := Low(gPlayers) to High(gPlayers) do
- if (gPlayers[i].Team <> p.Team) and (gPlayers[i].FClientID >= 0) then
- if Data.MessageKind = 0 then
- MH_SEND_Chat(msg, NET_CHAT_SYSTEM, gPlayers[i].FClientID)
- else if Data.MessageKind = 1 then
- MH_SEND_GameEvent(NET_EV_BIGTEXT, Data.MessageTime, msg, gPlayers[i].FClientID);
- end;
- end;
- end;
-
- 3: // red team
- begin
- if g_Game_IsWatchedTeam(TEAM_RED) then
- if Data.MessageKind = 0 then
- g_Console_Add(msg, True)
- else if Data.MessageKind = 1 then
- g_Game_Message(msg, Data.MessageTime);
-
- if g_Game_IsNet then
- begin
- for i := Low(gPlayers) to High(gPlayers) do
- if (gPlayers[i].Team = TEAM_RED) and (gPlayers[i].FClientID >= 0) then
- if Data.MessageKind = 0 then
- MH_SEND_Chat(msg, NET_CHAT_SYSTEM, gPlayers[i].FClientID)
- else if Data.MessageKind = 1 then
- MH_SEND_GameEvent(NET_EV_BIGTEXT, Data.MessageTime, msg, gPlayers[i].FClientID);
- end;
- end;
-
- 4: // blue team
- begin
- if g_Game_IsWatchedTeam(TEAM_BLUE) then
- if Data.MessageKind = 0 then
- g_Console_Add(msg, True)
- else if Data.MessageKind = 1 then
- g_Game_Message(msg, Data.MessageTime);
-
- if g_Game_IsNet then
- begin
- for i := Low(gPlayers) to High(gPlayers) do
- if (gPlayers[i].Team = TEAM_BLUE) and (gPlayers[i].FClientID >= 0) then
- if Data.MessageKind = 0 then
- MH_SEND_Chat(msg, NET_CHAT_SYSTEM, gPlayers[i].FClientID)
- else if Data.MessageKind = 1 then
- MH_SEND_GameEvent(NET_EV_BIGTEXT, Data.MessageTime, msg, gPlayers[i].FClientID);
- end;
- end;
-
- 5: // everyone
- begin
- if Data.MessageKind = 0 then
- g_Console_Add(msg, True)
- else if Data.MessageKind = 1 then
- g_Game_Message(msg, Data.MessageTime);
-
- if g_Game_IsNet then
- begin
- if Data.MessageKind = 0 then
- MH_SEND_Chat(msg, NET_CHAT_SYSTEM)
- else if Data.MessageKind = 1 then
- MH_SEND_GameEvent(NET_EV_BIGTEXT, Data.MessageTime, msg);
- end;
- end;
- end;
+ Result := tr_Message(Data.MessageKind, Data.MessageText,
+ Data.MessageSendTo, Data.MessageTime,
+ ActivateUID);
TimeOut := 18;
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
UID_MONSTER:
begin
- m := g_Monsters_Get(ActivateUID);
+ m := g_Monsters_ByUID(ActivateUID);
if m = nil then
Exit;
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;
if ShotSightTime > 0 then
Exit;
+ // put this at the beginning so it doesn't trigger itself
+ TimeOut := Data.ShotWait + 1;
+
wx := Data.ShotPos.X;
wy := Data.ShotPos.Y;
pAngle := -DegToRad(Data.ShotAngle);
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
- (Data.ShotAllMap or g_Obj_Collide(X, Y, Width, Height, @(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;
+ //TODO: accelerate this!
+ g_Mons_ForEachAlive(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
- (Data.ShotAllMap or g_Obj_Collide(X, Y, Width, Height, @(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
- (Data.ShotAllMap or g_Obj_Collide(X, Y, Width, Height, @(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
- (Data.ShotAllMap or g_Obj_Collide(X, Y, Width, Height, @(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
- (Data.ShotAllMap or g_Obj_Collide(X, Y, Width, Height, @(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;
+ //TODO: accelerate this!
+ g_Mons_ForEachAlive(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
- (Data.ShotAllMap or g_Obj_Collide(X, Y, Width, Height, @(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
- (Data.ShotAllMap or g_Obj_Collide(X, Y, Width, Height, @(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
- (Data.ShotAllMap or g_Obj_Collide(X, Y, Width, Height, @(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
+ begin
+ //TODO: accelerate this!
+ g_Mons_ForEachAlive(monShotTargetPlrMon);
+ end;
end;
- else TargetUID := ActivateUID;
+ else begin
+ if (Data.ShotTarget <> TRIGGER_SHOT_TARGET_NONE) or
+ (Data.ShotType <> TRIGGER_SHOT_REV) then
+ TargetUID := ActivateUID;
+ end;
end;
- if (Data.ShotTarget = TRIGGER_SHOT_TARGET_NONE) or (TargetUID > 0) then
+ if (Data.ShotTarget = TRIGGER_SHOT_TARGET_NONE) or (TargetUID > 0) or
+ ((Data.ShotTarget > TRIGGER_SHOT_TARGET_NONE) and (TargetUID = 0)) then
begin
Result := True;
if (Data.ShotIntSight = 0) or
end;
end;
end;
-
- TimeOut := Data.ShotWait + 1;
end;
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:
if Data.FXSpreadR > 0 then xd := xd + Random(Data.FXSpreadR + 1);
if Data.FXSpreadU > 0 then yd := yd - Random(Data.FXSpreadU + 1);
if Data.FXSpreadD > 0 then yd := yd + Random(Data.FXSpreadD + 1);
- MakeEffect(wx, wy, xd, yd,
+ 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;
-
- TRIGGER_SCRIPT:
- begin
- g_Scripts_ProcExec(Data.SCRProc, [ID, ActivateUID, actType, Data.SCRArg], 'map');
- TimeOut := 0;
- Result := True;
- end;
end;
end;
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);
+ end;
+
begin
if gTriggers = nil then
Exit;
// Òðèããåð "Ëîâóøêà" - ïîðà îòêðûâàòü:
if (TriggerType = TRIGGER_TRAP) and (DoorTime = 0) and (Data.PanelID <> -1) then
begin
- OpenDoor(Data.PanelID, Data.NoSound, Data.d2d_doors);
+ tr_OpenDoor(Data.PanelID, Data.NoSound, Data.d2d_doors);
DoorTime := -1;
end;
if gWalls[Data.PanelID].Enabled then
DoorTime := -1
else // Ïîêà îòêðûòà - çàêðûâàåì
- if CloseDoor(Data.PanelID, Data.NoSound, Data.d2d_doors) then
+ if tr_CloseDoor(Data.PanelID, Data.NoSound, Data.d2d_doors) then
DoorTime := -1;
end;
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);
+ //Alive?!
+ g_Mons_ForEachAt(gTriggers[a].X, gTriggers[a].Y, gTriggers[a].Width, gTriggers[a].Height, monsNear);
+ end;
- // "Ìîíñòðîâ íåò":
+ // "Ìîíñòðîâ íåò"
if ByteBool(ActivateType and ACTIVATE_NOMONSTER) and
(TimeOut = 0) and (Keys = 0) then
- if not g_CollideMonster(X, Y, Width, Height) then
+ if not g_Mons_IsAnyAliveAt(X, Y, Width, Height) then
begin
gTriggers[a].ActivateUID := 0;
ActivateTrigger(gTriggers[a], ACTIVATE_NOMONSTER);
end;
end;
-procedure g_Triggers_Press(ID: DWORD; ActivateType: Byte);
+procedure g_Triggers_Press(ID: DWORD; ActivateType: Byte; ActivateUID: Word = 0);
begin
- gTriggers[ID].ActivateUID := 0;
+ gTriggers[ID].ActivateUID := ActivateUID;
ActivateTrigger(gTriggers[ID], ActivateType);
end;
end;
end;
-procedure g_Triggers_PressC(CX, CY: Integer; Radius: Word; UID: Word; ActivateType: Byte);
+procedure g_Triggers_PressC(CX, CY: Integer; Radius: Word; UID: Word; ActivateType: Byte; IgnoreTrigger: Integer = -1);
var
a: Integer;
k: Byte;
rsq := Radius * Radius;
for a := 0 to High(gTriggers) do
- if (gTriggers[a].TriggerType <> TRIGGER_NONE) and
+ if (gTriggers[a].ID <> DWORD(IgnoreTrigger)) and
+ (gTriggers[a].TriggerType <> TRIGGER_NONE) and
(gTriggers[a].TimeOut = 0) and
((gTriggers[a].Keys and k) = gTriggers[a].Keys) and
ByteBool(gTriggers[a].ActivateType and ActivateType) then
(TriggerType = TRIGGER_DOOR5) or
(TriggerType = TRIGGER_DOOR) then
begin
- OpenDoor(Data.PanelID, True, Data.d2d_doors);
+ tr_OpenDoor(Data.PanelID, True, Data.d2d_doors);
if TriggerType = TRIGGER_DOOR5 then DoorTime := 180;
b := True;
end;