99864d94b148b56cf93e6bc1c643ff9217b002e2
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, version 3 of the License ONLY.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 {$INCLUDE ../shared/a_modes.inc}
26 SHELL_LAST
= SHELL_DBLSHELL
;
28 DefaultShellTimeout
= 60000;
29 DefaultShellMax
= 300;
40 procedure getMapBox (out x
, y
, w
, h
: Integer); inline;
41 procedure moveBy (dx
, dy
: Integer); inline;
43 procedure positionChanged (); inline; //WARNING! call this after entity position was changed, or coldet will not >
47 gShells
: Array of TShell
;
49 procedure g_Shells_SetMax (Count
: Word);
50 function g_Shells_GetMax (): Word;
52 procedure g_Shells_Create (fX
, fY
, dX
, dY
: Integer; T
: Byte);
53 procedure g_Shells_RemoveAll
;
54 procedure g_Shells_Update
;
58 uses SysUtils
, g_base
, g_game
, g_sound
;
61 SHELL_TIMEOUT
: Cardinal = DefaultShellTimeout
;
62 MaxShells
: Word = DefaultShellMax
;
63 CurrentShell
: Integer = 0;
65 procedure TShell
.getMapBox (out x
, y
, w
, h
: Integer); inline;
73 procedure TShell
.moveBy (dx
, dy
: Integer); inline;
75 if (dx
<> 0) or (dy
<> 0) then
83 procedure TShell
.positionChanged (); inline;
87 procedure g_Shells_SetMax (Count
: Word);
90 SetLength(gShells
, Count
);
91 if CurrentShell
>= Count
then
95 function g_Shells_GetMax (): Word;
100 procedure g_Shells_Create (fX
, fY
, dX
, dY
: Integer; T
: Byte);
102 if (gShells
= nil) or (Length(gShells
) = 0) then
105 with gShells
[CurrentShell
] do
110 if T
= SHELL_BULLET
then
113 Obj
.Rect
.Height
:= 2;
118 Obj
.Rect
.Height
:= 3;
124 g_Obj_Push(@Obj
, dX
+ Random(4)-Random(4), dY
-Random(4));
125 positionChanged(); // this updates spatial accelerators
126 RAngle
:= Random(360);
127 Timeout
:= gTime
+ SHELL_TIMEOUT
;
128 if CurrentShell
>= High(gShells
) then
135 procedure g_Shells_RemoveAll
;
138 if gShells
<> nil then
139 for i
:= 0 to High(gShells
) do
140 gShells
[i
].alive
:= false;
143 procedure g_Shells_SoundBounce(X
, Y
: Integer; T
: Byte);
147 if T
= SHELL_BULLET
then
148 g_Sound_PlayExAt('SOUND_PLAYER_CASING' + IntToStr(k
), X
, Y
)
150 g_Sound_PlayExAt('SOUND_PLAYER_SHELL' + IntToStr(k
), X
, Y
);
153 procedure g_Shells_Update
;
154 var i
: Integer; vel
: TPoint2i
; mr
: Word;
156 if gShells
= nil then
159 for i
:= 0 to High(gShells
) do
161 if gShells
[i
].alive
then
169 mr
:= g_Obj_Move(@Obj
, True, False, True);
170 positionChanged(); // this updates spatial accelerators
172 if WordBool(mr
and MOVE_FALLOUT
) or (gShells
[i
].Timeout
< gTime
) then
178 // Отлетает от удара о стену/потолок/пол:
179 if WordBool(mr
and MOVE_HITWALL
) then
181 Obj
.Vel
.X
:= -(vel
.X
div 2);
182 if not WordBool(mr
and MOVE_INWATER
) then
183 g_Shells_SoundBounce(Obj
.X
, Obj
.Y
, SType
);
185 if WordBool(mr
and (MOVE_HITCEIL
or MOVE_HITLAND
)) then
187 Obj
.Vel
.Y
:= -(vel
.Y
div 2);
188 if Obj
.Vel
.X
<> 0 then Obj
.Vel
.X
:= Obj
.Vel
.X
div 2;
189 if (Obj
.Vel
.X
= 0) and (Obj
.Vel
.Y
= 0) then
191 if RAngle
mod 90 <> 0 then
192 RAngle
:= (RAngle
div 90) * 90;
194 else if not WordBool(mr
and MOVE_INWATER
) then
195 g_Shells_SoundBounce(Obj
.X
, Obj
.Y
, SType
);
198 if (Obj
.Vel
.X
>= 0) then
200 RAngle
:= RAngle
+ Abs(Obj
.Vel
.X
)*8 + Abs(Obj
.Vel
.Y
);
201 if RAngle
>= 360 then
202 RAngle
:= RAngle
mod 360;
203 end else begin // Counter-clockwise
204 RAngle
:= RAngle
- Abs(Obj
.Vel
.X
)*8 - Abs(Obj
.Vel
.Y
);
206 RAngle
:= (360 - (Abs(RAngle
) mod 360)) mod 360;