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}
27 DefaultShellTimeout
= 60000;
28 DefaultShellMax
= 300;
39 procedure getMapBox (out x
, y
, w
, h
: Integer); inline;
40 procedure moveBy (dx
, dy
: Integer); inline;
42 procedure positionChanged (); inline; //WARNING! call this after entity position was changed, or coldet will not >
46 gShells
: Array of TShell
;
48 procedure g_Shells_SetMax (Count
: Word);
49 function g_Shells_GetMax (): Word;
51 procedure g_Shells_Create (fX
, fY
, dX
, dY
: Integer; T
: Byte);
52 procedure g_Shells_Update
;
56 uses SysUtils
, g_base
, g_game
, g_sound
;
59 SHELL_TIMEOUT
: Cardinal = DefaultShellTimeout
;
60 MaxShells
: Word = DefaultShellMax
;
61 CurrentShell
: Integer = 0;
63 procedure TShell
.getMapBox (out x
, y
, w
, h
: Integer); inline;
71 procedure TShell
.moveBy (dx
, dy
: Integer); inline;
73 if (dx
<> 0) or (dy
<> 0) then
81 procedure TShell
.positionChanged (); inline;
85 procedure g_Shells_SetMax (Count
: Word);
88 SetLength(gShells
, Count
);
89 if CurrentShell
>= Count
then
93 function g_Shells_GetMax (): Word;
98 procedure g_Shells_Create (fX
, fY
, dX
, dY
: Integer; T
: Byte);
100 if (gShells
= nil) or (Length(gShells
) = 0) then
103 with gShells
[CurrentShell
] do
108 if T
= SHELL_BULLET
then
111 Obj
.Rect
.Height
:= 2;
116 Obj
.Rect
.Height
:= 3;
122 g_Obj_Push(@Obj
, dX
+ Random(4)-Random(4), dY
-Random(4));
123 positionChanged(); // this updates spatial accelerators
124 RAngle
:= Random(360);
125 Timeout
:= gTime
+ SHELL_TIMEOUT
;
126 if CurrentShell
>= High(gShells
) then
133 procedure g_Shells_SoundBounce(X
, Y
: Integer; T
: Byte);
137 if T
= SHELL_BULLET
then
138 g_Sound_PlayExAt('SOUND_PLAYER_CASING' + IntToStr(k
), X
, Y
)
140 g_Sound_PlayExAt('SOUND_PLAYER_SHELL' + IntToStr(k
), X
, Y
);
143 procedure g_Shells_Update
;
144 var i
: Integer; vel
: TPoint2i
; mr
: Word;
146 if gShells
= nil then
149 for i
:= 0 to High(gShells
) do
151 if gShells
[i
].alive
then
159 mr
:= g_Obj_Move(@Obj
, True, False, True);
160 positionChanged(); // this updates spatial accelerators
162 if WordBool(mr
and MOVE_FALLOUT
) or (gShells
[i
].Timeout
< gTime
) then
168 // Отлетает от удара о стену/потолок/пол:
169 if WordBool(mr
and MOVE_HITWALL
) then
171 Obj
.Vel
.X
:= -(vel
.X
div 2);
172 if not WordBool(mr
and MOVE_INWATER
) then
173 g_Shells_SoundBounce(Obj
.X
, Obj
.Y
, SType
);
175 if WordBool(mr
and (MOVE_HITCEIL
or MOVE_HITLAND
)) then
177 Obj
.Vel
.Y
:= -(vel
.Y
div 2);
178 if Obj
.Vel
.X
<> 0 then Obj
.Vel
.X
:= Obj
.Vel
.X
div 2;
179 if (Obj
.Vel
.X
= 0) and (Obj
.Vel
.Y
= 0) then
181 if RAngle
mod 90 <> 0 then
182 RAngle
:= (RAngle
div 90) * 90;
184 else if not WordBool(mr
and MOVE_INWATER
) then
185 g_Shells_SoundBounce(Obj
.X
, Obj
.Y
, SType
);
188 if (Obj
.Vel
.X
>= 0) then
190 RAngle
:= RAngle
+ Abs(Obj
.Vel
.X
)*8 + Abs(Obj
.Vel
.Y
);
191 if RAngle
>= 360 then
192 RAngle
:= RAngle
mod 360;
193 end else begin // Counter-clockwise
194 RAngle
:= RAngle
- Abs(Obj
.Vel
.X
)*8 - Abs(Obj
.Vel
.Y
);
196 RAngle
:= (360 - (Abs(RAngle
) mod 360)) mod 360;