X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;ds=sidebyside;f=src%2Fgame%2Fg_triggers.pas;h=a1183e8e6899aacf51d23705851c21330fbdbcb1;hb=2b647061c5ce08e02c046c3ef8e0a31917cc28f3;hp=6748a005098b7874218adc0e15af4fcd3fa5a631;hpb=88ce644db1b40111bdb380f4357fa59bdb5173be;p=d2df-sdl.git diff --git a/src/game/g_triggers.pas b/src/game/g_triggers.pas index 6748a00..a1183e8 100644 --- a/src/game/g_triggers.pas +++ b/src/game/g_triggers.pas @@ -1,17 +1,35 @@ +(* Copyright (C) DooM 2D:Forever Developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *) +{$INCLUDE ../shared/a_modes.inc} unit g_triggers; interface uses - MAPSTRUCT, e_graphics, MAPDEF, g_basic, g_sound, - BinEditor; + MAPDEF, e_graphics, g_basic, g_sound, + BinEditor, xdynrec; type TActivator = record UID: Word; TimeOut: Word; end; + PTrigger = ^TTrigger; TTrigger = record + public ID: DWORD; ClientID: DWORD; TriggerType: Byte; @@ -44,22 +62,47 @@ type ShotAmmoCount: Word; ShotReloadTime: Integer; - Data: TTriggerData; + mapId: AnsiString; // trigger id, from map + mapIndex: Integer; // index in fields['trigger'], used in save/load + //trigShotPanelId: Integer; + trigPanelId: Integer; + + //TrigData: TTriggerData; + trigData: TDynRecord; // triggerdata; owned by trigger + + public + function trigCenter (): TDFPoint; inline; + + public + property trigShotPanelId: Integer read trigPanelId write trigPanelId; end; -function g_Triggers_Create(Trigger: TTrigger): DWORD; +function g_Triggers_Create(Trigger: TTrigger; forceInternalIndex: Integer=-1): 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; @@ -71,38 +114,44 @@ implementation uses g_player, g_map, Math, g_gfx, g_game, g_textures, g_console, g_monsters, g_items, g_phys, g_weapons, - WADEDITOR, g_main, SysUtils, e_log, g_language, - g_options, g_net, g_netmsg; + wadreader, g_main, SysUtils, e_log, g_language, + g_options, g_net, g_netmsg, utils, xparser; const - TRIGGER_SIGNATURE = $52475254; // 'TRGR' + TRIGGER_SIGNATURE = $58475254; // 'TRGX' TRAP_DAMAGE = 1000; + +function TTrigger.trigCenter (): TDFPoint; inline; +begin + result := TDFPoint.Create(x+width div 2, y+height div 2); +end; + + function FindTrigger(): DWORD; var i: Integer; begin - if gTriggers <> nil then - for i := 0 to High(gTriggers) do - if gTriggers[i].TriggerType = TRIGGER_NONE then - begin - Result := i; - Exit; - end; + for i := 0 to High(gTriggers) do + begin + if gTriggers[i].TriggerType = TRIGGER_NONE then begin result := i; exit; end; + end; - if gTriggers = nil then + if (gTriggers = nil) then begin SetLength(gTriggers, 8); - Result := 0; + result := 0; end else begin - Result := High(gTriggers) + 1; - SetLength(gTriggers, Length(gTriggers) + 8); + result := Length(gTriggers); + SetLength(gTriggers, result+8); + for i := result to High(gTriggers) do gTriggers[i].TriggerType := TRIGGER_NONE; 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 @@ -115,7 +164,7 @@ 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 @@ -152,7 +201,7 @@ 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 @@ -177,22 +226,36 @@ begin 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 @@ -202,11 +265,8 @@ 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; @@ -219,30 +279,41 @@ begin 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 @@ -251,18 +322,23 @@ begin 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 @@ -325,7 +401,7 @@ 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 @@ -399,195 +475,207 @@ 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 (trigData.trigShotAmmo = 0) or + ((trigData.trigShotAmmo > 0) and (ShotAmmoCount > 0)) then + begin + if (trigShotPanelID <> -1) and (ShotPanelTime = 0) then + begin + g_Map_SwitchTexture(ShotPanelType, trigShotPanelID); + 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 trigData.trigShotIntSight > 0 then + ShotSightTimeout := 180; // ~= 5 ñåêóíä + + if ShotAmmoCount > 0 then Dec(ShotAmmoCount); + + dx := dx + Random(trigData.trigShotAccuracy) - Random(trigData.trigShotAccuracy); + dy := dy + Random(trigData.trigShotAccuracy) - Random(trigData.trigShotAccuracy); - if Data.ShotSound then - g_Sound_PlayExAt(snd, wx, wy); + tr_SpawnShot(trigData.trigShotType, wx, wy, dx, dy, trigData.trigShotSound, TargetUID); end else - if (Data.ShotIntReload > 0) and (ShotReloadTime = 0) then - ShotReloadTime := Data.ShotIntReload; // òèêîâ íà ïåðåçàðÿäêó ïóøêè + if (trigData.trigShotIntReload > 0) and (ShotReloadTime = 0) then + ShotReloadTime := trigData.trigShotIntReload; // òèêîâ íà ïåðåçàðÿäêó ïóøêè 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; @@ -657,12 +745,256 @@ begin 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 := (trigData.trigShotAim and TRIGGER_SHOT_AIM_ALLMAP > 0) + or g_Obj_Collide(X, Y, Width, Height, Obj); + if Result and (trigData.trigShotAim and TRIGGER_SHOT_AIM_TRACE > 0) then + Result := g_TraceVector(trigData.trigShotPos.X, + trigData.trigShotPos.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; @@ -670,7 +1002,45 @@ var 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 @@ -695,7 +1065,7 @@ begin g_Sound_PlayEx('SOUND_GAME_SWITCH0'); if g_Game_IsNet then MH_SEND_Sound(X, Y, 'SOUND_GAME_SWITCH0'); gExitByTrigger := True; - g_Game_ExitLevel(Data.MapName); + g_Game_ExitLevel(trigData.trigMapName); TimeOut := 18; Result := True; @@ -704,80 +1074,38 @@ begin 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, + trigData.trigTargetPoint.X, trigData.trigTargetPoint.Y, + trigData.trigTlpDir, trigData.trigsilent_teleport, + trigData.trigd2d_teleport); TimeOut := 0; end; TRIGGER_OPENDOOR: begin - Result := OpenDoor(Data.PanelID, Data.NoSound, Data.d2d_doors); + Result := tr_OpenDoor(trigPanelID, trigData.trigNoSound, trigData.trigd2d_doors); TimeOut := 0; end; TRIGGER_CLOSEDOOR: begin - Result := CloseDoor(Data.PanelID, Data.NoSound, Data.d2d_doors); + Result := tr_CloseDoor(trigPanelID, trigData.trigNoSound, trigData.trigd2d_doors); TimeOut := 0; end; TRIGGER_DOOR, TRIGGER_DOOR5: begin - if Data.PanelID <> -1 then + if trigPanelID <> -1 then begin - if gWalls[Data.PanelID].Enabled then + if gWalls[trigPanelID].Enabled then begin - Result := OpenDoor(Data.PanelID, Data.NoSound, Data.d2d_doors); + Result := tr_OpenDoor(trigPanelID, trigData.trigNoSound, trigData.trigd2d_doors); if TriggerType = TRIGGER_DOOR5 then DoorTime := 180; end else - Result := CloseDoor(Data.PanelID, Data.NoSound, Data.d2d_doors); + Result := tr_CloseDoor(trigPanelID, trigData.trigNoSound, trigData.trigd2d_doors); if Result then TimeOut := 18; @@ -786,7 +1114,7 @@ begin TRIGGER_CLOSETRAP, TRIGGER_TRAP: begin - CloseTrap(Data.PanelID, Data.NoSound, Data.d2d_doors); + tr_CloseTrap(trigPanelID, trigData.trigNoSound, trigData.trigd2d_doors); if TriggerType = TRIGGER_TRAP then begin @@ -805,9 +1133,9 @@ begin TRIGGER_PRESS, TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF: begin PressCount := PressCount + 1; - + if PressTime = -1 then - PressTime := Data.Wait; + PressTime := trigData.trigWait; if coolDown then TimeOut := 18 @@ -831,10 +1159,10 @@ begin TRIGGER_LIFTUP: begin - Result := SetLift(Data.PanelID, 0, Data.NoSound, Data.d2d_doors); + Result := tr_SetLift(trigPanelID, 0, trigData.trigNoSound, trigData.trigd2d_doors); TimeOut := 0; - if (not Data.NoSound) and Result then begin + if (not trigData.trigNoSound) and Result then begin g_Sound_PlayExAt('SOUND_GAME_SWITCH0', X + (Width div 2), Y + (Height div 2)); @@ -847,10 +1175,10 @@ begin TRIGGER_LIFTDOWN: begin - Result := SetLift(Data.PanelID, 1, Data.NoSound, Data.d2d_doors); + Result := tr_SetLift(trigPanelID, 1, trigData.trigNoSound, trigData.trigd2d_doors); TimeOut := 0; - if (not Data.NoSound) and Result then begin + if (not trigData.trigNoSound) and Result then begin g_Sound_PlayExAt('SOUND_GAME_SWITCH0', X + (Width div 2), Y + (Height div 2)); @@ -863,13 +1191,13 @@ begin TRIGGER_LIFT: begin - Result := SetLift(Data.PanelID, 3, Data.NoSound, Data.d2d_doors); + Result := tr_SetLift(trigPanelID, 3, trigData.trigNoSound, trigData.trigd2d_doors); if Result then begin TimeOut := 18; - if (not Data.NoSound) and Result then begin + if (not trigData.trigNoSound) and Result then begin g_Sound_PlayExAt('SOUND_GAME_SWITCH0', X + (Width div 2), Y + (Height div 2)); @@ -883,7 +1211,7 @@ begin TRIGGER_TEXTURE: begin - if ByteBool(Data.ActivateOnce) then + if trigData.trigActivateOnce then begin Enabled := False; TriggerType := TRIGGER_NONE; @@ -894,7 +1222,7 @@ begin else TimeOut := 0; - animonce := Data.AnimOnce; + animonce := trigData.trigAnimOnce; Result := True; end; @@ -902,17 +1230,17 @@ begin begin if Sound <> nil then begin - if Data.SoundSwitch and Sound.IsPlaying() then + if trigData.trigSoundSwitch and Sound.IsPlaying() then begin // Íóæíî âûêëþ÷èòü, åñëè èãðàë Sound.Stop(); SoundPlayCount := 0; Result := True; end else // (not Data.SoundSwitch) or (not Sound.IsPlaying()) - if (Data.PlayCount > 0) or (not Sound.IsPlaying()) then + if (trigData.trigPlayCount > 0) or (not Sound.IsPlaying()) then begin - if Data.PlayCount > 0 then - SoundPlayCount := Data.PlayCount + if trigData.trigPlayCount > 0 then + SoundPlayCount := trigData.trigPlayCount else // 0 - èãðàåì áåñêîíå÷íî SoundPlayCount := 1; Result := True; @@ -922,10 +1250,10 @@ begin end; TRIGGER_SPAWNMONSTER: - if (Data.MonType in [MONSTER_DEMON..MONSTER_MAN]) then + if (trigData.trigMonType in [MONSTER_DEMON..MONSTER_MAN]) then begin Result := False; - if (Data.MonDelay > 0) and (actType <> ACTIVATE_CUSTOM) then + if (trigData.trigMonDelay > 0) and (actType <> ACTIVATE_CUSTOM) then begin AutoSpawn := not AutoSpawn; SpawnCooldown := 0; @@ -933,92 +1261,91 @@ begin Result := True; end; - if ((Data.MonDelay = 0) and (actType <> ACTIVATE_CUSTOM)) - or ((Data.MonDelay > 0) and (actType = ACTIVATE_CUSTOM)) then - for k := 1 to Data.MonCount do + if ((trigData.trigMonDelay = 0) and (actType <> ACTIVATE_CUSTOM)) + or ((trigData.trigMonDelay > 0) and (actType = ACTIVATE_CUSTOM)) then + for k := 1 to trigData.trigMonCount do begin - if (actType = ACTIVATE_CUSTOM) and (Data.MonDelay > 0) then - SpawnCooldown := Data.MonDelay; - if (Data.MonMax > 0) and (SpawnedCount >= Data.MonMax) then + if (actType = ACTIVATE_CUSTOM) and (trigData.trigMonDelay > 0) then + SpawnCooldown := trigData.trigMonDelay; + if (trigData.trigMonMax > 0) and (SpawnedCount >= trigData.trigMonMax) then Break; - i := g_Monsters_Create(Data.MonType, - Data.MonPos.X, Data.MonPos.Y, - TDirection(Data.MonDir), True); + mon := g_Monsters_Create(trigData.trigMonType, + trigData.trigMonPos.X, trigData.trigMonPos.Y, + TDirection(trigData.trigMonDir), True); Result := True; // Çäîðîâüå: - if (Data.MonHealth > 0) then - gMonsters[i].SetHealth(Data.MonHealth); + if (trigData.trigMonHealth > 0) then + mon.SetHealth(trigData.trigMonHealth); // Óñòàíàâëèâàåì ïîâåäåíèå: - gMonsters[i].MonsterBehaviour := Data.MonBehav; + mon.MonsterBehaviour := trigData.trigMonBehav; + mon.FNoRespawn := True; + if g_Game_IsNet then + MH_SEND_MonsterSpawn(mon.UID); // Èäåì èñêàòü öåëü, åñëè íàäî: - if Data.MonActive then - gMonsters[i].WakeUp(); - gMonsters[i].FNoRespawn := True; + if trigData.trigMonActive then + mon.WakeUp(); - if Data.MonType <> MONSTER_BARREL then Inc(gTotalMonsters); + if trigData.trigMonType <> 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 + if trigData.trigMonMax > 0 then begin - gMonsters[i].SpawnTrigger := ID; + mon.SpawnTrigger := ID; Inc(SpawnedCount); end; - case Data.MonEffect of + case trigData.trigMonEffect of EFFECT_TELEPORT: begin if g_Frames_Get(FramesID, 'FRAMES_TELEPORT') then 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_Sound_PlayExAt('SOUND_GAME_TELEPORT', trigData.trigMonPos.X, trigData.trigMonPos.Y); + 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 if g_Frames_Get(FramesID, 'FRAMES_ITEM_RESPAWN') then 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_Sound_PlayExAt('SOUND_ITEM_RESPAWNITEM', trigData.trigMonPos.X, trigData.trigMonPos.Y); + 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 if g_Frames_Get(FramesID, 'FRAMES_FIRE') then 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_Sound_PlayExAt('SOUND_FIRE', trigData.trigMonPos.X, trigData.trigMonPos.Y); + 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 @@ -1036,10 +1363,10 @@ begin end; TRIGGER_SPAWNITEM: - if (Data.ItemType in [ITEM_MEDKIT_SMALL..ITEM_MAX]) then + if (trigData.trigItemType in [ITEM_MEDKIT_SMALL..ITEM_MAX]) then begin Result := False; - if (Data.ItemDelay > 0) and (actType <> ACTIVATE_CUSTOM) then + if (trigData.trigItemDelay > 0) and (actType <> ACTIVATE_CUSTOM) then begin AutoSpawn := not AutoSpawn; SpawnCooldown := 0; @@ -1047,69 +1374,73 @@ begin Result := True; end; - if ((Data.ItemDelay = 0) and (actType <> ACTIVATE_CUSTOM)) - or ((Data.ItemDelay > 0) and (actType = ACTIVATE_CUSTOM)) then - if (not Data.ItemOnlyDM) or + if ((trigData.trigItemDelay = 0) and (actType <> ACTIVATE_CUSTOM)) + or ((trigData.trigItemDelay > 0) and (actType = ACTIVATE_CUSTOM)) then + if (not trigData.trigItemOnlyDM) or (gGameSettings.GameMode in [GM_DM, GM_TDM, GM_CTF]) then - for k := 1 to Data.ItemCount do + for k := 1 to trigData.trigItemCount do begin - if (actType = ACTIVATE_CUSTOM) and (Data.ItemDelay > 0) then - SpawnCooldown := Data.ItemDelay; - if (Data.ItemMax > 0) and (SpawnedCount >= Data.ItemMax) then + if (actType = ACTIVATE_CUSTOM) and (trigData.trigItemDelay > 0) then + SpawnCooldown := trigData.trigItemDelay; + if (trigData.trigItemMax > 0) and (SpawnedCount >= trigData.trigItemMax) then Break; - iid := g_Items_Create(Data.ItemPos.X, Data.ItemPos.Y, - Data.ItemType, Data.ItemFalls, False, True); + iid := g_Items_Create(trigData.trigItemPos.X, trigData.trigItemPos.Y, + trigData.trigItemType, trigData.trigItemFalls, False, True); Result := True; - if Data.ItemMax > 0 then + if trigData.trigItemMax > 0 then begin - gItems[iid].SpawnTrigger := ID; + it := g_Items_ByIdx(iid); + it.SpawnTrigger := ID; Inc(SpawnedCount); end; - case Data.ItemEffect of + case trigData.trigItemEffect 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_Sound_PlayExAt('SOUND_GAME_TELEPORT', trigData.trigItemPos.X, trigData.trigItemPos.Y); + 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_Sound_PlayExAt('SOUND_ITEM_RESPAWNITEM', trigData.trigItemPos.X, trigData.trigItemPos.Y); + 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_Sound_PlayExAt('SOUND_FIRE', trigData.trigItemPos.X, trigData.trigItemPos.Y); + 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; @@ -1130,14 +1461,14 @@ begin TRIGGER_MUSIC: begin // Ìåíÿåì ìóçûêó, åñëè åñòü íà ÷òî: - if (Trigger.Data.MusicName <> '') then + if (Trigger.trigData.trigMusicName <> '') then begin - gMusic.SetByName(Trigger.Data.MusicName); + gMusic.SetByName(Trigger.trigData.trigMusicName); gMusic.SpecPause := True; gMusic.Play(); end; - if Trigger.Data.MusicAction = 1 then + if Trigger.trigData.trigMusicAction = 1 then begin // Âêëþ÷èòü if gMusic.SpecPause then // Áûëà íà ïàóçå => èãðàòü gMusic.SpecPause := False @@ -1160,153 +1491,118 @@ begin 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(trigData.trigPushAngle); + Result := tr_Push(ActivateUID, + Floor(Cos(pAngle)*trigData.trigPushForce), + Floor(Sin(pAngle)*trigData.trigPushForce), + trigData.trigResetVel); TimeOut := 0; - Result := True; end; TRIGGER_SCORE: begin Result := False; // Ïðèáàâèòü èëè îòíÿòü î÷êî - if (Data.ScoreAction in [0..1]) and (Data.ScoreCount > 0) then + if (trigData.trigScoreAction in [0..1]) and (trigData.trigScoreCount > 0) then begin // Ñâîåé èëè ÷óæîé êîìàíäå - if (Data.ScoreTeam in [0..1]) and (g_GetUIDType(ActivateUID) = UID_PLAYER) then + if (trigData.trigScoreTeam in [0..1]) and (g_GetUIDType(ActivateUID) = UID_PLAYER) then begin p := g_Player_Get(ActivateUID); - if ((Data.ScoreAction = 0) and (Data.ScoreTeam = 0) and (p.Team = TEAM_RED)) - or ((Data.ScoreAction = 0) and (Data.ScoreTeam = 1) and (p.Team = TEAM_BLUE)) then + if ((trigData.trigScoreAction = 0) and (trigData.trigScoreTeam = 0) and (p.Team = TEAM_RED)) + or ((trigData.trigScoreAction = 0) and (trigData.trigScoreTeam = 1) and (p.Team = TEAM_BLUE)) then begin - Inc(gTeamStat[TEAM_RED].Goals, Data.ScoreCount); // Red Scores + Inc(gTeamStat[TEAM_RED].Goals, trigData.trigScoreCount); // Red Scores - if Data.ScoreCon then - if Data.ScoreTeam = 0 then + if trigData.trigScoreCon then + if trigData.trigScoreTeam = 0 then begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_OWN], [p.Name, Data.ScoreCount, _lc[I_PLAYER_SCORE_TO_RED]]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_OWN], [p.Name, trigData.trigScoreCount, _lc[I_PLAYER_SCORE_TO_RED]]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (Data.ScoreCount shl 16), '+r'); + MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (trigData.trigScoreCount shl 16), '+r'); end else begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_ENEMY], [p.Name, Data.ScoreCount, _lc[I_PLAYER_SCORE_TO_RED]]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_ENEMY], [p.Name, trigData.trigScoreCount, _lc[I_PLAYER_SCORE_TO_RED]]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (Data.ScoreCount shl 16), '+re'); + MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (trigData.trigScoreCount shl 16), '+re'); end; - if Data.ScoreMsg then + if trigData.trigScoreMsg then begin g_Game_Message(Format(_lc[I_MESSAGE_SCORE_ADD], [AnsiUpperCase(_lc[I_GAME_TEAM_RED])]), 108); if g_Game_IsServer and g_Game_IsNet then MH_SEND_GameEvent(NET_EV_SCORE_MSG, TEAM_RED); end; end; - if ((Data.ScoreAction = 1) and (Data.ScoreTeam = 0) and (p.Team = TEAM_RED)) - or ((Data.ScoreAction = 1) and (Data.ScoreTeam = 1) and (p.Team = TEAM_BLUE)) then + if ((trigData.trigScoreAction = 1) and (trigData.trigScoreTeam = 0) and (p.Team = TEAM_RED)) + or ((trigData.trigScoreAction = 1) and (trigData.trigScoreTeam = 1) and (p.Team = TEAM_BLUE)) then begin - Dec(gTeamStat[TEAM_RED].Goals, Data.ScoreCount); // Red Fouls + Dec(gTeamStat[TEAM_RED].Goals, trigData.trigScoreCount); // Red Fouls - if Data.ScoreCon then - if Data.ScoreTeam = 0 then + if trigData.trigScoreCon then + if trigData.trigScoreTeam = 0 then begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_OWN], [p.Name, Data.ScoreCount, _lc[I_PLAYER_SCORE_TO_RED]]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_OWN], [p.Name, trigData.trigScoreCount, _lc[I_PLAYER_SCORE_TO_RED]]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (Data.ScoreCount shl 16), '-r'); + MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (trigData.trigScoreCount shl 16), '-r'); end else begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_ENEMY], [p.Name, Data.ScoreCount, _lc[I_PLAYER_SCORE_TO_RED]]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_ENEMY], [p.Name, trigData.trigScoreCount, _lc[I_PLAYER_SCORE_TO_RED]]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (Data.ScoreCount shl 16), '-re'); + MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (trigData.trigScoreCount shl 16), '-re'); end; - if Data.ScoreMsg then + if trigData.trigScoreMsg then begin g_Game_Message(Format(_lc[I_MESSAGE_SCORE_SUB], [AnsiUpperCase(_lc[I_GAME_TEAM_RED])]), 108); if g_Game_IsServer and g_Game_IsNet then MH_SEND_GameEvent(NET_EV_SCORE_MSG, -TEAM_RED); end; end; - if ((Data.ScoreAction = 0) and (Data.ScoreTeam = 0) and (p.Team = TEAM_BLUE)) - or ((Data.ScoreAction = 0) and (Data.ScoreTeam = 1) and (p.Team = TEAM_RED)) then + if ((trigData.trigScoreAction = 0) and (trigData.trigScoreTeam = 0) and (p.Team = TEAM_BLUE)) + or ((trigData.trigScoreAction = 0) and (trigData.trigScoreTeam = 1) and (p.Team = TEAM_RED)) then begin - Inc(gTeamStat[TEAM_BLUE].Goals, Data.ScoreCount); // Blue Scores + Inc(gTeamStat[TEAM_BLUE].Goals, trigData.trigScoreCount); // Blue Scores - if Data.ScoreCon then - if Data.ScoreTeam = 0 then + if trigData.trigScoreCon then + if trigData.trigScoreTeam = 0 then begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_OWN], [p.Name, Data.ScoreCount, _lc[I_PLAYER_SCORE_TO_BLUE]]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_OWN], [p.Name, trigData.trigScoreCount, _lc[I_PLAYER_SCORE_TO_BLUE]]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (Data.ScoreCount shl 16), '+b'); + MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (trigData.trigScoreCount shl 16), '+b'); end else begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_ENEMY], [p.Name, Data.ScoreCount, _lc[I_PLAYER_SCORE_TO_BLUE]]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_ENEMY], [p.Name, trigData.trigScoreCount, _lc[I_PLAYER_SCORE_TO_BLUE]]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (Data.ScoreCount shl 16), '+be'); + MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (trigData.trigScoreCount shl 16), '+be'); end; - if Data.ScoreMsg then + if trigData.trigScoreMsg then begin g_Game_Message(Format(_lc[I_MESSAGE_SCORE_ADD], [AnsiUpperCase(_lc[I_GAME_TEAM_BLUE])]), 108); if g_Game_IsServer and g_Game_IsNet then MH_SEND_GameEvent(NET_EV_SCORE_MSG, TEAM_BLUE); end; end; - if ((Data.ScoreAction = 1) and (Data.ScoreTeam = 0) and (p.Team = TEAM_BLUE)) - or ((Data.ScoreAction = 1) and (Data.ScoreTeam = 1) and (p.Team = TEAM_RED)) then + if ((trigData.trigScoreAction = 1) and (trigData.trigScoreTeam = 0) and (p.Team = TEAM_BLUE)) + or ((trigData.trigScoreAction = 1) and (trigData.trigScoreTeam = 1) and (p.Team = TEAM_RED)) then begin - Dec(gTeamStat[TEAM_BLUE].Goals, Data.ScoreCount); // Blue Fouls + Dec(gTeamStat[TEAM_BLUE].Goals, trigData.trigScoreCount); // Blue Fouls - if Data.ScoreCon then - if Data.ScoreTeam = 0 then + if trigData.trigScoreCon then + if trigData.trigScoreTeam = 0 then begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_OWN], [p.Name, Data.ScoreCount, _lc[I_PLAYER_SCORE_TO_BLUE]]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_OWN], [p.Name, trigData.trigScoreCount, _lc[I_PLAYER_SCORE_TO_BLUE]]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (Data.ScoreCount shl 16), '-b'); + MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (trigData.trigScoreCount shl 16), '-b'); end else begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_ENEMY], [p.Name, Data.ScoreCount, _lc[I_PLAYER_SCORE_TO_BLUE]]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_ENEMY], [p.Name, trigData.trigScoreCount, _lc[I_PLAYER_SCORE_TO_BLUE]]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (Data.ScoreCount shl 16), '-be'); + MH_SEND_GameEvent(NET_EV_SCORE, p.UID or (trigData.trigScoreCount shl 16), '-be'); end; - if Data.ScoreMsg then + if trigData.trigScoreMsg then begin g_Game_Message(Format(_lc[I_MESSAGE_SCORE_SUB], [AnsiUpperCase(_lc[I_GAME_TEAM_BLUE])]), 108); if g_Game_IsServer and g_Game_IsNet then @@ -1316,74 +1612,74 @@ begin Result := (p.Team = TEAM_RED) or (p.Team = TEAM_BLUE); end; // Êàêîé-òî êîíêðåòíîé êîìàíäå - if Data.ScoreTeam in [2..3] then + if trigData.trigScoreTeam in [2..3] then begin - if (Data.ScoreAction = 0) and (Data.ScoreTeam = 2) then + if (trigData.trigScoreAction = 0) and (trigData.trigScoreTeam = 2) then begin - Inc(gTeamStat[TEAM_RED].Goals, Data.ScoreCount); // Red Scores + Inc(gTeamStat[TEAM_RED].Goals, trigData.trigScoreCount); // Red Scores - if Data.ScoreCon then + if trigData.trigScoreCon then begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_TEAM], [_lc[I_PLAYER_SCORE_RED], Data.ScoreCount]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_TEAM], [_lc[I_PLAYER_SCORE_RED], trigData.trigScoreCount]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, Data.ScoreCount shl 16, '+tr'); + MH_SEND_GameEvent(NET_EV_SCORE, trigData.trigScoreCount shl 16, '+tr'); end; - if Data.ScoreMsg then + if trigData.trigScoreMsg then begin g_Game_Message(Format(_lc[I_MESSAGE_SCORE_ADD], [AnsiUpperCase(_lc[I_GAME_TEAM_RED])]), 108); if g_Game_IsServer and g_Game_IsNet then MH_SEND_GameEvent(NET_EV_SCORE_MSG, TEAM_RED); end; end; - if (Data.ScoreAction = 1) and (Data.ScoreTeam = 2) then + if (trigData.trigScoreAction = 1) and (trigData.trigScoreTeam = 2) then begin - Dec(gTeamStat[TEAM_RED].Goals, Data.ScoreCount); // Red Fouls + Dec(gTeamStat[TEAM_RED].Goals, trigData.trigScoreCount); // Red Fouls - if Data.ScoreCon then + if trigData.trigScoreCon then begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_TEAM], [_lc[I_PLAYER_SCORE_RED], Data.ScoreCount]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_TEAM], [_lc[I_PLAYER_SCORE_RED], trigData.trigScoreCount]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, Data.ScoreCount shl 16, '-tr'); + MH_SEND_GameEvent(NET_EV_SCORE, trigData.trigScoreCount shl 16, '-tr'); end; - if Data.ScoreMsg then + if trigData.trigScoreMsg then begin g_Game_Message(Format(_lc[I_MESSAGE_SCORE_SUB], [AnsiUpperCase(_lc[I_GAME_TEAM_RED])]), 108); if g_Game_IsServer and g_Game_IsNet then MH_SEND_GameEvent(NET_EV_SCORE_MSG, -TEAM_RED); end; end; - if (Data.ScoreAction = 0) and (Data.ScoreTeam = 3) then + if (trigData.trigScoreAction = 0) and (trigData.trigScoreTeam = 3) then begin - Inc(gTeamStat[TEAM_BLUE].Goals, Data.ScoreCount); // Blue Scores + Inc(gTeamStat[TEAM_BLUE].Goals, trigData.trigScoreCount); // Blue Scores - if Data.ScoreCon then + if trigData.trigScoreCon then begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_TEAM], [_lc[I_PLAYER_SCORE_BLUE], Data.ScoreCount]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_ADD_TEAM], [_lc[I_PLAYER_SCORE_BLUE], trigData.trigScoreCount]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, Data.ScoreCount shl 16, '+tb'); + MH_SEND_GameEvent(NET_EV_SCORE, trigData.trigScoreCount shl 16, '+tb'); end; - if Data.ScoreMsg then + if trigData.trigScoreMsg then begin g_Game_Message(Format(_lc[I_MESSAGE_SCORE_ADD], [AnsiUpperCase(_lc[I_GAME_TEAM_BLUE])]), 108); if g_Game_IsServer and g_Game_IsNet then MH_SEND_GameEvent(NET_EV_SCORE_MSG, TEAM_BLUE); end; end; - if (Data.ScoreAction = 1) and (Data.ScoreTeam = 3) then + if (trigData.trigScoreAction = 1) and (trigData.trigScoreTeam = 3) then begin - Dec(gTeamStat[TEAM_BLUE].Goals, Data.ScoreCount); // Blue Fouls + Dec(gTeamStat[TEAM_BLUE].Goals, trigData.trigScoreCount); // Blue Fouls - if Data.ScoreCon then + if trigData.trigScoreCon then begin - g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_TEAM], [_lc[I_PLAYER_SCORE_BLUE], Data.ScoreCount]), True); + g_Console_Add(Format(_lc[I_PLAYER_SCORE_SUB_TEAM], [_lc[I_PLAYER_SCORE_BLUE], trigData.trigScoreCount]), True); if g_Game_IsServer and g_Game_IsNet then - MH_SEND_GameEvent(NET_EV_SCORE, Data.ScoreCount shl 16, '-tb'); + MH_SEND_GameEvent(NET_EV_SCORE, trigData.trigScoreCount shl 16, '-tb'); end; - if Data.ScoreMsg then + if trigData.trigScoreMsg then begin g_Game_Message(Format(_lc[I_MESSAGE_SCORE_SUB], [AnsiUpperCase(_lc[I_GAME_TEAM_BLUE])]), 108); if g_Game_IsServer and g_Game_IsNet then @@ -1394,20 +1690,20 @@ begin end; end; // Âûèãðûø - if (Data.ScoreAction = 2) and (gGameSettings.GoalLimit > 0) then + if (trigData.trigScoreAction = 2) and (gGameSettings.GoalLimit > 0) then begin // Ñâîåé èëè ÷óæîé êîìàíäû - if (Data.ScoreTeam in [0..1]) and (g_GetUIDType(ActivateUID) = UID_PLAYER) then + if (trigData.trigScoreTeam in [0..1]) and (g_GetUIDType(ActivateUID) = UID_PLAYER) then begin p := g_Player_Get(ActivateUID); - if ((Data.ScoreTeam = 0) and (p.Team = TEAM_RED)) // Red Wins - or ((Data.ScoreTeam = 1) and (p.Team = TEAM_BLUE)) then + if ((trigData.trigScoreTeam = 0) and (p.Team = TEAM_RED)) // Red Wins + or ((trigData.trigScoreTeam = 1) and (p.Team = TEAM_BLUE)) then if gTeamStat[TEAM_RED].Goals < SmallInt(gGameSettings.GoalLimit) then begin gTeamStat[TEAM_RED].Goals := gGameSettings.GoalLimit; - if Data.ScoreCon then - if Data.ScoreTeam = 0 then + if trigData.trigScoreCon then + if trigData.trigScoreTeam = 0 then begin g_Console_Add(Format(_lc[I_PLAYER_SCORE_WIN_OWN], [p.Name, _lc[I_PLAYER_SCORE_TO_RED]]), True); if g_Game_IsServer and g_Game_IsNet then @@ -1421,14 +1717,14 @@ begin Result := True; end; - if ((Data.ScoreTeam = 0) and (p.Team = TEAM_BLUE)) // Blue Wins - or ((Data.ScoreTeam = 1) and (p.Team = TEAM_RED)) then + if ((trigData.trigScoreTeam = 0) and (p.Team = TEAM_BLUE)) // Blue Wins + or ((trigData.trigScoreTeam = 1) and (p.Team = TEAM_RED)) then if gTeamStat[TEAM_BLUE].Goals < SmallInt(gGameSettings.GoalLimit) then begin gTeamStat[TEAM_BLUE].Goals := gGameSettings.GoalLimit; - if Data.ScoreCon then - if Data.ScoreTeam = 0 then + if trigData.trigScoreCon then + if trigData.trigScoreTeam = 0 then begin g_Console_Add(Format(_lc[I_PLAYER_SCORE_WIN_OWN], [p.Name, _lc[I_PLAYER_SCORE_TO_BLUE]]), True); if g_Game_IsServer and g_Game_IsNet then @@ -1444,15 +1740,15 @@ begin end; end; // Êàêîé-òî êîíêðåòíîé êîìàíäû - if Data.ScoreTeam in [2..3] then + if trigData.trigScoreTeam in [2..3] then begin - if Data.ScoreTeam = 2 then // Red Wins + if trigData.trigScoreTeam = 2 then // Red Wins if gTeamStat[TEAM_RED].Goals < SmallInt(gGameSettings.GoalLimit) then begin gTeamStat[TEAM_RED].Goals := gGameSettings.GoalLimit; Result := True; end; - if Data.ScoreTeam = 3 then // Blue Wins + if trigData.trigScoreTeam = 3 then // Blue Wins if gTeamStat[TEAM_BLUE].Goals < SmallInt(gGameSettings.GoalLimit) then begin gTeamStat[TEAM_BLUE].Goals := gGameSettings.GoalLimit; @@ -1461,20 +1757,20 @@ begin end; end; // Ïðîèãðûø - if (Data.ScoreAction = 3) and (gGameSettings.GoalLimit > 0) then + if (trigData.trigScoreAction = 3) and (gGameSettings.GoalLimit > 0) then begin // Ñâîåé èëè ÷óæîé êîìàíäû - if (Data.ScoreTeam in [0..1]) and (g_GetUIDType(ActivateUID) = UID_PLAYER) then + if (trigData.trigScoreTeam in [0..1]) and (g_GetUIDType(ActivateUID) = UID_PLAYER) then begin p := g_Player_Get(ActivateUID); - if ((Data.ScoreTeam = 0) and (p.Team = TEAM_BLUE)) // Red Wins - or ((Data.ScoreTeam = 1) and (p.Team = TEAM_RED)) then + if ((trigData.trigScoreTeam = 0) and (p.Team = TEAM_BLUE)) // Red Wins + or ((trigData.trigScoreTeam = 1) and (p.Team = TEAM_RED)) then if gTeamStat[TEAM_RED].Goals < SmallInt(gGameSettings.GoalLimit) then begin gTeamStat[TEAM_RED].Goals := gGameSettings.GoalLimit; - if Data.ScoreCon then - if Data.ScoreTeam = 0 then + if trigData.trigScoreCon then + if trigData.trigScoreTeam = 0 then begin g_Console_Add(Format(_lc[I_PLAYER_SCORE_WIN_ENEMY], [p.Name, _lc[I_PLAYER_SCORE_TO_RED]]), True); if g_Game_IsServer and g_Game_IsNet then @@ -1488,14 +1784,14 @@ begin Result := True; end; - if ((Data.ScoreTeam = 0) and (p.Team = TEAM_RED)) // Blue Wins - or ((Data.ScoreTeam = 1) and (p.Team = TEAM_BLUE)) then + if ((trigData.trigScoreTeam = 0) and (p.Team = TEAM_RED)) // Blue Wins + or ((trigData.trigScoreTeam = 1) and (p.Team = TEAM_BLUE)) then if gTeamStat[TEAM_BLUE].Goals < SmallInt(gGameSettings.GoalLimit) then begin gTeamStat[TEAM_BLUE].Goals := gGameSettings.GoalLimit; - if Data.ScoreCon then - if Data.ScoreTeam = 0 then + if trigData.trigScoreCon then + if trigData.trigScoreTeam = 0 then begin g_Console_Add(Format(_lc[I_PLAYER_SCORE_WIN_ENEMY], [p.Name, _lc[I_PLAYER_SCORE_TO_BLUE]]), True); if g_Game_IsServer and g_Game_IsNet then @@ -1511,15 +1807,15 @@ begin end; end; // Êàêîé-òî êîíêðåòíîé êîìàíäû - if Data.ScoreTeam in [2..3] then + if trigData.trigScoreTeam in [2..3] then begin - if Data.ScoreTeam = 3 then // Red Wins + if trigData.trigScoreTeam = 3 then // Red Wins if gTeamStat[TEAM_RED].Goals < SmallInt(gGameSettings.GoalLimit) then begin gTeamStat[TEAM_RED].Goals := gGameSettings.GoalLimit; Result := True; end; - if Data.ScoreTeam = 2 then // Blue Wins + if trigData.trigScoreTeam = 2 then // Blue Wins if gTeamStat[TEAM_BLUE].Goals < SmallInt(gGameSettings.GoalLimit) then begin gTeamStat[TEAM_BLUE].Goals := gGameSettings.GoalLimit; @@ -1539,131 +1835,9 @@ begin 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(trigData.trigMessageKind, trigData.trigMessageText, + trigData.trigMessageSendTo, trigData.trigMessageTime, + ActivateUID); TimeOut := 18; end; @@ -1678,10 +1852,10 @@ begin 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 @@ -1693,7 +1867,7 @@ begin end else begin // Óæå âèäåëè åãî // Åñëè èíòåðâàë îòêëþ÷¸í, íî îí âñ¸ åù¸ â çîíå ïîðàæåíèÿ, äà¸ì åìó âðåìÿ - if (Data.DamageInterval = 0) and (Activators[k].TimeOut > 0) then + if (trigData.trigDamageInterval = 0) and (Activators[k].TimeOut > 0) then Activators[k].TimeOut := 65535; // Òàéìàóò ïðîø¸ë - ðàáîòàåì Result := Activators[k].TimeOut = 0; @@ -1710,12 +1884,12 @@ begin Exit; // Íàíîñèì óðîí èãðîêó - if (TriggerType = TRIGGER_DAMAGE) and (Data.DamageValue > 0) then - p.Damage(Data.DamageValue, 0, 0, 0, HIT_SOME); + if (TriggerType = TRIGGER_DAMAGE) and (trigData.trigDamageValue > 0) then + p.Damage(trigData.trigDamageValue, 0, 0, 0, HIT_SOME); // Ëå÷èì èãðîêà - if (TriggerType = TRIGGER_HEALTH) and (Data.HealValue > 0) then - if p.Heal(Data.HealValue, not Data.HealMax) and (not Data.HealSilent) then + if (TriggerType = TRIGGER_HEALTH) and (trigData.trigHealValue > 0) then + if p.Heal(trigData.trigHealValue, not trigData.trigHealMax) and (not trigData.trigHealSilent) then begin g_Sound_PlayExAt('SOUND_ITEM_GETITEM', p.Obj.X, p.Obj.Y); if g_Game_IsServer and g_Game_IsNet then @@ -1725,17 +1899,17 @@ begin UID_MONSTER: begin - m := g_Monsters_Get(ActivateUID); + m := g_Monsters_ByUID(ActivateUID); if m = nil then Exit; // Íàíîñèì óðîí ìîíñòðó - if (TriggerType = TRIGGER_DAMAGE) and (Data.DamageValue > 0) then - m.Damage(Data.DamageValue, 0, 0, 0, HIT_SOME); + if (TriggerType = TRIGGER_DAMAGE) and (trigData.trigDamageValue > 0) then + m.Damage(trigData.trigDamageValue, 0, 0, 0, HIT_SOME); // Ëå÷èì ìîíñòðà - if (TriggerType = TRIGGER_HEALTH) and (Data.HealValue > 0) then - if m.Heal(Data.HealValue) and (not Data.HealSilent) then + if (TriggerType = TRIGGER_HEALTH) and (trigData.trigHealValue > 0) then + if m.Heal(trigData.trigHealValue) and (not trigData.trigHealSilent) then begin g_Sound_PlayExAt('SOUND_ITEM_GETITEM', m.Obj.X, m.Obj.Y); if g_Game_IsServer and g_Game_IsNet then @@ -1745,12 +1919,12 @@ begin end; // Íàçíà÷àåì âðåìÿ ñëåäóþùåãî âîçäåéñòâèÿ if TriggerType = TRIGGER_DAMAGE then - i := Data.DamageInterval + idx := trigData.trigDamageInterval else - i := Data.HealInterval; + idx := trigData.trigHealInterval; 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; @@ -1763,84 +1937,72 @@ begin if ShotSightTime > 0 then Exit; - wx := Data.ShotPos.X; - wy := Data.ShotPos.Y; - pAngle := -DegToRad(Data.ShotAngle); + // put this at the beginning so it doesn't trigger itself + TimeOut := trigData.trigShotWait + 1; + + wx := trigData.trigShotPos.X; + wy := trigData.trigShotPos.Y; + pAngle := -DegToRad(trigData.trigShotAngle); xd := wx + Round(Cos(pAngle) * 32.0); yd := wy + Round(Sin(pAngle) * 32.0); TargetUID := 0; - case Data.ShotTarget of + case trigData.trigShotTarget 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; @@ -1848,42 +2010,42 @@ begin 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 (trigData.trigShotTarget <> TRIGGER_SHOT_TARGET_NONE) or + (trigData.trigShotType <> TRIGGER_SHOT_REV) then + TargetUID := ActivateUID; + end; end; - if (Data.ShotTarget = TRIGGER_SHOT_TARGET_NONE) or (TargetUID > 0) then + if (trigData.trigShotTarget = TRIGGER_SHOT_TARGET_NONE) or (TargetUID > 0) or + ((trigData.trigShotTarget > TRIGGER_SHOT_TARGET_NONE) and (TargetUID = 0)) then begin Result := True; - if (Data.ShotIntSight = 0) or - (Data.ShotTarget = TRIGGER_SHOT_TARGET_NONE) or + if (trigData.trigShotIntSight = 0) or + (trigData.trigShotTarget = TRIGGER_SHOT_TARGET_NONE) or (TargetUID = ShotSightTarget) then MakeShot(Trigger, wx, wy, xd, yd, TargetUID) else begin - ShotSightTime := Data.ShotIntSight; + ShotSightTime := trigData.trigShotIntSight; ShotSightTargetN := TargetUID; - if Data.ShotType = TRIGGER_SHOT_BFG then + if trigData.trigShotType = TRIGGER_SHOT_BFG then begin g_Sound_PlayExAt('SOUND_WEAPON_STARTFIREBFG', wx, wy); if g_Game_IsNet and g_Game_IsServer then @@ -1891,17 +2053,15 @@ begin end; end; end; - - TimeOut := Data.ShotWait + 1; end; TRIGGER_EFFECT: begin - i := Data.FXCount; + idx := trigData.trigFXCount; - while i > 0 do + while idx > 0 do begin - case Data.FXPos of + case trigData.trigFXPos of TRIGGER_EFFECT_POS_CENTER: begin wx := X + Width div 2; @@ -1917,18 +2077,18 @@ begin wy := Y + Height div 2; end; end; - xd := Data.FXVelX; - yd := Data.FXVelY; - if Data.FXSpreadL > 0 then xd := xd - Random(Data.FXSpreadL + 1); - 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, - Data.FXType, Data.FXSubType, - Data.FXColorR, Data.FXColorG, Data.FXColorB, True, False); - Dec(i); + xd := trigData.trigFXVelX; + yd := trigData.trigFXVelY; + if trigData.trigFXSpreadL > 0 then xd := xd - Random(trigData.trigFXSpreadL + 1); + if trigData.trigFXSpreadR > 0 then xd := xd + Random(trigData.trigFXSpreadR + 1); + if trigData.trigFXSpreadU > 0 then yd := yd - Random(trigData.trigFXSpreadU + 1); + if trigData.trigFXSpreadD > 0 then yd := yd + Random(trigData.trigFXSpreadD + 1); + tr_MakeEffect(wx, wy, xd, yd, + trigData.trigFXType, trigData.trigFXSubType, + trigData.trigFXColorR, trigData.trigFXColorG, trigData.trigFXColorB, True, False); + Dec(idx); end; - TimeOut := Data.FXWait; + TimeOut := trigData.trigFXWait; end; end; end; @@ -1937,10 +2097,35 @@ begin g_Map_SwitchTexture(Trigger.TexturePanelType, Trigger.TexturePanel, IfThen(animonce, 2, 1)); end; -function g_Triggers_Create(Trigger: TTrigger): DWORD; + +function g_Triggers_CreateWithMapIndex (Trigger: TTrigger; arridx, mapidx: Integer): DWORD; +var + triggers: TDynField; +begin + triggers := gCurrentMap['trigger']; + if (triggers = nil) then raise Exception.Create('LOAD: map has no triggers'); + if (mapidx < 0) or (mapidx >= triggers.count) then raise Exception.Create('LOAD: invalid map trigger index'); + Trigger.trigData := triggers.item[mapidx]; + if (Trigger.trigData = nil) then raise Exception.Create('LOAD: internal error in trigger loader'); + Trigger.mapId := Trigger.trigData.id; + Trigger.mapIndex := mapidx; + if (Trigger.trigData.trigRec <> nil) then + begin + Trigger.trigData := Trigger.trigData.trigRec.clone(); + end + else + begin + Trigger.trigData := nil; + end; + result := g_Triggers_Create(Trigger, arridx); +end; + + +function g_Triggers_Create(Trigger: TTrigger; forceInternalIndex: Integer=-1): DWORD; var find_id: DWORD; - fn, mapw: String; + fn, mapw: AnsiString; + f, olen: Integer; begin // Íå ñîçäàâàòü âûõîä, åñëè èãðà áåç âûõîäà: if (Trigger.TriggerType = TRIGGER_EXIT) and @@ -1957,9 +2142,37 @@ begin if Trigger.TriggerType = TRIGGER_SECRET then gSecretsCount := gSecretsCount + 1; - find_id := FindTrigger(); + if (forceInternalIndex < 0) then + begin + find_id := FindTrigger(); + end + else + begin + olen := Length(gTriggers); + if (forceInternalIndex >= olen) then + begin + SetLength(gTriggers, forceInternalIndex+1); + for f := olen to High(gTriggers) do gTriggers[f].TriggerType := TRIGGER_NONE; + end; + find_id := DWORD(forceInternalIndex); + end; gTriggers[find_id] := Trigger; + e_LogWritefln('created trigger with map index %s, findid=%s (%s)', [Trigger.mapIndex, find_id, Trigger.mapId]); + + { + writeln('trigger #', find_id, ': pos=(', Trigger.x, ',', Trigger.y, ')-(', Trigger.width, 'x', Trigger.height, ')', + '; TexturePanel=', Trigger.TexturePanel, + '; TexturePanelType=', Trigger.TexturePanelType, + '; ShotPanelType=', Trigger.ShotPanelType, + '; TriggerType=', Trigger.TriggerType, + '; ActivateType=', Trigger.ActivateType, + '; Keys=', Trigger.Keys, + '; trigPanelId=', Trigger.trigPanelId, + '; trigShotPanelId=', Trigger.trigShotPanelId + ); + } + with gTriggers[find_id] do begin ID := find_id; @@ -1987,30 +2200,30 @@ begin // Çàãðóæàåì çâóê, åñëè ýòî òðèããåð "Çâóê": if (Trigger.TriggerType = TRIGGER_SOUND) and - (Trigger.Data.SoundName <> '') then + (Trigger.trigData.trigSoundName <> '') then begin // Åùå íåò òàêîãî çâóêà: - if not g_Sound_Exists(Trigger.Data.SoundName) then + if not g_Sound_Exists(Trigger.trigData.trigSoundName) then begin - g_ProcessResourceStr(Trigger.Data.SoundName, @fn, nil, nil); + fn := g_ExtractWadName(Trigger.trigData.trigSoundName); if fn = '' then begin // Çâóê â ôàéëå ñ êàðòîé - g_ProcessResourceStr(gMapInfo.Map, @mapw, nil, nil); - fn := mapw + Trigger.Data.SoundName; + mapw := g_ExtractWadName(gMapInfo.Map); + fn := mapw+':'+g_ExtractFilePathName(Trigger.trigData.trigSoundName); end else // Çâóê â îòäåëüíîì ôàéëå - fn := GameDir + '/wads/' + Trigger.Data.SoundName; + fn := GameDir + '/wads/' + Trigger.trigData.trigSoundName; - if not g_Sound_CreateWADEx(Trigger.Data.SoundName, fn) then - g_FatalError(Format(_lc[I_GAME_ERROR_TR_SOUND], [fn, Trigger.Data.SoundName])); + if not g_Sound_CreateWADEx(Trigger.trigData.trigSoundName, fn) then + g_FatalError(Format(_lc[I_GAME_ERROR_TR_SOUND], [fn, Trigger.trigData.trigSoundName])); end; // Ñîçäàåì îáúåêò çâóêà: with gTriggers[find_id] do begin Sound := TPlayableSound.Create(); - if not Sound.SetByName(Trigger.Data.SoundName) then + if not Sound.SetByName(Trigger.trigData.trigSoundName) then begin Sound.Free(); Sound := nil; @@ -2020,23 +2233,23 @@ begin // Çàãðóæàåì ìóçûêó, åñëè ýòî òðèããåð "Ìóçûêà": if (Trigger.TriggerType = TRIGGER_MUSIC) and - (Trigger.Data.MusicName <> '') then + (Trigger.trigData.trigMusicName <> '') then begin // Åùå íåò òàêîé ìóçûêè: - if not g_Sound_Exists(Trigger.Data.MusicName) then + if not g_Sound_Exists(Trigger.trigData.trigMusicName) then begin - g_ProcessResourceStr(Trigger.Data.MusicName, @fn, nil, nil); + fn := g_ExtractWadName(Trigger.trigData.trigMusicName); if fn = '' then begin // Ìóçûêà â ôàéëå ñ êàðòîé - g_ProcessResourceStr(gMapInfo.Map, @mapw, nil, nil); - fn := mapw + Trigger.Data.MusicName; + mapw := g_ExtractWadName(gMapInfo.Map); + fn := mapw+':'+g_ExtractFilePathName(Trigger.trigData.trigMusicName); end else // Ìóçûêà â ôàéëå ñ êàðòîé - fn := GameDir+'/wads/'+Trigger.Data.MusicName; + fn := GameDir+'/wads/'+Trigger.trigData.trigMusicName; - if not g_Sound_CreateWADEx(Trigger.Data.MusicName, fn, True) then - g_FatalError(Format(_lc[I_GAME_ERROR_TR_SOUND], [fn, Trigger.Data.MusicName])); + if not g_Sound_CreateWADEx(Trigger.trigData.trigMusicName, fn, True) then + g_FatalError(Format(_lc[I_GAME_ERROR_TR_SOUND], [fn, Trigger.trigData.trigMusicName])); end; end; @@ -2049,18 +2262,41 @@ begin ShotSightTimeout := 0; ShotSightTarget := 0; ShotSightTargetN := 0; - ShotAmmoCount := Trigger.Data.ShotAmmo; + ShotAmmoCount := Trigger.trigData.trigShotAmmo; ShotReloadTime := 0; end; Result := find_id; end; + +// sorry; grid doesn't support recursive queries, so we have to do this +type + TSimpleMonsterList = specialize TSimpleList; + +var + tgMonsList: TSimpleMonsterList = nil; + procedure g_Triggers_Update(); var a, b, i: Integer; Affected: array of Integer; + + function monsNear (mon: TMonster): Boolean; + begin + result := false; // don't stop + { + gTriggers[a].ActivateUID := mon.UID; + ActivateTrigger(gTriggers[a], ACTIVATE_MONSTERCOLLIDE); + } + tgMonsList.append(mon); + end; + +var + mon: TMonster; begin + if (tgMonsList = nil) then tgMonsList := TSimpleMonsterList.Create(); + if gTriggers = nil then Exit; SetLength(Affected, 0); @@ -2086,7 +2322,7 @@ begin else Continue; // Ñ÷èòàåì, ÷òî îáúåêò ïîêèíóë çîíó äåéñòâèÿ òðèããåðà - if (Data.DamageInterval = 0) and (Activators[b].TimeOut < 65530) then + if (trigData.trigDamageInterval = 0) and (Activators[b].TimeOut < 65530) then Activators[b].TimeOut := 0; end; @@ -2095,13 +2331,13 @@ begin if SpawnCooldown = 0 then begin // Åñëè ïðèøëî âðåìÿ, ñïàâíèì ìîíñòðà: - if (TriggerType = TRIGGER_SPAWNMONSTER) and (Data.MonDelay > 0) then + if (TriggerType = TRIGGER_SPAWNMONSTER) and (trigData.trigMonDelay > 0) then begin ActivateUID := 0; ActivateTrigger(gTriggers[a], ACTIVATE_CUSTOM); end; // Åñëè ïðèøëî âðåìÿ, ñïàâíèì ïðåäìåò: - if (TriggerType = TRIGGER_SPAWNITEM) and (Data.ItemDelay > 0) then + if (TriggerType = TRIGGER_SPAWNITEM) and (trigData.trigItemDelay > 0) then begin ActivateUID := 0; ActivateTrigger(gTriggers[a], ACTIVATE_CUSTOM); @@ -2116,7 +2352,7 @@ begin begin Dec(ShotPanelTime); if ShotPanelTime = 0 then - g_Map_SwitchTexture(ShotPanelType, Data.ShotPanelID); + g_Map_SwitchTexture(ShotPanelType, trigShotPanelID); end; if ShotSightTime > 0 then begin @@ -2134,7 +2370,7 @@ begin begin Dec(ShotReloadTime); if ShotReloadTime = 0 then - ShotAmmoCount := Data.ShotAmmo; + ShotAmmoCount := trigData.trigShotAmmo; end; end; @@ -2142,60 +2378,60 @@ begin if Enabled and (TriggerType = TRIGGER_SOUND) and (Sound <> nil) then if (SoundPlayCount > 0) and (not Sound.IsPlaying()) then begin - if Data.PlayCount > 0 then // Åñëè 0 - èãðàåì çâóê áåñêîíå÷íî + if trigData.trigPlayCount > 0 then // Åñëè 0 - èãðàåì çâóê áåñêîíå÷íî SoundPlayCount := SoundPlayCount - 1; - if Data.Local then - Sound.PlayVolumeAt(X+(Width div 2), Y+(Height div 2), Data.Volume/255.0) + if trigData.trigLocal then + Sound.PlayVolumeAt(X+(Width div 2), Y+(Height div 2), trigData.trigVolume/255.0) else - Sound.PlayPanVolume((Data.Pan-127.0)/128.0, Data.Volume/255.0); + Sound.PlayPanVolume((trigData.trigPan-127.0)/128.0, trigData.trigVolume/255.0); if Sound.IsPlaying() and g_Game_IsNet and g_Game_IsServer then MH_SEND_TriggerSound(gTriggers[a]); end; // Òðèããåð "Ëîâóøêà" - ïîðà îòêðûâàòü: - if (TriggerType = TRIGGER_TRAP) and (DoorTime = 0) and (Data.PanelID <> -1) then + if (TriggerType = TRIGGER_TRAP) and (DoorTime = 0) and (trigPanelID <> -1) then begin - OpenDoor(Data.PanelID, Data.NoSound, Data.d2d_doors); + tr_OpenDoor(trigPanelID, trigData.trigNoSound, trigData.trigd2d_doors); DoorTime := -1; end; // Òðèããåð "Äâåðü 5 ñåê" - ïîðà çàêðûâàòü: - if (TriggerType = TRIGGER_DOOR5) and (DoorTime = 0) and (Data.PanelID <> -1) then + if (TriggerType = TRIGGER_DOOR5) and (DoorTime = 0) and (trigPanelID <> -1) then begin // Óæå çàêðûòà: - if gWalls[Data.PanelID].Enabled then + if gWalls[trigPanelID].Enabled then DoorTime := -1 else // Ïîêà îòêðûòà - çàêðûâàåì - if CloseDoor(Data.PanelID, Data.NoSound, Data.d2d_doors) then + if tr_CloseDoor(trigPanelID, trigData.trigNoSound, trigData.trigd2d_doors) then DoorTime := -1; end; // Òðèããåð - ðàñøèðèòåëü èëè ïåðåêëþ÷àòåëü, è ïðîøëà çàäåðæêà, è íàæàëè íóæíîå ÷èñëî ðàç: if (TriggerType in [TRIGGER_PRESS, TRIGGER_ON, TRIGGER_OFF, TRIGGER_ONOFF]) and - (PressTime = 0) and (PressCount >= Data.Count) then + (PressTime = 0) and (PressCount >= trigData.trigCount) then begin // Ñáðàñûâàåì çàäåðæêó àêòèâàöèè: PressTime := -1; // Ñáðàñûâàåì ñ÷åò÷èê íàæàòèé: - if Data.Count > 0 then - PressCount := PressCount - Data.Count + if trigData.trigCount > 0 then + PressCount := PressCount - trigData.trigCount else PressCount := 0; // Îïðåäåëÿåì èçìåíÿåìûå èì òðèããåðû: for b := 0 to High(gTriggers) do - if g_Collide(Data.tX, Data.tY, Data.tWidth, Data.tHeight, gTriggers[b].X, gTriggers[b].Y, + if g_Collide(trigData.trigtX, trigData.trigtY, trigData.trigtWidth, trigData.trigtHeight, gTriggers[b].X, gTriggers[b].Y, gTriggers[b].Width, gTriggers[b].Height) and - ((b <> a) or (Data.Wait > 0)) then + ((b <> a) or (trigData.trigWait > 0)) then begin // Can be self-activated, if there is Data.Wait - if (not Data.ExtRandom) or gTriggers[b].Enabled then + if (not trigData.trigExtRandom) or gTriggers[b].Enabled then begin SetLength(Affected, Length(Affected) + 1); Affected[High(Affected)] := b; end; end; // Âûáèðàåì îäèí èç òðèããåðîâ äëÿ ðàñøèðèòåëÿ, åñëè âêëþ÷åí ðàíäîì: - if (TriggerType = TRIGGER_PRESS) and Data.ExtRandom then + if (TriggerType = TRIGGER_PRESS) and trigData.trigExtRandom then begin if (Length(Affected) > 0) then begin @@ -2290,23 +2526,26 @@ begin 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?! + tgMonsList.reset(); + g_Mons_ForEachAt(gTriggers[a].X, gTriggers[a].Y, gTriggers[a].Width, gTriggers[a].Height, monsNear); + for mon in tgMonsList do + begin + gTriggers[a].ActivateUID := mon.UID; + ActivateTrigger(gTriggers[a], ACTIVATE_MONSTERCOLLIDE); + end; + tgMonsList.reset(); // just in case + 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); @@ -2317,9 +2556,9 @@ begin 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; @@ -2330,6 +2569,8 @@ var k: Byte; p: TPlayer; begin + Result := nil; + if gTriggers = nil then Exit; case g_GetUIDType(UID) of @@ -2345,8 +2586,6 @@ begin else k := 0; end; - Result := nil; - for a := 0 to High(gTriggers) do if (gTriggers[a].TriggerType <> TRIGGER_NONE) and (gTriggers[a].TimeOut = 0) and @@ -2400,7 +2639,7 @@ begin 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; @@ -2426,7 +2665,8 @@ begin 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 @@ -2461,7 +2701,7 @@ begin (TriggerType = TRIGGER_DOOR5) or (TriggerType = TRIGGER_DOOR) then begin - OpenDoor(Data.PanelID, True, Data.d2d_doors); + tr_OpenDoor(trigPanelID, True, trigData.trigd2d_doors); if TriggerType = TRIGGER_DOOR5 then DoorTime := 180; b := True; end; @@ -2480,19 +2720,22 @@ procedure g_Triggers_Free(); var a: Integer; begin - if gTriggers <> nil then - for a := 0 to High(gTriggers) do + for a := 0 to High(gTriggers) do + begin + if (gTriggers[a].TriggerType = TRIGGER_SOUND) then begin - if gTriggers[a].TriggerType = TRIGGER_SOUND then + if g_Sound_Exists(gTriggers[a].trigData.trigSoundName) then begin - if g_Sound_Exists(gTriggers[a].Data.SoundName) then - g_Sound_Delete(gTriggers[a].Data.SoundName); - - gTriggers[a].Sound.Free(); + g_Sound_Delete(gTriggers[a].trigData.trigSoundName); end; - if gTriggers[a].Activators <> nil then - SetLength(gTriggers[a].Activators, 0); + gTriggers[a].Sound.Free(); end; + if (gTriggers[a].Activators <> nil) then + begin + SetLength(gTriggers[a].Activators, 0); + end; + gTriggers[a].trigData.Free(); + end; gTriggers := nil; gSecretsCount := 0; @@ -2505,32 +2748,32 @@ var dw: DWORD; sg: Single; b: Boolean; - p: Pointer; begin -// Ñ÷èòàåì êîëè÷åñòâî ñóùåñòâóþùèõ òðèããåðîâ: - count := 0; - if gTriggers <> nil then - for i := 0 to High(gTriggers) do - count := count + 1; + // Ñ÷èòàåì êîëè÷åñòâî ñóùåñòâóþùèõ òðèããåðîâ + count := Length(gTriggers); Mem := TBinMemoryWriter.Create((count+1) * 200); -// Êîëè÷åñòâî òðèããåðîâ: + // Êîëè÷åñòâî òðèããåðîâ: Mem.WriteInt(count); - if count = 0 then - Exit; + e_LogWritefln('saving %s triggers (count=%s)', [Length(gTriggers), count]); + + if count = 0 then exit; for i := 0 to High(gTriggers) do begin // Ñèãíàòóðà òðèããåðà: - dw := TRIGGER_SIGNATURE; // 'TRGR' + dw := TRIGGER_SIGNATURE; // 'TRGX' Mem.WriteDWORD(dw); // Òèï òðèããåðà: Mem.WriteByte(gTriggers[i].TriggerType); - // Ñïåöèàëüíûå äàííûå òðèããåðà: - p := @gTriggers[i].Data; - Mem.WriteMemory(p, SizeOf(TTriggerData)); + if (gTriggers[i].TriggerType = TRIGGER_NONE) then continue; // empty one + // Ñïåöèàëüíûå äàííûå òðèããåðà: äà â æîïó, ïîòîì èç êàðòû îïÿòü âûòàùèì; ñîõðàíèì òîëüêî èíäåêñ + e_LogWritefln('=== trigger #%s saved ===', [gTriggers[i].mapIndex]); + Mem.WriteInt(gTriggers[i].mapIndex); + //p := @gTriggers[i].Data; + //Mem.WriteMemory(p, SizeOf(TTriggerData)); // Êîîðäèíàòû ëåâîãî âåðõíåãî óãëà: Mem.WriteInt(gTriggers[i].X); Mem.WriteInt(gTriggers[i].Y); @@ -2547,6 +2790,8 @@ begin Mem.WriteInt(gTriggers[i].TexturePanel); // Òèï ýòîé ïàíåëè: Mem.WriteWord(gTriggers[i].TexturePanelType); + // Âíóòðåííèé íîìåð äðóãîé ïàíåëè (ïî ñ÷àñòëèâîé ñëó÷àéíîñòè îí áóäåò ñîâïàäàòü ñ òåì, ÷òî ñîçäàíî ïðè çàãðóçêå êàðòû) + Mem.WriteInt(gTriggers[i].trigPanelId); // Âðåìÿ äî âîçìîæíîñòè àêòèâàöèè: Mem.WriteWord(gTriggers[i].TimeOut); // UID òîãî, êòî àêòèâèðîâàë ýòîò òðèããåð: @@ -2605,8 +2850,10 @@ var dw: DWORD; vol, pan: Single; b: Boolean; - p: Pointer; + //p: Pointer; Trig: TTrigger; + mapIndex: Integer; + //tw: TStrTextWriter; begin if Mem = nil then Exit; @@ -2616,28 +2863,44 @@ begin // Êîëè÷åñòâî òðèããåðîâ: Mem.ReadInt(count); - if count = 0 then - Exit; + if (count = 0) then exit; for a := 0 to count-1 do begin // Ñèãíàòóðà òðèããåðà: Mem.ReadDWORD(dw); - if dw <> TRIGGER_SIGNATURE then // 'TRGR' + if (dw <> TRIGGER_SIGNATURE) then // 'TRGX' begin raise EBinSizeError.Create('g_Triggers_LoadState: Wrong Trigger Signature'); end; // Òèï òðèããåðà: Mem.ReadByte(Trig.TriggerType); - // Ñïåöèàëüíûå äàííûå òðèããåðà: + // Ñïåöèàëüíûå äàííûå òðèããåðà: èíäåêñ â gCurrentMap.field['triggers'] + if (Trig.TriggerType = TRIGGER_NONE) then continue; // empty one + Mem.ReadInt(mapIndex); + //!!!FIXME!!! + { Mem.ReadMemory(p, dw); if dw <> SizeOf(TTriggerData) then begin raise EBinSizeError.Create('g_Triggers_LoadState: Wrong TriggerData Size'); end; Trig.Data := TTriggerData(p^); + } // Ñîçäàåì òðèããåð: - i := g_Triggers_Create(Trig); + i := g_Triggers_CreateWithMapIndex(Trig, a, mapIndex); + { + if (gTriggers[i].trigData <> nil) then + begin + tw := TStrTextWriter.Create(); + try + gTriggers[i].trigData.writeTo(tw); + e_LogWritefln('=== trigger #%s loaded ==='#10'%s'#10'---', [mapIndex, tw.str]); + finally + tw.Free(); + end; + end; + } // Êîîðäèíàòû ëåâîãî âåðõíåãî óãëà: Mem.ReadInt(gTriggers[i].X); Mem.ReadInt(gTriggers[i].Y); @@ -2654,6 +2917,8 @@ begin Mem.ReadInt(gTriggers[i].TexturePanel); // Òèï ýòîé ïàíåëè: Mem.ReadWord(gTriggers[i].TexturePanelType); + // Âíóòðåííèé íîìåð äðóãîé ïàíåëè (ïî ñ÷àñòëèâîé ñëó÷àéíîñòè îí áóäåò ñîâïàäàòü ñ òåì, ÷òî ñîçäàíî ïðè çàãðóçêå êàðòû) + Mem.ReadInt(gTriggers[i].trigPanelId); // Âðåìÿ äî âîçìîæíîñòè àêòèâàöèè: Mem.ReadWord(gTriggers[i].TimeOut); // UID òîãî, êòî àêòèâèðîâàë ýòîò òðèããåð: