1 (* Copyright (C) DooM 2D:Forever Developers
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 g_textures
, g_basic
, e_graphics
, g_phys
, BinEditor
;
44 Animation
: TAnimation
;
50 Shots
: array of TShot
= nil;
51 LastShotID
: Integer = 0;
53 procedure g_Weapon_LoadData();
54 procedure g_Weapon_FreeData();
55 procedure g_Weapon_Init();
56 procedure g_Weapon_Free();
57 function g_Weapon_Hit(obj
: PObj
; d
: Integer; SpawnerUID
: Word; t
: Byte; HitCorpses
: Boolean = True): Byte;
58 function g_Weapon_HitUID(UID
: Word; d
: Integer; SpawnerUID
: Word; t
: Byte): Boolean;
59 function g_Weapon_CreateShot(I
: Integer; ShotType
: Byte; Spawner
, TargetUID
: Word; X
, Y
, XV
, YV
: Integer): LongWord;
61 procedure g_Weapon_gun(x
, y
, xd
, yd
, v
, dmg
: Integer; SpawnerUID
: Word; CheckTrigger
: Boolean);
62 procedure g_Weapon_punch(x
, y
: Integer; d
, SpawnerUID
: Word);
63 function g_Weapon_chainsaw(x
, y
: Integer; d
, SpawnerUID
: Word): Integer;
64 procedure g_Weapon_rocket(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word; WID
: Integer = -1; Silent
: Boolean = False);
65 procedure g_Weapon_revf(x
, y
, xd
, yd
: Integer; SpawnerUID
, TargetUID
: Word; WID
: Integer = -1; Silent
: Boolean = False);
66 procedure g_Weapon_plasma(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word; WID
: Integer = -1; Silent
: Boolean = False);
67 procedure g_Weapon_ball1(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word; WID
: Integer = -1; Silent
: Boolean = False);
68 procedure g_Weapon_ball2(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word; WID
: Integer = -1; Silent
: Boolean = False);
69 procedure g_Weapon_ball7(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word; WID
: Integer = -1; Silent
: Boolean = False);
70 procedure g_Weapon_aplasma(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word; WID
: Integer = -1; Silent
: Boolean = False);
71 procedure g_Weapon_manfire(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word; WID
: Integer = -1; Silent
: Boolean = False);
72 procedure g_Weapon_bfgshot(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word; WID
: Integer = -1; Silent
: Boolean = False);
73 procedure g_Weapon_bfghit(x
, y
: Integer);
74 procedure g_Weapon_pistol(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word; Silent
: Boolean = False);
75 procedure g_Weapon_mgun(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word; Silent
: Boolean = False);
76 procedure g_Weapon_shotgun(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word; Silent
: Boolean = False);
77 procedure g_Weapon_dshotgun(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word; Silent
: Boolean = False);
79 function g_Weapon_Explode(X
, Y
: Integer; rad
: Integer; SpawnerUID
: Word): Boolean;
80 procedure g_Weapon_BFG9000(X
, Y
: Integer; SpawnerUID
: Word);
81 procedure g_Weapon_Update();
82 procedure g_Weapon_Draw();
83 function g_Weapon_Danger(UID
: Word; X
, Y
: Integer; Width
, Height
: Word; Time
: Byte): Boolean;
84 procedure g_Weapon_DestroyShot(I
: Integer; X
, Y
: Integer; Loud
: Boolean = True);
86 procedure g_Weapon_SaveState(var Mem
: TBinMemoryWriter
);
87 procedure g_Weapon_LoadState(var Mem
: TBinMemoryReader
);
96 WEAPON_ROCKETLAUNCHER
= 6;
99 WEAPON_SUPERPULEMET
= 9;
100 WEAPON_MEGAKASTET
= 10;
101 WEAPON_ZOMBY_PISTOL
= 20;
102 WEAPON_IMP_FIRE
= 21;
103 WEAPON_BSP_FIRE
= 22;
104 WEAPON_CACO_FIRE
= 23;
105 WEAPON_BARON_FIRE
= 24;
106 WEAPON_MANCUB_FIRE
= 25;
107 WEAPON_SKEL_FIRE
= 26;
112 Math
, g_map
, g_player
, g_gfx
, g_sound
, g_main
,
113 g_console
, SysUtils
, g_options
, g_game
,
114 g_triggers
, MAPDEF
, e_log
, g_monsters
, g_saveload
,
115 g_language
, g_netmsg
;
125 SHOT_ROCKETLAUNCHER_WIDTH
= 14;
126 SHOT_ROCKETLAUNCHER_HEIGHT
= 14;
128 SHOT_SKELFIRE_WIDTH
= 14;
129 SHOT_SKELFIRE_HEIGHT
= 14;
131 SHOT_PLASMA_WIDTH
= 16;
132 SHOT_PLASMA_HEIGHT
= 16;
135 SHOT_BFG_HEIGHT
= 32;
136 SHOT_BFG_DAMAGE
= 100;
137 SHOT_BFG_RADIUS
= 256;
139 SHOT_SIGNATURE
= $544F4853; // 'SHOT'
142 WaterMap
: array of array of DWORD
= nil;
144 function FindShot(): DWORD
;
149 for i
:= 0 to High(Shots
) do
150 if Shots
[i
].ShotType
= 0 then
153 LastShotID
:= Result
;
159 SetLength(Shots
, 128);
164 Result
:= High(Shots
) + 1;
165 SetLength(Shots
, Length(Shots
) + 128);
167 LastShotID
:= Result
;
170 procedure CreateWaterMap();
172 WaterArray
: Array of TWaterPanel
;
179 SetLength(WaterArray
, Length(gWater
));
181 for a
:= 0 to High(gWater
) do
183 WaterArray
[a
].X
:= gWater
[a
].X
;
184 WaterArray
[a
].Y
:= gWater
[a
].Y
;
185 WaterArray
[a
].Width
:= gWater
[a
].Width
;
186 WaterArray
[a
].Height
:= gWater
[a
].Height
;
187 WaterArray
[a
].Active
:= True;
190 g_Game_SetLoadingText(_lc
[I_LOAD_WATER_MAP
], High(WaterArray
), False);
192 for a
:= 0 to High(WaterArray
) do
193 if WaterArray
[a
].Active
then
195 WaterArray
[a
].Active
:= False;
196 m
:= Length(WaterMap
);
197 SetLength(WaterMap
, m
+1);
198 SetLength(WaterMap
[m
], 1);
205 for b
:= 0 to High(WaterArray
) do
206 if WaterArray
[b
].Active
then
207 for c
:= 0 to High(WaterMap
[m
]) do
208 if g_CollideAround(WaterArray
[b
].X
,
211 WaterArray
[b
].Height
,
212 WaterArray
[WaterMap
[m
][c
]].X
,
213 WaterArray
[WaterMap
[m
][c
]].Y
,
214 WaterArray
[WaterMap
[m
][c
]].Width
,
215 WaterArray
[WaterMap
[m
][c
]].Height
) then
217 WaterArray
[b
].Active
:= False;
218 SetLength(WaterMap
[m
],
219 Length(WaterMap
[m
])+1);
220 WaterMap
[m
][High(WaterMap
[m
])] := b
;
226 g_Game_StepLoading();
232 procedure CheckTrap(ID
: DWORD
; dm
: Integer; t
: Byte);
234 a
, b
, c
, d
, i1
, i2
: Integer;
237 if (gWater
= nil) or (WaterMap
= nil) then Exit
;
244 for d
:= 0 to 1023 do pl
[d
] := $FFFF;
245 for d
:= 0 to 1023 do mn
[d
] := $FFFF;
247 for a
:= 0 to High(WaterMap
) do
248 for b
:= 0 to High(WaterMap
[a
]) do
250 if not g_Obj_Collide(gWater
[WaterMap
[a
][b
]].X
, gWater
[WaterMap
[a
][b
]].Y
,
251 gWater
[WaterMap
[a
][b
]].Width
, gWater
[WaterMap
[a
][b
]].Height
,
252 @Shots
[ID
].Obj
) then Continue
;
254 for c
:= 0 to High(WaterMap
[a
]) do
256 if gPlayers
<> nil then
258 for d
:= 0 to High(gPlayers
) do
259 if (gPlayers
[d
] <> nil) and (gPlayers
[d
].Live
) then
260 if gPlayers
[d
].Collide(gWater
[WaterMap
[a
][c
]]) then
261 if not InWArray(d
, pl
) then
269 if gMonsters
<> nil then
271 for d
:= 0 to High(gMonsters
) do
272 if (gMonsters
[d
] <> nil) and (gMonsters
[d
].Live
) then
273 if gMonsters
[d
].Collide(gWater
[WaterMap
[a
][c
]]) then
274 if not InWArray(d
, mn
) then
285 gPlayers
[pl
[d
]].Damage(dm
, Shots
[ID
].SpawnerUID
, 0, 0, t
);
289 gMonsters
[mn
[d
]].Damage(dm
, 0, 0, Shots
[ID
].SpawnerUID
, t
);
296 function HitMonster(m
: TMonster
; d
: Integer; vx
, vy
: Integer; SpawnerUID
: Word; t
: Byte): Boolean;
303 tt
:= g_GetUIDType(SpawnerUID
);
304 if tt
= UID_MONSTER
then
306 mon
:= g_Monsters_Get(SpawnerUID
);
308 mt
:= g_Monsters_Get(SpawnerUID
).MonsterType
315 if m
= nil then Exit
;
316 if m
.UID
= SpawnerUID
then
318 // Ñàì ñåáÿ ìîæåò ðàíèòü òîëüêî ðàêåòîé è òîêîì:
319 if (t
<> HIT_ROCKET
) and (t
<> HIT_ELECTRO
) then
321 // Êèáåð äåìîí è áî÷êà âîîáùå íå ìîãóò ñåáÿ ðàíèòü:
322 if (m
.MonsterType
= MONSTER_CYBER
) or
323 (m
.MonsterType
= MONSTER_BARREL
) then
330 if tt
= UID_MONSTER
then
332 // Lost_Soul íå ìîæåò ðàíèòü Pain_Elemental'à:
333 if (mt
= MONSTER_SOUL
) and (m
.MonsterType
= MONSTER_PAIN
) then
336 // Îáà ìîíñòðà îäíîãî âèäà:
337 if mt
= m
.MonsterType
then
339 MONSTER_IMP
, MONSTER_DEMON
, MONSTER_BARON
, MONSTER_KNIGHT
, MONSTER_CACO
,
340 MONSTER_SOUL
, MONSTER_MANCUB
, MONSTER_SKEL
, MONSTER_FISH
:
341 Exit
; // Ýòè íå áüþò ñâîèõ
345 if g_Game_IsServer
then
346 Result
:= m
.Damage(d
, vx
, vy
, SpawnerUID
, t
)
351 function HitPlayer(p
: TPlayer
; d
: Integer; vx
, vy
: Integer; SpawnerUID
: Word; t
: Byte): Boolean;
355 // Ñàì ñåáÿ ìîæåò ðàíèòü òîëüêî ðàêåòîé è òîêîì:
356 if (p
.UID
= SpawnerUID
) and (t
<> HIT_ROCKET
) and (t
<> HIT_ELECTRO
) then
359 if g_Game_IsServer
then p
.Damage(d
, SpawnerUID
, vx
, vy
, t
);
364 function GunHit(X
, Y
: Integer; vx
, vy
: Integer; dmg
: Integer;
365 SpawnerUID
: Word; AllowPush
: Boolean): Byte;
375 if (gPlayers
[i
] <> nil) and gPlayers
[i
].Live
and gPlayers
[i
].Collide(X
, Y
) then
376 if HitPlayer(gPlayers
[i
], dmg
, vx
*10, vy
*10-3, SpawnerUID
, HIT_SOME
) then
378 if AllowPush
then gPlayers
[i
].Push(vx
, vy
);
382 if Result
<> 0 then Exit
;
384 h
:= High(gMonsters
);
388 if (gMonsters
[i
] <> nil) and gMonsters
[i
].Live
and gMonsters
[i
].Collide(X
, Y
) then
389 if HitMonster(gMonsters
[i
], dmg
, vx
*10, vy
*10-3, SpawnerUID
, HIT_SOME
) then
391 if AllowPush
then gMonsters
[i
].Push(vx
, vy
);
397 procedure g_Weapon_BFG9000(X
, Y
: Integer; SpawnerUID
: Word);
404 //g_Sound_PlayEx('SOUND_WEAPON_EXPLODEBFG', 255);
408 if gAdvCorpses
and (h
<> -1) then
410 if (gCorpses
[i
] <> nil) and (gCorpses
[i
].State
<> CORPSE_STATE_REMOVEME
) then
412 if (g_PatchLength(X
, Y
, Obj
.X
+Obj
.Rect
.X
+(Obj
.Rect
.Width
div 2),
413 Obj
.Y
+Obj
.Rect
.Y
+(Obj
.Rect
.Height
div 2)) <= SHOT_BFG_RADIUS
) and
414 g_TraceVector(X
, Y
, Obj
.X
+Obj
.Rect
.X
+(Obj
.Rect
.Width
div 2),
415 Obj
.Y
+Obj
.Rect
.Y
+(Obj
.Rect
.Height
div 2)) then
418 g_Weapon_BFGHit(Obj
.X
+Obj
.Rect
.X
+(Obj
.Rect
.Width
div 2),
419 Obj
.Y
+Obj
.Rect
.Y
+(Obj
.Rect
.Height
div 2));
423 pl
:= g_Player_Get(SpawnerUID
);
431 if (gPlayers
[i
] <> nil) and (gPlayers
[i
].Live
) and (gPlayers
[i
].UID
<> SpawnerUID
) then
433 if (g_PatchLength(X
, Y
, GameX
+PLAYER_RECT
.X
+(PLAYER_RECT
.Width
div 2),
434 GameY
+PLAYER_RECT
.Y
+(PLAYER_RECT
.Height
div 2)) <= SHOT_BFG_RADIUS
) and
435 g_TraceVector(X
, Y
, GameX
+PLAYER_RECT
.X
+(PLAYER_RECT
.Width
div 2),
436 GameY
+PLAYER_RECT
.Y
+(PLAYER_RECT
.Height
div 2)) then
438 if (st
= TEAM_NONE
) or (st
<> gPlayers
[i
].Team
) then
439 b
:= HitPlayer(gPlayers
[i
], 50, 0, 0, SpawnerUID
, HIT_SOME
)
441 b
:= HitPlayer(gPlayers
[i
], 25, 0, 0, SpawnerUID
, HIT_SOME
);
443 gPlayers
[i
].BFGHit();
446 h
:= High(gMonsters
);
450 if (gMonsters
[i
] <> nil) and (gMonsters
[i
].Live
) and (gMonsters
[i
].UID
<> SpawnerUID
) then
452 if (g_PatchLength(X
, Y
, Obj
.X
+Obj
.Rect
.X
+(Obj
.Rect
.Width
div 2),
453 Obj
.Y
+Obj
.Rect
.Y
+(Obj
.Rect
.Height
div 2)) <= SHOT_BFG_RADIUS
) and
454 g_TraceVector(X
, Y
, Obj
.X
+Obj
.Rect
.X
+(Obj
.Rect
.Width
div 2),
455 Obj
.Y
+Obj
.Rect
.Y
+(Obj
.Rect
.Height
div 2)) then
456 if HitMonster(gMonsters
[i
], 50, 0, 0, SpawnerUID
, HIT_SOME
) then gMonsters
[i
].BFGHit();
459 function g_Weapon_CreateShot(I
: Integer; ShotType
: Byte; Spawner
, TargetUID
: Word; X
, Y
, XV
, YV
: Integer): LongWord;
461 find_id
, FramesID
: DWORD
;
464 find_id
:= FindShot()
468 if Integer(find_id
) >= High(Shots
) then
469 SetLength(Shots
, find_id
+ 64)
473 WEAPON_ROCKETLAUNCHER
:
475 with Shots
[find_id
] do
479 Obj
.Rect
.Width
:= SHOT_ROCKETLAUNCHER_WIDTH
;
480 Obj
.Rect
.Height
:= SHOT_ROCKETLAUNCHER_HEIGHT
;
484 ShotType
:= WEAPON_ROCKETLAUNCHER
;
485 g_Texture_Get('TEXTURE_WEAPON_ROCKET', TextureID
);
491 with Shots
[find_id
] do
495 Obj
.Rect
.Width
:= SHOT_PLASMA_WIDTH
;
496 Obj
.Rect
.Height
:= SHOT_PLASMA_HEIGHT
;
499 ShotType
:= WEAPON_PLASMA
;
500 g_Frames_Get(FramesID
, 'FRAMES_WEAPON_PLASMA');
501 Animation
:= TAnimation
.Create(FramesID
, True, 5);
507 with Shots
[find_id
] do
511 Obj
.Rect
.Width
:= SHOT_BFG_WIDTH
;
512 Obj
.Rect
.Height
:= SHOT_BFG_HEIGHT
;
515 ShotType
:= WEAPON_BFG
;
516 g_Frames_Get(FramesID
, 'FRAMES_WEAPON_BFG');
517 Animation
:= TAnimation
.Create(FramesID
, True, 6);
523 with Shots
[find_id
] do
527 Obj
.Rect
.Width
:= 16;
528 Obj
.Rect
.Height
:= 16;
531 ShotType
:= WEAPON_IMP_FIRE
;
532 g_Frames_Get(FramesID
, 'FRAMES_WEAPON_IMPFIRE');
533 Animation
:= TAnimation
.Create(FramesID
, True, 4);
539 with Shots
[find_id
] do
543 Obj
.Rect
.Width
:= 16;
544 Obj
.Rect
.Height
:= 16;
547 ShotType
:= WEAPON_CACO_FIRE
;
548 g_Frames_Get(FramesID
, 'FRAMES_WEAPON_CACOFIRE');
549 Animation
:= TAnimation
.Create(FramesID
, True, 4);
555 with Shots
[find_id
] do
559 Obj
.Rect
.Width
:= 32;
560 Obj
.Rect
.Height
:= 32;
563 ShotType
:= WEAPON_MANCUB_FIRE
;
564 g_Frames_Get(FramesID
, 'FRAMES_WEAPON_MANCUBFIRE');
565 Animation
:= TAnimation
.Create(FramesID
, True, 4);
571 with Shots
[find_id
] do
575 Obj
.Rect
.Width
:= 32;
576 Obj
.Rect
.Height
:= 16;
579 ShotType
:= WEAPON_BARON_FIRE
;
580 g_Frames_Get(FramesID
, 'FRAMES_WEAPON_BARONFIRE');
581 Animation
:= TAnimation
.Create(FramesID
, True, 4);
587 with Shots
[find_id
] do
591 Obj
.Rect
.Width
:= 16;
592 Obj
.Rect
.Height
:= 16;
595 ShotType
:= WEAPON_BSP_FIRE
;
596 g_Frames_Get(FramesID
, 'FRAMES_WEAPON_BSPFIRE');
597 Animation
:= TAnimation
.Create(FramesID
, True, 4);
603 with Shots
[find_id
] do
607 Obj
.Rect
.Width
:= SHOT_SKELFIRE_WIDTH
;
608 Obj
.Rect
.Height
:= SHOT_SKELFIRE_HEIGHT
;
611 ShotType
:= WEAPON_SKEL_FIRE
;
613 g_Frames_Get(FramesID
, 'FRAMES_WEAPON_SKELFIRE');
614 Animation
:= TAnimation
.Create(FramesID
, True, 5);
619 Shots
[find_id
].Obj
.X
:= X
;
620 Shots
[find_id
].Obj
.Y
:= Y
;
621 Shots
[find_id
].Obj
.Vel
.X
:= XV
;
622 Shots
[find_id
].Obj
.Vel
.Y
:= YV
;
623 Shots
[find_id
].Obj
.Accel
.X
:= 0;
624 Shots
[find_id
].Obj
.Accel
.Y
:= 0;
625 Shots
[find_id
].SpawnerUID
:= Spawner
;
629 procedure throw(i
, x
, y
, xd
, yd
, s
: Integer);
636 a
:= Max(Abs(xd
), Abs(yd
));
642 Shots
[i
].Obj
.Vel
.X
:= (xd
*s
) div a
;
643 Shots
[i
].Obj
.Vel
.Y
:= (yd
*s
) div a
;
644 Shots
[i
].Obj
.Accel
.X
:= 0;
645 Shots
[i
].Obj
.Accel
.Y
:= 0;
646 if Shots
[i
].ShotType
in [WEAPON_ROCKETLAUNCHER
, WEAPON_BFG
] then
647 Shots
[i
].Timeout
:= 900 // ~25 sec
649 Shots
[i
].Timeout
:= 550 // ~15 sec
652 function g_Weapon_Hit(obj
: PObj
; d
: Integer; SpawnerUID
: Word; t
: Byte; HitCorpses
: Boolean = True): Byte;
656 function PlayerHit(Team
: Byte = 0): Boolean;
667 if (gPlayers
[i
] <> nil) and gPlayers
[i
].Live
and g_Obj_Collide(obj
, @gPlayers
[i
].Obj
) then
670 if (Team
> 0) and (g_GetUIDType(SpawnerUID
) = UID_PLAYER
) then
672 p
:= g_Player_Get(SpawnerUID
);
674 ChkTeam
:= (p
.Team
= gPlayers
[i
].Team
) xor (Team
= 2);
677 if HitPlayer(gPlayers
[i
], d
, obj
^.Vel
.X
, obj
^.Vel
.Y
, SpawnerUID
, t
) then
679 gPlayers
[i
].Push((obj
^.Vel
.X
+obj
^.Accel
.X
)*IfThen(t
= HIT_BFG
, 8, 1) div 4,
680 (obj
^.Vel
.Y
+obj
^.Accel
.Y
)*IfThen(t
= HIT_BFG
, 8, 1) div 4);
682 g_Game_DelayEvent(DE_BFGHIT
, 1000, SpawnerUID
);
688 function MonsterHit(): Boolean;
693 h
:= High(gMonsters
);
697 if (gMonsters
[i
] <> nil) and gMonsters
[i
].Live
and g_Obj_Collide(obj
, @gMonsters
[i
].Obj
) then
698 if HitMonster(gMonsters
[i
], d
, obj
^.Vel
.X
, obj
^.Vel
.Y
, SpawnerUID
, t
) then
700 gMonsters
[i
].Push((obj
^.Vel
.X
+obj
^.Accel
.X
)*IfThen(t
= HIT_BFG
, 8, 1) div 4,
701 (obj
^.Vel
.Y
+obj
^.Accel
.Y
)*IfThen(t
= HIT_BFG
, 8, 1) div 4);
713 if gAdvCorpses
and (h
<> -1) then
715 if (gCorpses
[i
] <> nil) and (gCorpses
[i
].State
<> CORPSE_STATE_REMOVEME
) and
716 g_Obj_Collide(obj
, @gCorpses
[i
].Obj
) then
719 gCorpses
[i
].Damage(d
, (obj
^.Vel
.X
+obj
^.Accel
.X
) div 4,
720 (obj
^.Vel
.Y
+obj
^.Accel
.Y
) div 4);
725 case gGameSettings
.GameMode
of
729 // Ñíà÷àëà áü¸ì ìîíñòðîâ, åñëè åñòü, ïîòîì ïûòàåìñÿ áèòü èãðîêîâ
746 // Ñíà÷àëà áü¸ì èãðîêîâ, åñëè åñòü, ïîòîì ïûòàåìñÿ áèòü ìîíñòðîâ
763 // Ñíà÷àëà áü¸ì èãðîêîâ êîìàíäû ñîïåðíèêà
777 // È â êîíöå ñâîèõ èãðîêîâ
788 function g_Weapon_HitUID(UID
: Word; d
: Integer; SpawnerUID
: Word; t
: Byte): Boolean;
792 case g_GetUIDType(UID
) of
793 UID_PLAYER
: Result
:= HitPlayer(g_Player_Get(UID
), d
, 0, 0, SpawnerUID
, t
);
794 UID_MONSTER
: Result
:= HitMonster(g_Monsters_Get(UID
), d
, 0, 0, SpawnerUID
, t
);
799 function g_Weapon_Explode(X
, Y
: Integer; rad
: Integer; SpawnerUID
: Word): Boolean;
801 i
, h
, r
, dx
, dy
, m
, mm
: Integer;
806 g_Triggers_PressC(X
, Y
, rad
, SpawnerUID
, ACTIVATE_SHOT
);
814 if (gPlayers
[i
] <> nil) and gPlayers
[i
].Live
then
817 dx
:= Obj
.X
+Obj
.Rect
.X
+(Obj
.Rect
.Width
div 2)-X
;
818 dy
:= Obj
.Y
+Obj
.Rect
.Y
+(Obj
.Rect
.Height
div 2)-Y
;
820 if dx
> 1000 then dx
:= 1000;
821 if dy
> 1000 then dy
:= 1000;
823 if dx
*dx
+dy
*dy
< r
then
825 //m := PointToRect(X, Y, GameX+PLAYER_RECT.X, GameY+PLAYER_RECT.Y,
826 // PLAYER_RECT.Width, PLAYER_RECT.Height);
828 mm
:= Max(abs(dx
), abs(dy
));
829 if mm
= 0 then mm
:= 1;
831 HitPlayer(gPlayers
[i
], (100*(rad
-mm
)) div rad
, (dx
*10) div mm
, (dy
*10) div mm
, SpawnerUID
, HIT_ROCKET
);
832 gPlayers
[i
].Push((dx
*7) div mm
, (dy
*7) div mm
);
836 h
:= High(gMonsters
);
840 if gMonsters
[i
] <> nil then
843 dx
:= Obj
.X
+Obj
.Rect
.X
+(Obj
.Rect
.Width
div 2)-X
;
844 dy
:= Obj
.Y
+Obj
.Rect
.Y
+(Obj
.Rect
.Height
div 2)-Y
;
846 if dx
> 1000 then dx
:= 1000;
847 if dy
> 1000 then dy
:= 1000;
849 if dx
*dx
+dy
*dy
< r
then
851 //m := PointToRect(X, Y, Obj.X+Obj.Rect.X, Obj.Y+Obj.Rect.Y,
852 // Obj.Rect.Width, Obj.Rect.Height);
854 mm
:= Max(abs(dx
), abs(dy
));
855 if mm
= 0 then mm
:= 1;
857 if gMonsters
[i
].Live
then
858 HitMonster(gMonsters
[i
], ((gMonsters
[i
].Obj
.Rect
.Width
div 4)*10*(rad
-mm
)) div rad
,
859 0, 0, SpawnerUID
, HIT_ROCKET
);
861 gMonsters
[i
].Push((dx
*7) div mm
, (dy
*7) div mm
);
867 if gAdvCorpses
and (h
<> -1) then
869 if (gCorpses
[i
] <> nil) and (gCorpses
[i
].State
<> CORPSE_STATE_REMOVEME
) then
872 dx
:= Obj
.X
+Obj
.Rect
.X
+(Obj
.Rect
.Width
div 2)-X
;
873 dy
:= Obj
.Y
+Obj
.Rect
.Y
+(Obj
.Rect
.Height
div 2)-Y
;
875 if dx
> 1000 then dx
:= 1000;
876 if dy
> 1000 then dy
:= 1000;
878 if dx
*dx
+dy
*dy
< r
then
880 m
:= PointToRect(X
, Y
, Obj
.X
+Obj
.Rect
.X
, Obj
.Y
+Obj
.Rect
.Y
,
881 Obj
.Rect
.Width
, Obj
.Rect
.Height
);
883 mm
:= Max(abs(dx
), abs(dy
));
884 if mm
= 0 then mm
:= 1;
886 Damage(Round(100*(rad
-m
)/rad
), (dx
*10) div mm
, (dy
*10) div mm
);
892 if gAdvGibs
and (h
<> -1) then
894 if gGibs
[i
].Live
then
897 dx
:= Obj
.X
+Obj
.Rect
.X
+(Obj
.Rect
.Width
div 2)-X
;
898 dy
:= Obj
.Y
+Obj
.Rect
.Y
+(Obj
.Rect
.Height
div 2)-Y
;
900 if dx
> 1000 then dx
:= 1000;
901 if dy
> 1000 then dy
:= 1000;
903 if dx
*dx
+dy
*dy
< r
then
905 m
:= PointToRect(X
, Y
, Obj
.X
+Obj
.Rect
.X
, Obj
.Y
+Obj
.Rect
.Y
,
906 Obj
.Rect
.Width
, Obj
.Rect
.Height
);
907 _angle
:= GetAngle(Obj
.X
+Obj
.Rect
.X
+(Obj
.Rect
.Width
div 2),
908 Obj
.Y
+Obj
.Rect
.Y
+(Obj
.Rect
.Height
div 2), X
, Y
);
910 g_Obj_PushA(@Obj
, Round(15*(rad
-m
)/rad
), _angle
);
915 procedure g_Weapon_Init();
920 procedure g_Weapon_Free();
926 for i
:= 0 to High(Shots
) do
927 if Shots
[i
].ShotType
<> 0 then
928 Shots
[i
].Animation
.Free();
936 procedure g_Weapon_LoadData();
938 e_WriteLog('Loading weapons data...', MSG_NOTIFY
);
940 g_Sound_CreateWADEx('SOUND_WEAPON_HITPUNCH', GameWAD
+':SOUNDS\HITPUNCH');
941 g_Sound_CreateWADEx('SOUND_WEAPON_MISSPUNCH', GameWAD
+':SOUNDS\MISSPUNCH');
942 g_Sound_CreateWADEx('SOUND_WEAPON_HITBERSERK', GameWAD
+':SOUNDS\HITBERSERK');
943 g_Sound_CreateWADEx('SOUND_WEAPON_MISSBERSERK', GameWAD
+':SOUNDS\MISSBERSERK');
944 g_Sound_CreateWADEx('SOUND_WEAPON_SELECTSAW', GameWAD
+':SOUNDS\SELECTSAW');
945 g_Sound_CreateWADEx('SOUND_WEAPON_IDLESAW', GameWAD
+':SOUNDS\IDLESAW');
946 g_Sound_CreateWADEx('SOUND_WEAPON_HITSAW', GameWAD
+':SOUNDS\HITSAW');
947 g_Sound_CreateWADEx('SOUND_WEAPON_FIRESHOTGUN2', GameWAD
+':SOUNDS\FIRESHOTGUN2');
948 g_Sound_CreateWADEx('SOUND_WEAPON_FIRESHOTGUN', GameWAD
+':SOUNDS\FIRESHOTGUN');
949 g_Sound_CreateWADEx('SOUND_WEAPON_FIRESAW', GameWAD
+':SOUNDS\FIRESAW');
950 g_Sound_CreateWADEx('SOUND_WEAPON_FIREROCKET', GameWAD
+':SOUNDS\FIREROCKET');
951 g_Sound_CreateWADEx('SOUND_WEAPON_FIREPLASMA', GameWAD
+':SOUNDS\FIREPLASMA');
952 g_Sound_CreateWADEx('SOUND_WEAPON_FIREPISTOL', GameWAD
+':SOUNDS\FIREPISTOL');
953 g_Sound_CreateWADEx('SOUND_WEAPON_FIRECGUN', GameWAD
+':SOUNDS\FIRECGUN');
954 g_Sound_CreateWADEx('SOUND_WEAPON_FIREBFG', GameWAD
+':SOUNDS\FIREBFG');
955 g_Sound_CreateWADEx('SOUND_FIRE', GameWAD
+':SOUNDS\FIRE');
956 g_Sound_CreateWADEx('SOUND_WEAPON_STARTFIREBFG', GameWAD
+':SOUNDS\STARTFIREBFG');
957 g_Sound_CreateWADEx('SOUND_WEAPON_EXPLODEROCKET', GameWAD
+':SOUNDS\EXPLODEROCKET');
958 g_Sound_CreateWADEx('SOUND_WEAPON_EXPLODEBFG', GameWAD
+':SOUNDS\EXPLODEBFG');
959 g_Sound_CreateWADEx('SOUND_WEAPON_BFGWATER', GameWAD
+':SOUNDS\BFGWATER');
960 g_Sound_CreateWADEx('SOUND_WEAPON_EXPLODEPLASMA', GameWAD
+':SOUNDS\EXPLODEPLASMA');
961 g_Sound_CreateWADEx('SOUND_WEAPON_PLASMAWATER', GameWAD
+':SOUNDS\PLASMAWATER');
962 g_Sound_CreateWADEx('SOUND_WEAPON_FIREBALL', GameWAD
+':SOUNDS\FIREBALL');
963 g_Sound_CreateWADEx('SOUND_WEAPON_EXPLODEBALL', GameWAD
+':SOUNDS\EXPLODEBALL');
964 g_Sound_CreateWADEx('SOUND_WEAPON_FIREREV', GameWAD
+':SOUNDS\FIREREV');
965 g_Sound_CreateWADEx('SOUND_PLAYER_JETFLY', GameWAD
+':SOUNDS\WORKJETPACK');
966 g_Sound_CreateWADEx('SOUND_PLAYER_JETON', GameWAD
+':SOUNDS\STARTJETPACK');
967 g_Sound_CreateWADEx('SOUND_PLAYER_JETOFF', GameWAD
+':SOUNDS\STOPJETPACK');
968 g_Sound_CreateWADEx('SOUND_PLAYER_CASING1', GameWAD
+':SOUNDS\CASING1');
969 g_Sound_CreateWADEx('SOUND_PLAYER_CASING2', GameWAD
+':SOUNDS\CASING2');
970 g_Sound_CreateWADEx('SOUND_PLAYER_SHELL1', GameWAD
+':SOUNDS\SHELL1');
971 g_Sound_CreateWADEx('SOUND_PLAYER_SHELL2', GameWAD
+':SOUNDS\SHELL2');
973 g_Texture_CreateWADEx('TEXTURE_WEAPON_ROCKET', GameWAD
+':TEXTURES\BROCKET');
974 g_Frames_CreateWAD(nil, 'FRAMES_WEAPON_SKELFIRE', GameWAD
+':TEXTURES\BSKELFIRE', 64, 16, 2);
975 g_Frames_CreateWAD(nil, 'FRAMES_WEAPON_BFG', GameWAD
+':TEXTURES\BBFG', 64, 64, 2);
976 g_Frames_CreateWAD(nil, 'FRAMES_WEAPON_PLASMA', GameWAD
+':TEXTURES\BPLASMA', 16, 16, 2);
977 g_Frames_CreateWAD(nil, 'FRAMES_WEAPON_IMPFIRE', GameWAD
+':TEXTURES\BIMPFIRE', 16, 16, 2);
978 g_Frames_CreateWAD(nil, 'FRAMES_WEAPON_BSPFIRE', GameWAD
+':TEXTURES\BBSPFIRE', 16, 16, 2);
979 g_Frames_CreateWAD(nil, 'FRAMES_WEAPON_CACOFIRE', GameWAD
+':TEXTURES\BCACOFIRE', 16, 16, 2);
980 g_Frames_CreateWAD(nil, 'FRAMES_WEAPON_BARONFIRE', GameWAD
+':TEXTURES\BBARONFIRE', 64, 16, 2);
981 g_Frames_CreateWAD(nil, 'FRAMES_WEAPON_MANCUBFIRE', GameWAD
+':TEXTURES\BMANCUBFIRE', 64, 32, 2);
982 g_Frames_CreateWAD(nil, 'FRAMES_EXPLODE_ROCKET', GameWAD
+':TEXTURES\EROCKET', 128, 128, 6);
983 g_Frames_CreateWAD(nil, 'FRAMES_EXPLODE_SKELFIRE', GameWAD
+':TEXTURES\ESKELFIRE', 64, 64, 3);
984 g_Frames_CreateWAD(nil, 'FRAMES_EXPLODE_BFG', GameWAD
+':TEXTURES\EBFG', 128, 128, 6);
985 g_Frames_CreateWAD(nil, 'FRAMES_EXPLODE_IMPFIRE', GameWAD
+':TEXTURES\EIMPFIRE', 64, 64, 3);
986 g_Frames_CreateWAD(nil, 'FRAMES_BFGHIT', GameWAD
+':TEXTURES\BFGHIT', 64, 64, 4);
987 g_Frames_CreateWAD(nil, 'FRAMES_FIRE', GameWAD
+':TEXTURES\FIRE', 64, 128, 8);
988 g_Frames_CreateWAD(nil, 'FRAMES_EXPLODE_PLASMA', GameWAD
+':TEXTURES\EPLASMA', 32, 32, 4, True);
989 g_Frames_CreateWAD(nil, 'FRAMES_EXPLODE_BSPFIRE', GameWAD
+':TEXTURES\EBSPFIRE', 32, 32, 5);
990 g_Frames_CreateWAD(nil, 'FRAMES_EXPLODE_CACOFIRE', GameWAD
+':TEXTURES\ECACOFIRE', 64, 64, 3);
991 g_Frames_CreateWAD(nil, 'FRAMES_EXPLODE_BARONFIRE', GameWAD
+':TEXTURES\EBARONFIRE', 64, 64, 3);
992 g_Frames_CreateWAD(nil, 'FRAMES_SMOKE', GameWAD
+':TEXTURES\SMOKE', 32, 32, 10, False);
994 g_Texture_CreateWADEx('TEXTURE_SHELL_BULLET', GameWAD
+':TEXTURES\EBULLET');
995 g_Texture_CreateWADEx('TEXTURE_SHELL_SHELL', GameWAD
+':TEXTURES\ESHELL');
998 procedure g_Weapon_FreeData();
1000 e_WriteLog('Releasing weapons data...', MSG_NOTIFY
);
1002 g_Sound_Delete('SOUND_WEAPON_HITPUNCH');
1003 g_Sound_Delete('SOUND_WEAPON_MISSPUNCH');
1004 g_Sound_Delete('SOUND_WEAPON_HITBERSERK');
1005 g_Sound_Delete('SOUND_WEAPON_MISSBERSERK');
1006 g_Sound_Delete('SOUND_WEAPON_SELECTSAW');
1007 g_Sound_Delete('SOUND_WEAPON_IDLESAW');
1008 g_Sound_Delete('SOUND_WEAPON_HITSAW');
1009 g_Sound_Delete('SOUND_WEAPON_FIRESHOTGUN2');
1010 g_Sound_Delete('SOUND_WEAPON_FIRESHOTGUN');
1011 g_Sound_Delete('SOUND_WEAPON_FIRESAW');
1012 g_Sound_Delete('SOUND_WEAPON_FIREROCKET');
1013 g_Sound_Delete('SOUND_WEAPON_FIREPLASMA');
1014 g_Sound_Delete('SOUND_WEAPON_FIREPISTOL');
1015 g_Sound_Delete('SOUND_WEAPON_FIRECGUN');
1016 g_Sound_Delete('SOUND_WEAPON_FIREBFG');
1017 g_Sound_Delete('SOUND_FIRE');
1018 g_Sound_Delete('SOUND_WEAPON_STARTFIREBFG');
1019 g_Sound_Delete('SOUND_WEAPON_EXPLODEROCKET');
1020 g_Sound_Delete('SOUND_WEAPON_EXPLODEBFG');
1021 g_Sound_Delete('SOUND_WEAPON_BFGWATER');
1022 g_Sound_Delete('SOUND_WEAPON_EXPLODEPLASMA');
1023 g_Sound_Delete('SOUND_WEAPON_PLASMAWATER');
1024 g_Sound_Delete('SOUND_WEAPON_FIREBALL');
1025 g_Sound_Delete('SOUND_WEAPON_EXPLODEBALL');
1026 g_Sound_Delete('SOUND_WEAPON_FIREREV');
1027 g_Sound_Delete('SOUND_PLAYER_JETFLY');
1028 g_Sound_Delete('SOUND_PLAYER_JETON');
1029 g_Sound_Delete('SOUND_PLAYER_JETOFF');
1030 g_Sound_Delete('SOUND_PLAYER_CASING1');
1031 g_Sound_Delete('SOUND_PLAYER_CASING2');
1032 g_Sound_Delete('SOUND_PLAYER_SHELL1');
1033 g_Sound_Delete('SOUND_PLAYER_SHELL2');
1035 g_Texture_Delete('TEXTURE_WEAPON_ROCKET');
1036 g_Frames_DeleteByName('FRAMES_WEAPON_BFG');
1037 g_Frames_DeleteByName('FRAMES_WEAPON_PLASMA');
1038 g_Frames_DeleteByName('FRAMES_WEAPON_IMPFIRE');
1039 g_Frames_DeleteByName('FRAMES_WEAPON_BSPFIRE');
1040 g_Frames_DeleteByName('FRAMES_WEAPON_CACOFIRE');
1041 g_Frames_DeleteByName('FRAMES_WEAPON_MANCUBFIRE');
1042 g_Frames_DeleteByName('FRAMES_EXPLODE_ROCKET');
1043 g_Frames_DeleteByName('FRAMES_EXPLODE_BFG');
1044 g_Frames_DeleteByName('FRAMES_EXPLODE_IMPFIRE');
1045 g_Frames_DeleteByName('FRAMES_BFGHIT');
1046 g_Frames_DeleteByName('FRAMES_FIRE');
1047 g_Frames_DeleteByName('FRAMES_EXPLODE_PLASMA');
1048 g_Frames_DeleteByName('FRAMES_EXPLODE_BSPFIRE');
1049 g_Frames_DeleteByName('FRAMES_EXPLODE_CACOFIRE');
1050 g_Frames_DeleteByName('FRAMES_SMOKE');
1051 g_Frames_DeleteByName('FRAMES_WEAPON_BARONFIRE');
1052 g_Frames_DeleteByName('FRAMES_EXPLODE_BARONFIRE');
1055 procedure g_Weapon_gun(x
, y
, xd
, yd
, v
, dmg
: Integer; SpawnerUID
: Word; CheckTrigger
: Boolean);
1067 t1
, _collide
: Boolean;
1070 a
:= GetAngle(x
, y
, xd
, yd
)+180;
1072 SinCos(DegToRad(-a
), s
, c
);
1074 if Abs(s
) < 0.01 then s
:= 0;
1075 if Abs(c
) < 0.01 then c
:= 0;
1077 x2
:= x
+Round(c
*gMapInfo
.Width
);
1078 y2
:= y
+Round(s
*gMapInfo
.Width
);
1080 t1
:= gWalls
<> nil;
1082 w
:= gMapInfo
.Width
;
1083 h
:= gMapInfo
.Height
;
1090 if (xd
= 0) and (yd
= 0) then Exit
;
1092 if dx
> 0 then xi
:= 1 else if dx
< 0 then xi
:= -1 else xi
:= 0;
1093 if dy
> 0 then yi
:= 1 else if dy
< 0 then yi
:= -1 else yi
:= 0;
1098 if dx
> dy
then d
:= dx
else d
:= dy
;
1100 //blood vel, for Monster.Damage()
1101 //vx := (dx*10 div d)*xi;
1102 //vy := (dy*10 div d)*yi;
1124 if (yy
> h
) or (yy
< 0) then Break
;
1125 if (xx
> w
) or (xx
< 0) then Break
;
1128 if ByteBool(gCollideMap
[yy
, xx
] and MARK_BLOCKED
) then
1131 g_GFX_Spark(xx
-xi
, yy
-yi
, 2+Random(2), 180+a
, 0, 0);
1132 if g_Game_IsServer
and g_Game_IsNet
then
1133 MH_SEND_Effect(xx
-xi
, yy
-yi
, 180+a
, NET_GFX_SPARK
);
1136 if not _collide
then
1137 _collide
:= GunHit(xx
, yy
, xi
*v
, yi
*v
, dmg
, SpawnerUID
, v
<> 0) <> 0;
1143 if CheckTrigger
and g_Game_IsServer
then
1144 g_Triggers_PressL(X
, Y
, xx
-xi
, yy
-yi
, SpawnerUID
, ACTIVATE_SHOT
);
1147 procedure g_Weapon_punch(x
, y
: Integer; d
, SpawnerUID
: Word);
1155 obj
.rect
.Width
:= 39;
1156 obj
.rect
.Height
:= 52;
1162 if g_Weapon_Hit(@obj
, d
, SpawnerUID
, HIT_SOME
) <> 0 then
1163 g_Sound_PlayExAt('SOUND_WEAPON_HITPUNCH', x
, y
)
1165 g_Sound_PlayExAt('SOUND_WEAPON_MISSPUNCH', x
, y
);
1168 function g_Weapon_chainsaw(x
, y
: Integer; d
, SpawnerUID
: Word): Integer;
1176 obj
.rect
.Width
:= 32;
1177 obj
.rect
.Height
:= 52;
1183 Result
:= g_Weapon_Hit(@obj
, d
, SpawnerUID
, HIT_SOME
);
1186 procedure g_Weapon_rocket(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word; WID
: Integer = -1;
1187 Silent
: Boolean = False);
1193 find_id
:= FindShot()
1197 if Integer(find_id
) >= High(Shots
) then
1198 SetLength(Shots
, find_id
+ 64)
1201 with Shots
[find_id
] do
1205 Obj
.Rect
.Width
:= SHOT_ROCKETLAUNCHER_WIDTH
;
1206 Obj
.Rect
.Height
:= SHOT_ROCKETLAUNCHER_HEIGHT
;
1208 dx
:= IfThen(xd
> x
, -Obj
.Rect
.Width
, 0);
1209 dy
:= -(Obj
.Rect
.Height
div 2);
1210 throw(find_id
, x
+dx
, y
+dy
, xd
+dx
, yd
+dy
, 12);
1214 ShotType
:= WEAPON_ROCKETLAUNCHER
;
1215 g_Texture_Get('TEXTURE_WEAPON_ROCKET', TextureID
);
1218 Shots
[find_id
].SpawnerUID
:= SpawnerUID
;
1221 g_Sound_PlayExAt('SOUND_WEAPON_FIREROCKET', x
, y
);
1224 procedure g_Weapon_revf(x
, y
, xd
, yd
: Integer; SpawnerUID
, TargetUID
: Word;
1225 WID
: Integer = -1; Silent
: Boolean = False);
1227 find_id
, FramesID
: DWORD
;
1231 find_id
:= FindShot()
1235 if Integer(find_id
) >= High(Shots
) then
1236 SetLength(Shots
, find_id
+ 64)
1239 with Shots
[find_id
] do
1243 Obj
.Rect
.Width
:= SHOT_SKELFIRE_WIDTH
;
1244 Obj
.Rect
.Height
:= SHOT_SKELFIRE_HEIGHT
;
1246 dx
:= -(Obj
.Rect
.Width
div 2);
1247 dy
:= -(Obj
.Rect
.Height
div 2);
1248 throw(find_id
, x
+dx
, y
+dy
, xd
+dx
, yd
+dy
, 12);
1251 ShotType
:= WEAPON_SKEL_FIRE
;
1252 target
:= TargetUID
;
1253 g_Frames_Get(FramesID
, 'FRAMES_WEAPON_SKELFIRE');
1254 Animation
:= TAnimation
.Create(FramesID
, True, 5);
1257 Shots
[find_id
].SpawnerUID
:= SpawnerUID
;
1260 g_Sound_PlayExAt('SOUND_WEAPON_FIREREV', x
, y
);
1263 procedure g_Weapon_plasma(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word; WID
: Integer = -1;
1264 Silent
: Boolean = False);
1266 find_id
, FramesID
: DWORD
;
1270 find_id
:= FindShot()
1274 if Integer(find_id
) >= High(Shots
) then
1275 SetLength(Shots
, find_id
+ 64);
1278 with Shots
[find_id
] do
1282 Obj
.Rect
.Width
:= SHOT_PLASMA_WIDTH
;
1283 Obj
.Rect
.Height
:= SHOT_PLASMA_HEIGHT
;
1285 dx
:= IfThen(xd
>x
, -Obj
.Rect
.Width
, 0);
1286 dy
:= -(Obj
.Rect
.Height
div 2);
1287 throw(find_id
, x
+dx
, y
+dy
, xd
+dx
, yd
+dy
, 16);
1290 ShotType
:= WEAPON_PLASMA
;
1291 g_Frames_Get(FramesID
, 'FRAMES_WEAPON_PLASMA');
1292 Animation
:= TAnimation
.Create(FramesID
, True, 5);
1295 Shots
[find_id
].SpawnerUID
:= SpawnerUID
;
1298 g_Sound_PlayExAt('SOUND_WEAPON_FIREPLASMA', x
, y
);
1301 procedure g_Weapon_ball1(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word; WID
: Integer = -1;
1302 Silent
: Boolean = False);
1304 find_id
, FramesID
: DWORD
;
1308 find_id
:= FindShot()
1312 if Integer(find_id
) >= High(Shots
) then
1313 SetLength(Shots
, find_id
+ 64)
1316 with Shots
[find_id
] do
1320 Obj
.Rect
.Width
:= 16;
1321 Obj
.Rect
.Height
:= 16;
1323 dx
:= IfThen(xd
>x
, -Obj
.Rect
.Width
, 0);
1324 dy
:= -(Obj
.Rect
.Height
div 2);
1325 throw(find_id
, x
+dx
, y
+dy
, xd
+dx
, yd
+dy
, 16);
1328 ShotType
:= WEAPON_IMP_FIRE
;
1329 g_Frames_Get(FramesID
, 'FRAMES_WEAPON_IMPFIRE');
1330 Animation
:= TAnimation
.Create(FramesID
, True, 4);
1333 Shots
[find_id
].SpawnerUID
:= SpawnerUID
;
1336 g_Sound_PlayExAt('SOUND_WEAPON_FIREBALL', x
, y
);
1339 procedure g_Weapon_ball2(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word; WID
: Integer = -1;
1340 Silent
: Boolean = False);
1342 find_id
, FramesID
: DWORD
;
1346 find_id
:= FindShot()
1350 if Integer(find_id
) >= High(Shots
) then
1351 SetLength(Shots
, find_id
+ 64)
1354 with Shots
[find_id
] do
1358 Obj
.Rect
.Width
:= 16;
1359 Obj
.Rect
.Height
:= 16;
1361 dx
:= IfThen(xd
>x
, -Obj
.Rect
.Width
, 0);
1362 dy
:= -(Obj
.Rect
.Height
div 2);
1363 throw(find_id
, x
+dx
, y
+dy
, xd
+dx
, yd
+dy
, 16);
1366 ShotType
:= WEAPON_CACO_FIRE
;
1367 g_Frames_Get(FramesID
, 'FRAMES_WEAPON_CACOFIRE');
1368 Animation
:= TAnimation
.Create(FramesID
, True, 4);
1371 Shots
[find_id
].SpawnerUID
:= SpawnerUID
;
1374 g_Sound_PlayExAt('SOUND_WEAPON_FIREBALL', x
, y
);
1377 procedure g_Weapon_ball7(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word; WID
: Integer = -1;
1378 Silent
: Boolean = False);
1380 find_id
, FramesID
: DWORD
;
1384 find_id
:= FindShot()
1388 if Integer(find_id
) >= High(Shots
) then
1389 SetLength(Shots
, find_id
+ 64)
1392 with Shots
[find_id
] do
1396 Obj
.Rect
.Width
:= 32;
1397 Obj
.Rect
.Height
:= 16;
1399 dx
:= IfThen(xd
>x
, -Obj
.Rect
.Width
, 0);
1400 dy
:= -(Obj
.Rect
.Height
div 2);
1401 throw(find_id
, x
+dx
, y
+dy
, xd
+dx
, yd
+dy
, 16);
1404 ShotType
:= WEAPON_BARON_FIRE
;
1405 g_Frames_Get(FramesID
, 'FRAMES_WEAPON_BARONFIRE');
1406 Animation
:= TAnimation
.Create(FramesID
, True, 4);
1409 Shots
[find_id
].SpawnerUID
:= SpawnerUID
;
1412 g_Sound_PlayExAt('SOUND_WEAPON_FIREBALL', x
, y
);
1415 procedure g_Weapon_aplasma(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word; WID
: Integer = -1;
1416 Silent
: Boolean = False);
1418 find_id
, FramesID
: DWORD
;
1422 find_id
:= FindShot()
1426 if Integer(find_id
) >= High(Shots
) then
1427 SetLength(Shots
, find_id
+ 64)
1430 with Shots
[find_id
] do
1434 Obj
.Rect
.Width
:= 16;
1435 Obj
.Rect
.Height
:= 16;
1437 dx
:= IfThen(xd
>x
, -Obj
.Rect
.Width
, 0);
1438 dy
:= -(Obj
.Rect
.Height
div 2);
1439 throw(find_id
, x
+dx
, y
+dy
, xd
+dx
, yd
+dy
, 16);
1442 ShotType
:= WEAPON_BSP_FIRE
;
1443 g_Frames_Get(FramesID
, 'FRAMES_WEAPON_BSPFIRE');
1444 Animation
:= TAnimation
.Create(FramesID
, True, 4);
1447 Shots
[find_id
].SpawnerUID
:= SpawnerUID
;
1450 g_Sound_PlayExAt('SOUND_WEAPON_FIREPLASMA', x
, y
);
1453 procedure g_Weapon_manfire(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word; WID
: Integer = -1;
1454 Silent
: Boolean = False);
1456 find_id
, FramesID
: DWORD
;
1460 find_id
:= FindShot()
1464 if Integer(find_id
) >= High(Shots
) then
1465 SetLength(Shots
, find_id
+ 64)
1468 with Shots
[find_id
] do
1472 Obj
.Rect
.Width
:= 32;
1473 Obj
.Rect
.Height
:= 32;
1475 dx
:= IfThen(xd
>x
, -Obj
.Rect
.Width
, 0);
1476 dy
:= -(Obj
.Rect
.Height
div 2);
1477 throw(find_id
, x
+dx
, y
+dy
, xd
+dx
, yd
+dy
, 16);
1480 ShotType
:= WEAPON_MANCUB_FIRE
;
1481 g_Frames_Get(FramesID
, 'FRAMES_WEAPON_MANCUBFIRE');
1482 Animation
:= TAnimation
.Create(FramesID
, True, 4);
1485 Shots
[find_id
].SpawnerUID
:= SpawnerUID
;
1488 g_Sound_PlayExAt('SOUND_WEAPON_FIREBALL', x
, y
);
1491 procedure g_Weapon_bfgshot(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word; WID
: Integer = -1;
1492 Silent
: Boolean = False);
1494 find_id
, FramesID
: DWORD
;
1498 find_id
:= FindShot()
1502 if Integer(find_id
) >= High(Shots
) then
1503 SetLength(Shots
, find_id
+ 64)
1506 with Shots
[find_id
] do
1510 Obj
.Rect
.Width
:= SHOT_BFG_WIDTH
;
1511 Obj
.Rect
.Height
:= SHOT_BFG_HEIGHT
;
1513 dx
:= IfThen(xd
>x
, -Obj
.Rect
.Width
, 0);
1514 dy
:= -(Obj
.Rect
.Height
div 2);
1515 throw(find_id
, x
+dx
, y
+dy
, xd
+dx
, yd
+dy
, 16);
1518 ShotType
:= WEAPON_BFG
;
1519 g_Frames_Get(FramesID
, 'FRAMES_WEAPON_BFG');
1520 Animation
:= TAnimation
.Create(FramesID
, True, 6);
1523 Shots
[find_id
].SpawnerUID
:= SpawnerUID
;
1526 g_Sound_PlayExAt('SOUND_WEAPON_FIREBFG', x
, y
);
1529 procedure g_Weapon_bfghit(x
, y
: Integer);
1534 if g_Frames_Get(ID
, 'FRAMES_BFGHIT') then
1536 Anim
:= TAnimation
.Create(ID
, False, 4);
1537 g_GFX_OnceAnim(x
-32, y
-32, Anim
);
1542 procedure g_Weapon_pistol(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word;
1543 Silent
: Boolean = False);
1546 g_Sound_PlayExAt('SOUND_WEAPON_FIREPISTOL', x
, y
);
1548 g_Weapon_gun(x
, y
, xd
, yd
, 1, 3, SpawnerUID
, True);
1549 if gGameSettings
.GameMode
in [GM_DM
, GM_TDM
, GM_CTF
] then
1551 g_Weapon_gun(x
, y
+1, xd
, yd
+1, 1, 3, SpawnerUID
, False);
1552 g_Weapon_gun(x
, y
-1, xd
, yd
-1, 1, 2, SpawnerUID
, False);
1556 procedure g_Weapon_mgun(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word;
1557 Silent
: Boolean = False);
1560 if gSoundEffectsDF
then g_Sound_PlayExAt('SOUND_WEAPON_FIRECGUN', x
, y
);
1562 g_Weapon_gun(x
, y
, xd
, yd
, 1, 3, SpawnerUID
, True);
1563 if (gGameSettings
.GameMode
in [GM_DM
, GM_TDM
, GM_CTF
]) and
1564 (g_GetUIDType(SpawnerUID
) = UID_PLAYER
) then
1566 g_Weapon_gun(x
, y
+1, xd
, yd
+1, 1, 2, SpawnerUID
, False);
1567 g_Weapon_gun(x
, y
-1, xd
, yd
-1, 1, 2, SpawnerUID
, False);
1571 procedure g_Weapon_shotgun(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word;
1572 Silent
: Boolean = False);
1577 if gSoundEffectsDF
then g_Sound_PlayExAt('SOUND_WEAPON_FIRESHOTGUN', x
, y
);
1581 j
:= Random(17)-8; // -8 .. 8
1582 g_Weapon_gun(x
, y
+j
, xd
, yd
+j
, IfThen(i
mod 2 <> 0, 1, 0), 3, SpawnerUID
, i
=0);
1586 procedure g_Weapon_dshotgun(x
, y
, xd
, yd
: Integer; SpawnerUID
: Word;
1587 Silent
: Boolean = False);
1592 g_Sound_PlayExAt('SOUND_WEAPON_FIRESHOTGUN2', x
, y
);
1594 if gGameSettings
.GameMode
in [GM_DM
, GM_TDM
, GM_CTF
] then a
:= 25 else a
:= 20;
1597 j
:= Random(41)-20; // -20 .. 20
1598 g_Weapon_gun(x
, y
+j
, xd
, yd
+j
, IfThen(i
mod 3 <> 0, 0, 1), 3, SpawnerUID
, i
=0);
1602 procedure g_Weapon_Update();
1604 i
, a
, h
, cx
, cy
, oldvx
, oldvy
: Integer;
1617 for i
:= 0 to High(Shots
) do
1619 if Shots
[i
].ShotType
= 0 then
1626 Timeout
:= Timeout
- 1;
1629 // Àêòèâèðîâàòü òðèããåðû ïî ïóòè (êðîìå óæå àêòèâèðîâàííûõ):
1630 if g_Game_IsServer
then
1631 t
:= g_Triggers_PressR(Obj
.X
, Obj
.Y
, Obj
.Rect
.Width
, Obj
.Rect
.Height
,
1632 SpawnerUID
, ACTIVATE_SHOT
, triggers
)
1638 // Ïîïîëíÿåì ñïèñîê àêòèâèðîâàííûõ òðèããåðîâ:
1639 if triggers
= nil then
1646 if not InDWArray(t
[a
], triggers
) then
1648 SetLength(triggers
, Length(triggers
)+1);
1649 triggers
[High(triggers
)] := t
[a
];
1654 // Àíèìàöèÿ ñíàðÿäà:
1655 if Animation
<> nil then
1659 spl
:= (ShotType
<> WEAPON_PLASMA
) and
1660 (ShotType
<> WEAPON_BFG
) and
1661 (ShotType
<> WEAPON_BSP_FIRE
);
1663 st
:= g_Obj_Move(@Obj
, False, spl
);
1665 if WordBool(st
and MOVE_FALLOUT
) or (Obj
.X
< -1000) or
1666 (Obj
.X
> gMapInfo
.Width
+1000) or (Obj
.Y
< -1000) then
1668 // Íà êëèåíòå ñêîðåå âñåãî è òàê óæå âûïàë.
1674 cx
:= Obj
.X
+ (Obj
.Rect
.Width
div 2);
1675 cy
:= Obj
.Y
+ (Obj
.Rect
.Height
div 2);
1678 WEAPON_ROCKETLAUNCHER
, WEAPON_SKEL_FIRE
: // Ðàêåòû è ñíàðÿäû Ñêåëåòà
1680 // Âûëåòåëà èç âîäû:
1681 if WordBool(st
and MOVE_HITAIR
) then
1682 g_Obj_SetSpeed(@Obj
, 12);
1684 // Â âîäå øëåéô - ïóçûðè, â âîçäóõå øëåéô - äûì:
1685 if WordBool(st
and MOVE_INWATER
) then
1686 g_GFX_Bubbles(Obj
.X
+(Obj
.Rect
.Width
div 2),
1687 Obj
.Y
+(Obj
.Rect
.Height
div 2),
1688 1+Random(3), 16, 16)
1690 if g_Frames_Get(_id
, 'FRAMES_SMOKE') then
1692 Anim
:= TAnimation
.Create(_id
, False, 3);
1694 g_GFX_OnceAnim(Obj
.X
-14+Random(9),
1695 Obj
.Y
+(Obj
.Rect
.Height
div 2)-20+Random(9),
1696 Anim
, ONCEANIM_SMOKE
);
1700 // Ïîïàëè â êîãî-òî èëè â ñòåíó:
1701 if WordBool(st
and (MOVE_HITWALL
or MOVE_HITLAND
or MOVE_HITCEIL
)) or
1702 (g_Weapon_Hit(@Obj
, 10, SpawnerUID
, HIT_SOME
, False) <> 0) or
1708 g_Weapon_Explode(cx
, cy
, 60, SpawnerUID
);
1710 if ShotType
= WEAPON_SKEL_FIRE
then
1711 begin // Âçðûâ ñíàðÿäà Ñêåëåòà
1712 if g_Frames_Get(TextureID
, 'FRAMES_EXPLODE_SKELFIRE') then
1714 Anim
:= TAnimation
.Create(TextureID
, False, 8);
1715 Anim
.Blending
:= False;
1716 g_GFX_OnceAnim((Obj
.X
+32)-58, (Obj
.Y
+8)-36, Anim
);
1721 begin // Âçðûâ Ðàêåòû
1722 if g_Frames_Get(TextureID
, 'FRAMES_EXPLODE_ROCKET') then
1724 Anim
:= TAnimation
.Create(TextureID
, False, 6);
1725 Anim
.Blending
:= False;
1726 g_GFX_OnceAnim(cx
-64, cy
-64, Anim
);
1731 g_Sound_PlayExAt('SOUND_WEAPON_EXPLODEROCKET', Obj
.X
, Obj
.Y
);
1736 if ShotType
= WEAPON_SKEL_FIRE
then
1737 begin // Ñàìîíàâîäêà ñíàðÿäà Ñêåëåòà:
1738 if GetPos(target
, @o
) then
1739 throw(i
, Obj
.X
, Obj
.Y
,
1740 o
.X
+o
.Rect
.X
+(o
.Rect
.Width
div 2)+o
.Vel
.X
+o
.Accel
.X
,
1741 o
.Y
+o
.Rect
.Y
+(o
.Rect
.Height
div 2)+o
.Vel
.Y
+o
.Accel
.Y
,
1746 WEAPON_PLASMA
, WEAPON_BSP_FIRE
: // Ïëàçìà, ïëàçìà Àðàõíàòðîíà
1748 // Ïîïàëà â âîäó - ýëåêòðîøîê ïî âîäå:
1749 if WordBool(st
and (MOVE_INWATER
or MOVE_HITWATER
)) then
1751 g_Sound_PlayExAt('SOUND_WEAPON_PLASMAWATER', Obj
.X
, Obj
.Y
);
1752 if g_Game_IsServer
then CheckTrap(i
, 10, HIT_ELECTRO
);
1758 if (ShotType
= WEAPON_PLASMA
) and
1759 (gGameSettings
.GameMode
in [GM_DM
, GM_TDM
, GM_CTF
]) then
1764 if ShotType
= WEAPON_BSP_FIRE
then
1767 // Ïîïàëè â êîãî-òî èëè â ñòåíó:
1768 if WordBool(st
and (MOVE_HITWALL
or MOVE_HITLAND
or MOVE_HITCEIL
)) or
1769 (g_Weapon_Hit(@Obj
, a
, SpawnerUID
, HIT_SOME
, False) <> 0) or
1772 if ShotType
= WEAPON_PLASMA
then
1773 s
:= 'FRAMES_EXPLODE_PLASMA'
1775 s
:= 'FRAMES_EXPLODE_BSPFIRE';
1778 if g_Frames_Get(TextureID
, s
) then
1780 Anim
:= TAnimation
.Create(TextureID
, False, 3);
1781 Anim
.Blending
:= False;
1782 g_GFX_OnceAnim(cx
-16, cy
-16, Anim
);
1786 g_Sound_PlayExAt('SOUND_WEAPON_EXPLODEPLASMA', Obj
.X
, Obj
.Y
);
1794 // Ïîïàëà â âîäó - ýëåêòðîøîê ïî âîäå:
1795 if WordBool(st
and (MOVE_INWATER
or MOVE_HITWATER
)) then
1797 g_Sound_PlayExAt('SOUND_WEAPON_BFGWATER', Obj
.X
, Obj
.Y
);
1798 if g_Game_IsServer
then CheckTrap(i
, 1000, HIT_ELECTRO
);
1803 // Ïîïàëè â êîãî-òî èëè â ñòåíó:
1804 if WordBool(st
and (MOVE_HITWALL
or MOVE_HITLAND
or MOVE_HITCEIL
)) or
1805 (g_Weapon_Hit(@Obj
, SHOT_BFG_DAMAGE
, SpawnerUID
, HIT_BFG
, False) <> 0) or
1809 if g_Game_IsServer
then g_Weapon_BFG9000(cx
, cy
, SpawnerUID
);
1812 if g_Frames_Get(TextureID
, 'FRAMES_EXPLODE_BFG') then
1814 Anim
:= TAnimation
.Create(TextureID
, False, 6);
1815 Anim
.Blending
:= False;
1816 g_GFX_OnceAnim(cx
-64, cy
-64, Anim
);
1820 g_Sound_PlayExAt('SOUND_WEAPON_EXPLODEBFG', Obj
.X
, Obj
.Y
);
1826 WEAPON_IMP_FIRE
, WEAPON_CACO_FIRE
, WEAPON_BARON_FIRE
: // Âûñòðåëû Áåñà, Êàêîäåìîíà Ðûöàðÿ/Áàðîíà àäà
1829 if WordBool(st
and MOVE_HITAIR
) then
1830 g_Obj_SetSpeed(@Obj
, 16);
1833 if ShotType
= WEAPON_IMP_FIRE
then
1836 if ShotType
= WEAPON_CACO_FIRE
then
1841 // Ïîïàëè â êîãî-òî èëè â ñòåíó:
1842 if WordBool(st
and (MOVE_HITWALL
or MOVE_HITLAND
or MOVE_HITCEIL
)) or
1843 (g_Weapon_Hit(@Obj
, a
, SpawnerUID
, HIT_SOME
) <> 0) or
1846 if ShotType
= WEAPON_IMP_FIRE
then
1847 s
:= 'FRAMES_EXPLODE_IMPFIRE'
1849 if ShotType
= WEAPON_CACO_FIRE
then
1850 s
:= 'FRAMES_EXPLODE_CACOFIRE'
1852 s
:= 'FRAMES_EXPLODE_BARONFIRE';
1855 if g_Frames_Get(TextureID
, s
) then
1857 Anim
:= TAnimation
.Create(TextureID
, False, 6);
1858 Anim
.Blending
:= False;
1859 g_GFX_OnceAnim(cx
-32, cy
-32, Anim
);
1863 g_Sound_PlayExAt('SOUND_WEAPON_EXPLODEBALL', Obj
.X
, Obj
.Y
);
1869 WEAPON_MANCUB_FIRE
: // Âûñòðåë Ìàíêóáóñà
1872 if WordBool(st
and MOVE_HITAIR
) then
1873 g_Obj_SetSpeed(@Obj
, 16);
1875 // Ïîïàëè â êîãî-òî èëè â ñòåíó:
1876 if WordBool(st
and (MOVE_HITWALL
or MOVE_HITLAND
or MOVE_HITCEIL
)) or
1877 (g_Weapon_Hit(@Obj
, 40, SpawnerUID
, HIT_SOME
, False) <> 0) or
1881 if g_Frames_Get(TextureID
, 'FRAMES_EXPLODE_ROCKET') then
1883 Anim
:= TAnimation
.Create(TextureID
, False, 6);
1884 Anim
.Blending
:= False;
1885 g_GFX_OnceAnim(cx
-64, cy
-64, Anim
);
1889 g_Sound_PlayExAt('SOUND_WEAPON_EXPLODEBALL', Obj
.X
, Obj
.Y
);
1894 end; // case ShotType of...
1896 // Åñëè ñíàðÿäà óæå íåò, óäàëÿåì àíèìàöèþ:
1897 if (ShotType
= 0) then
1899 if gGameSettings
.GameType
= GT_SERVER
then
1900 MH_SEND_DeleteShot(i
, Obj
.X
, Obj
.Y
, Loud
);
1904 else if (oldvx
<> Obj
.Vel
.X
) or (oldvy
<> Obj
.Vel
.Y
) then
1905 if gGameSettings
.GameType
= GT_SERVER
then
1906 MH_SEND_UpdateShot(i
);
1911 procedure g_Weapon_Draw();
1920 for i
:= 0 to High(Shots
) do
1921 if Shots
[i
].ShotType
<> 0 then
1924 if (Shots
[i
].ShotType
= WEAPON_ROCKETLAUNCHER
) or
1925 (Shots
[i
].ShotType
= WEAPON_BARON_FIRE
) or
1926 (Shots
[i
].ShotType
= WEAPON_MANCUB_FIRE
) or
1927 (Shots
[i
].ShotType
= WEAPON_SKEL_FIRE
) then
1928 a
:= -GetAngle2(Obj
.Vel
.X
, Obj
.Vel
.Y
)
1932 p
.X
:= Obj
.Rect
.Width
div 2;
1933 p
.Y
:= Obj
.Rect
.Height
div 2;
1935 if Animation
<> nil then
1937 if (Shots
[i
].ShotType
= WEAPON_BARON_FIRE
) or
1938 (Shots
[i
].ShotType
= WEAPON_MANCUB_FIRE
) or
1939 (Shots
[i
].ShotType
= WEAPON_SKEL_FIRE
) then
1940 Animation
.DrawEx(Obj
.X
, Obj
.Y
, M_NONE
, p
, a
)
1942 Animation
.Draw(Obj
.X
, Obj
.Y
, M_NONE
);
1946 if (Shots
[i
].ShotType
= WEAPON_ROCKETLAUNCHER
) then
1947 e_DrawAdv(TextureID
, Obj
.X
, Obj
.Y
, 0, True, False, a
, @p
, M_NONE
)
1949 e_Draw(TextureID
, Obj
.X
, Obj
.Y
, 0, True, False);
1952 if g_debug_Frames
then
1954 e_DrawQuad(Obj
.X
+Obj
.Rect
.X
,
1956 Obj
.X
+Obj
.Rect
.X
+Obj
.Rect
.Width
-1,
1957 Obj
.Y
+Obj
.Rect
.Y
+Obj
.Rect
.Height
-1,
1963 function g_Weapon_Danger(UID
: Word; X
, Y
: Integer; Width
, Height
: Word; Time
: Byte): Boolean;
1972 for a
:= 0 to High(Shots
) do
1973 if (Shots
[a
].ShotType
<> 0) and (Shots
[a
].SpawnerUID
<> UID
) then
1974 if ((Shots
[a
].Obj
.Vel
.Y
= 0) and (Shots
[a
].Obj
.Vel
.X
> 0) and (Shots
[a
].Obj
.X
< X
)) or
1975 (Shots
[a
].Obj
.Vel
.Y
= 0) and (Shots
[a
].Obj
.Vel
.X
< 0) and (Shots
[a
].Obj
.X
> X
) then
1976 if (Abs(X
-Shots
[a
].Obj
.X
) < Abs(Shots
[a
].Obj
.Vel
.X
*Time
)) and
1977 g_Collide(X
, Y
, Width
, Height
, X
, Shots
[a
].Obj
.Y
,
1978 Shots
[a
].Obj
.Rect
.Width
, Shots
[a
].Obj
.Rect
.Height
) and
1979 g_TraceVector(X
, Y
, Shots
[a
].Obj
.X
, Shots
[a
].Obj
.Y
) then
1986 procedure g_Weapon_SaveState(var Mem
: TBinMemoryWriter
);
1988 count
, i
, j
: Integer;
1991 // Ñ÷èòàåì êîëè÷åñòâî ñóùåñòâóþùèõ ñíàðÿäîâ:
1993 if Shots
<> nil then
1994 for i
:= 0 to High(Shots
) do
1995 if Shots
[i
].ShotType
<> 0 then
1998 Mem
:= TBinMemoryWriter
.Create((count
+1) * 80);
2000 // Êîëè÷åñòâî ñíàðÿäîâ:
2001 Mem
.WriteInt(count
);
2006 for i
:= 0 to High(Shots
) do
2007 if Shots
[i
].ShotType
<> 0 then
2009 // Ñèãíàòóðà ñíàðÿäà:
2010 dw
:= SHOT_SIGNATURE
; // 'SHOT'
2013 Mem
.WriteByte(Shots
[i
].ShotType
);
2015 Mem
.WriteWord(Shots
[i
].Target
);
2017 Mem
.WriteWord(Shots
[i
].SpawnerUID
);
2018 // Ðàçìåð ïîëÿ Triggers:
2019 dw
:= Length(Shots
[i
].Triggers
);
2021 // Òðèããåðû, àêòèâèðîâàííûå âûñòðåëîì:
2022 for j
:= 0 to Integer(dw
)-1 do
2023 Mem
.WriteDWORD(Shots
[i
].Triggers
[j
]);
2025 Obj_SaveState(@Shots
[i
].Obj
, Mem
);
2029 procedure g_Weapon_LoadState(var Mem
: TBinMemoryReader
);
2031 count
, i
, j
: Integer;
2037 // Êîëè÷åñòâî ñíàðÿäîâ:
2040 SetLength(Shots
, count
);
2045 for i
:= 0 to count
-1 do
2047 // Ñèãíàòóðà ñíàðÿäà:
2049 if dw
<> SHOT_SIGNATURE
then // 'SHOT'
2051 raise EBinSizeError
.Create('g_Weapons_LoadState: Wrong Shot Signature');
2054 Mem
.ReadByte(Shots
[i
].ShotType
);
2056 Mem
.ReadWord(Shots
[i
].Target
);
2058 Mem
.ReadWord(Shots
[i
].SpawnerUID
);
2059 // Ðàçìåð ïîëÿ Triggers:
2061 SetLength(Shots
[i
].Triggers
, dw
);
2062 // Òðèããåðû, àêòèâèðîâàííûå âûñòðåëîì:
2063 for j
:= 0 to Integer(dw
)-1 do
2064 Mem
.ReadDWORD(Shots
[i
].Triggers
[j
]);
2066 Obj_LoadState(@Shots
[i
].Obj
, Mem
);
2068 // Óñòàíîâêà òåêñòóðû èëè àíèìàöèè:
2069 Shots
[i
].TextureID
:= DWORD(-1);
2070 Shots
[i
].Animation
:= nil;
2072 case Shots
[i
].ShotType
of
2073 WEAPON_ROCKETLAUNCHER
, WEAPON_SKEL_FIRE
:
2075 g_Texture_Get('TEXTURE_WEAPON_ROCKET', Shots
[i
].TextureID
);
2079 g_Frames_Get(dw
, 'FRAMES_WEAPON_PLASMA');
2080 Shots
[i
].Animation
:= TAnimation
.Create(dw
, True, 5);
2084 g_Frames_Get(dw
, 'FRAMES_WEAPON_BFG');
2085 Shots
[i
].Animation
:= TAnimation
.Create(dw
, True, 6);
2089 g_Frames_Get(dw
, 'FRAMES_WEAPON_IMPFIRE');
2090 Shots
[i
].Animation
:= TAnimation
.Create(dw
, True, 4);
2094 g_Frames_Get(dw
, 'FRAMES_WEAPON_BSPFIRE');
2095 Shots
[i
].Animation
:= TAnimation
.Create(dw
, True, 4);
2099 g_Frames_Get(dw
, 'FRAMES_WEAPON_CACOFIRE');
2100 Shots
[i
].Animation
:= TAnimation
.Create(dw
, True, 4);
2104 g_Frames_Get(dw
, 'FRAMES_WEAPON_BARONFIRE');
2105 Shots
[i
].Animation
:= TAnimation
.Create(dw
, True, 4);
2109 g_Frames_Get(dw
, 'FRAMES_WEAPON_MANCUBFIRE');
2110 Shots
[i
].Animation
:= TAnimation
.Create(dw
, True, 4);
2116 procedure g_Weapon_DestroyShot(I
: Integer; X
, Y
: Integer; Loud
: Boolean = True);
2124 if (I
> High(Shots
)) or (I
< 0) then Exit
;
2128 if ShotType
= 0 then Exit
;
2131 cx
:= Obj
.X
+ (Obj
.Rect
.Width
div 2);
2132 cy
:= Obj
.Y
+ (Obj
.Rect
.Height
div 2);
2135 WEAPON_ROCKETLAUNCHER
, WEAPON_SKEL_FIRE
: // Ðàêåòû è ñíàðÿäû Ñêåëåòà
2139 if ShotType
= WEAPON_SKEL_FIRE
then
2140 begin // Âçðûâ ñíàðÿäà Ñêåëåòà
2141 if g_Frames_Get(TextureID
, 'FRAMES_EXPLODE_SKELFIRE') then
2143 Anim
:= TAnimation
.Create(TextureID
, False, 8);
2144 Anim
.Blending
:= False;
2145 g_GFX_OnceAnim((Obj
.X
+32)-32, (Obj
.Y
+8)-32, Anim
);
2150 begin // Âçðûâ Ðàêåòû
2151 if g_Frames_Get(TextureID
, 'FRAMES_EXPLODE_ROCKET') then
2153 Anim
:= TAnimation
.Create(TextureID
, False, 6);
2154 Anim
.Blending
:= False;
2155 g_GFX_OnceAnim(cx
-64, cy
-64, Anim
);
2159 g_Sound_PlayExAt('SOUND_WEAPON_EXPLODEROCKET', Obj
.X
, Obj
.Y
);
2163 WEAPON_PLASMA
, WEAPON_BSP_FIRE
: // Ïëàçìà, ïëàçìà Àðàõíàòðîíà
2165 if ShotType
= WEAPON_PLASMA
then
2166 s
:= 'FRAMES_EXPLODE_PLASMA'
2168 s
:= 'FRAMES_EXPLODE_BSPFIRE';
2170 if g_Frames_Get(TextureID
, s
) and loud
then
2172 Anim
:= TAnimation
.Create(TextureID
, False, 3);
2173 Anim
.Blending
:= False;
2174 g_GFX_OnceAnim(cx
-16, cy
-16, Anim
);
2177 g_Sound_PlayExAt('SOUND_WEAPON_EXPLODEPLASMA', Obj
.X
, Obj
.Y
);
2184 if g_Frames_Get(TextureID
, 'FRAMES_EXPLODE_BFG') and Loud
then
2186 Anim
:= TAnimation
.Create(TextureID
, False, 6);
2187 Anim
.Blending
:= False;
2188 g_GFX_OnceAnim(cx
-64, cy
-64, Anim
);
2191 g_Sound_PlayExAt('SOUND_WEAPON_EXPLODEBFG', Obj
.X
, Obj
.Y
);
2195 WEAPON_IMP_FIRE
, WEAPON_CACO_FIRE
, WEAPON_BARON_FIRE
: // Âûñòðåëû Áåñà, Êàêîäåìîíà Ðûöàðÿ/Áàðîíà àäà
2197 if ShotType
= WEAPON_IMP_FIRE
then
2198 s
:= 'FRAMES_EXPLODE_IMPFIRE'
2200 if ShotType
= WEAPON_CACO_FIRE
then
2201 s
:= 'FRAMES_EXPLODE_CACOFIRE'
2203 s
:= 'FRAMES_EXPLODE_BARONFIRE';
2205 if g_Frames_Get(TextureID
, s
) and Loud
then
2207 Anim
:= TAnimation
.Create(TextureID
, False, 6);
2208 Anim
.Blending
:= False;
2209 g_GFX_OnceAnim(cx
-32, cy
-32, Anim
);
2212 g_Sound_PlayExAt('SOUND_WEAPON_EXPLODEBALL', Obj
.X
, Obj
.Y
);
2216 WEAPON_MANCUB_FIRE
: // Âûñòðåë Ìàíêóáóñà
2218 if g_Frames_Get(TextureID
, 'FRAMES_EXPLODE_ROCKET') and Loud
then
2220 Anim
:= TAnimation
.Create(TextureID
, False, 6);
2221 Anim
.Blending
:= False;
2222 g_GFX_OnceAnim(cx
-64, cy
-64, Anim
);
2225 g_Sound_PlayExAt('SOUND_WEAPON_EXPLODEBALL', Obj
.X
, Obj
.Y
);
2228 end; // case ShotType of...