a22cd1702cc385dfdc506def039da18f0b757f2c
33 procedure g_Obj_Init(Obj
: PObj
);
34 function g_Obj_Move(Obj
: PObj
; Fallable
: Boolean; Splash
: Boolean; ClimbSlopes
: Boolean = False): Word;
35 function g_Obj_Collide(Obj1
, Obj2
: PObj
): Boolean; overload
;
36 function g_Obj_Collide(X
, Y
: Integer; Width
, Height
: Word; Obj
: PObj
): Boolean; overload
;
37 function g_Obj_CollidePoint(X
, Y
: Integer; Obj
: PObj
): Boolean;
38 function g_Obj_CollideLevel(Obj
: PObj
; XInc
, YInc
: Integer): Boolean;
39 function g_Obj_CollideStep(Obj
: PObj
; XInc
, YInc
: Integer): Boolean;
40 function g_Obj_CollideWater(Obj
: PObj
; XInc
, YInc
: Integer): Boolean;
41 function g_Obj_CollideLiquid(Obj
: PObj
; XInc
, YInc
: Integer): Boolean;
42 function g_Obj_CollidePanel(Obj
: PObj
; XInc
, YInc
: Integer; PanelType
: Word): Boolean;
43 function g_Obj_StayOnStep(Obj
: PObj
): Boolean;
44 procedure g_Obj_Push(Obj
: PObj
; VelX
, VelY
: Integer);
45 procedure g_Obj_PushA(Obj
: PObj
; Vel
: Integer; Angle
: SmallInt);
46 procedure g_Obj_SetSpeed(Obj
: PObj
; s
: Integer);
47 function z_dec(a
, b
: Integer): Integer;
48 function z_fdec(a
, b
: Double): Double;
51 gMon
: Boolean = False;
56 g_map
, g_basic
, Math
, g_player
, g_console
, SysUtils
,
57 g_sound
, g_gfx
, MAPDEF
, g_monsters
, g_game
, BinEditor
;
59 function g_Obj_StayOnStep(Obj
: PObj
): Boolean;
61 Result
:= not g_Map_CollidePanel(Obj
^.X
+Obj
^.Rect
.X
, Obj
^.Y
+Obj
^.Rect
.Y
+Obj
^.Rect
.Height
-1,
64 and g_Map_CollidePanel(Obj
^.X
+Obj
^.Rect
.X
, Obj
^.Y
+Obj
^.Rect
.Y
+Obj
^.Rect
.Height
,
69 function CollideLiquid(Obj
: PObj
; XInc
, YInc
: Integer): Boolean;
71 Result
:= g_Map_CollidePanel(Obj
^.X
+Obj
^.Rect
.X
+XInc
, Obj
^.Y
+Obj
^.Rect
.Y
+YInc
,
72 Obj
^.Rect
.Width
, Obj
^.Rect
.Height
*2 div 3,
73 PANEL_WATER
or PANEL_ACID1
or PANEL_ACID2
, False);
76 function CollideLift(Obj
: PObj
; XInc
, YInc
: Integer): Integer;
78 if g_Map_CollidePanel(Obj
^.X
+Obj
^.Rect
.X
+XInc
, Obj
^.Y
+Obj
^.Rect
.Y
+YInc
,
79 Obj
^.Rect
.Width
, Obj
^.Rect
.Height
,
80 PANEL_LIFTUP
, False) then
82 else if g_Map_CollidePanel(Obj
^.X
+Obj
^.Rect
.X
+XInc
, Obj
^.Y
+Obj
^.Rect
.Y
+YInc
,
83 Obj
^.Rect
.Width
, Obj
^.Rect
.Height
,
84 PANEL_LIFTDOWN
, False) then
90 function CollideHorLift(Obj
: PObj
; XInc
, YInc
: Integer): Integer;
94 left
:= g_Map_CollidePanel(Obj
^.X
+Obj
^.Rect
.X
+XInc
, Obj
^.Y
+Obj
^.Rect
.Y
+YInc
,
95 Obj
^.Rect
.Width
, Obj
^.Rect
.Height
,
96 PANEL_LIFTLEFT
, False);
97 right
:= g_Map_CollidePanel(Obj
^.X
+Obj
^.Rect
.X
+XInc
, Obj
^.Y
+Obj
^.Rect
.Y
+YInc
,
98 Obj
^.Rect
.Width
, Obj
^.Rect
.Height
,
99 PANEL_LIFTRIGHT
, False);
100 if left
and not right
then
102 else if right
and not left
then
108 function CollidePlayers(_Obj
: PObj
; XInc
, YInc
: Integer): Boolean;
114 if gPlayers
= nil then
117 for a
:= 0 to High(gPlayers
) do
118 if gPlayers
[a
] <> nil then
121 g_Collide(GameX
+PLAYER_RECT
.X
, GameY
+PLAYER_RECT
.Y
,
122 PLAYER_RECT
.Width
, PLAYER_RECT
.Height
,
123 _Obj
^.X
+_Obj
^.Rect
.X
+XInc
, _Obj
^.Y
+_Obj
^.Rect
.Y
+YInc
,
124 _Obj
^.Rect
.Width
, _Obj
^.Rect
.Height
) then
131 function CollideMonsters(Obj
: PObj
; XInc
, YInc
: Integer): Boolean;
137 if gMonsters
= nil then
140 for a
:= 0 to High(gMonsters
) do
141 if gMonsters
[a
] <> nil then
142 if gMonsters
[a
].Live
and
143 gMonsters
[a
].Collide(Obj
^.X
+Obj
^.Rect
.X
+XInc
, Obj
^.Y
+Obj
^.Rect
.Y
+YInc
,
144 Obj
^.Rect
.Width
, Obj
^.Rect
.Height
) then
151 function Blocked(Obj
: PObj
; XInc
, YInc
: Integer): Boolean;
153 Result
:= g_Map_CollidePanel(Obj
^.X
+Obj
^.Rect
.X
+XInc
, Obj
^.Y
+Obj
.Rect
.Y
+YInc
,
154 Obj
^.Rect
.Width
, Obj
^.Rect
.Height
,
155 PANEL_BLOCKMON
, False);
158 function g_Obj_CollideLevel(Obj
: PObj
; XInc
, YInc
: Integer): Boolean;
160 Result
:= g_Map_CollidePanel(Obj
^.X
+Obj
^.Rect
.X
+XInc
, Obj
^.Y
+Obj
.Rect
.Y
+YInc
,
161 Obj
^.Rect
.Width
, Obj
^.Rect
.Height
,
165 function g_Obj_CollideStep(Obj
: PObj
; XInc
, YInc
: Integer): Boolean;
167 Result
:= g_Map_CollidePanel(Obj
^.X
+Obj
^.Rect
.X
+XInc
, Obj
^.Y
+Obj
.Rect
.Y
+YInc
,
168 Obj
^.Rect
.Width
, Obj
^.Rect
.Height
,
172 function g_Obj_CollideWater(Obj
: PObj
; XInc
, YInc
: Integer): Boolean;
174 Result
:= g_Map_CollidePanel(Obj
^.X
+Obj
^.Rect
.X
+XInc
, Obj
^.Y
+Obj
.Rect
.Y
+YInc
,
175 Obj
^.Rect
.Width
, Obj
^.Rect
.Height
,
179 function g_Obj_CollideLiquid(Obj
: PObj
; XInc
, YInc
: Integer): Boolean;
181 Result
:= g_Map_CollidePanel(Obj
^.X
+Obj
^.Rect
.X
+XInc
, Obj
^.Y
+Obj
.Rect
.Y
+YInc
,
182 Obj
^.Rect
.Width
, Obj
^.Rect
.Height
,
183 PANEL_WATER
or PANEL_ACID1
or PANEL_ACID2
, False);
186 function g_Obj_CollidePanel(Obj
: PObj
; XInc
, YInc
: Integer; PanelType
: Word): Boolean;
188 Result
:= g_Map_CollidePanel(Obj
^.X
+Obj
^.Rect
.X
+XInc
, Obj
^.Y
+Obj
.Rect
.Y
+YInc
,
189 Obj
^.Rect
.Width
, Obj
^.Rect
.Height
,
193 procedure g_Obj_Splash(Obj
: PObj
; Color
: Byte);
197 MaxVel
:= Max(Abs(Obj
^.Vel
.X
), Abs(Obj
^.Vel
.Y
));
198 if MaxVel
> 4 then begin
200 g_Sound_PlayExAt('SOUND_GAME_BULK1', Obj
^.X
, Obj
^.Y
)
202 g_Sound_PlayExAt('SOUND_GAME_BULK2', Obj
^.X
, Obj
^.Y
);
205 g_GFX_Water(Obj
^.X
+Obj
^.Rect
.X
+(Obj
^.Rect
.Width
div 2),
206 Obj
^.Y
+Obj
^.Rect
.Y
+(Obj
^.Rect
.Height
div 2),
207 Min(5*(Abs(Obj
^.Vel
.X
)+Abs(Obj
^.Vel
.Y
)), 50),
208 -Obj
^.Vel
.X
, -Obj
^.Vel
.Y
,
209 Obj
^.Rect
.Width
, 16, Color
);
212 function move(Obj
: PObj
; dx
, dy
: Integer; ClimbSlopes
: Boolean): Word;
218 procedure slope(s
: Integer);
223 while g_Obj_CollideLevel(Obj
, sx
, 0) and (i
< 4) do
225 Obj
^.Y
:= Obj
^.Y
+ s
;
228 Obj
^.X
:= Obj
^.X
+ sx
;
231 function movex(): Boolean;
235 // Åñëè ìîíñòðó øàãíóòü â ñòîðîíó, à òàì áëîêìîí:
236 if gMon
and not WordBool(st
and MOVE_BLOCK
) then
237 if Blocked(Obj
, sx
, 0) then
238 st
:= st
or MOVE_BLOCK
;
240 // Åñëè øàãíóòü â ñòîðîíó, à òàì ñòåíà => øàãàòü íåëüçÿ:
241 if g_Obj_CollideLevel(Obj
, sx
, 0) then
243 if ClimbSlopes
and (Abs(dy
) < 2) then
246 if (not g_Obj_CollideLevel(Obj
, sx
, -12)) // çàáèðàåìñÿ íà 12 ïèêñåëåé âëåâî/âïðàâî
247 and g_Obj_CollidePanel(Obj
, 0, 1, PANEL_WALL
or PANEL_STEP
) // òîëüêî åñëè åñòü çåìëÿ ïîä íîãàìè
253 st
:= st
or MOVE_HITWALL
;
257 st
:= st
or MOVE_HITWALL
;
259 else // Òàì ñòåíû íåò
261 if CollideLiquid(Obj
, sx
, 0) then
262 begin // Åñëè øàãíóòü â ñòîðîíó, à òàì òåïåðü æèäêîñòü
263 if not WordBool(st
and MOVE_INWATER
) then
264 st
:= st
or MOVE_HITWATER
;
266 else // Åñëè øàãíóòü â ñòîðîíó, à òàì óæå íåò æèäêîñòè
267 if WordBool(st
and MOVE_INWATER
) then
268 st
:= st
or MOVE_HITAIR
;
271 Obj
^.X
:= Obj
^.X
+ sx
;
276 function movey(): Boolean;
280 // Åñëè ìîíñòðó øàãíóòü ïî âåðòèêàëè, à òàì áëîêìîí:
281 if gMon
and not WordBool(st
and MOVE_BLOCK
) then
282 if Blocked(Obj
, 0, sy
) then
283 st
:= st
or MOVE_BLOCK
;
285 // Åñëè øàãíóòü â ïî âåðòèêàëè, à òàì ñòåíà => øàãàòü íåëüçÿ:
286 // Èëè åñëè øàãíóòü âíèç, à òàì ñòóïåíü => øàãàòü íåëüçÿ:
287 if g_Obj_CollideLevel(Obj
, 0, sy
) or
288 ((sy
> 0) and g_Obj_StayOnStep(Obj
)) then
291 st
:= st
or MOVE_HITLAND
293 st
:= st
or MOVE_HITCEIL
;
295 else // Òàì ñòåíû íåò. È ñòóïåíè ñíèçó òîæå íåò
297 if CollideLiquid(Obj
, 0, sy
) then
298 begin // Åñëè øàãíóòü â ïî âåðòèêàëè, à òàì òåïåðü æèäêîñòü
299 if not WordBool(st
and MOVE_INWATER
) then
300 st
:= st
or MOVE_HITWATER
;
302 else // Åñëè øàãíóòü â ïî âåðòèêàëè, à òàì óæå íåò æèäêîñòè
303 if WordBool(st
and MOVE_INWATER
) then
304 st
:= st
or MOVE_HITAIR
;
307 Obj
^.Y
:= Obj
^.Y
+ sy
;
316 // Îáúåêò â æèäêîñòè:
317 if CollideLiquid(Obj
, 0, 0) then
318 st
:= st
or MOVE_INWATER
;
320 // Ìîíñòð â áëîêìîíå:
322 if Blocked(Obj
, 0, 0) then
323 st
:= st
or MOVE_BLOCK
;
325 // Äâèãàòüñÿ íå íàäî:
326 if (dx
= 0) and (dy
= 0) then
332 sx
:= g_basic
.Sign(dx
);
333 sy
:= g_basic
.Sign(dy
);
348 procedure g_Obj_Init(Obj
: PObj
);
350 ZeroMemory(Obj
, SizeOf(TObj
));
353 function g_Obj_Move(Obj
: PObj
; Fallable
: Boolean; Splash
: Boolean; ClimbSlopes
: Boolean = False): Word;
355 xv
, yv
, dx
, dy
: Integer;
362 // Ëèìèòû íà ñêîðîñòü è óñêîðåíèå
363 if Obj
^.Vel
.X
< -LIMIT_VEL
then Obj
^.Vel
.X
:= -LIMIT_VEL
364 else if Obj
^.Vel
.X
> LIMIT_VEL
then Obj
^.Vel
.X
:= LIMIT_VEL
;
365 if Obj
^.Vel
.Y
< -LIMIT_VEL
then Obj
^.Vel
.Y
:= -LIMIT_VEL
366 else if Obj
^.Vel
.Y
> LIMIT_VEL
then Obj
^.Vel
.Y
:= LIMIT_VEL
;
367 if Obj
^.Accel
.X
< -LIMIT_ACCEL
then Obj
^.Accel
.X
:= -LIMIT_ACCEL
368 else if Obj
^.Accel
.X
> LIMIT_ACCEL
then Obj
^.Accel
.X
:= LIMIT_ACCEL
;
369 if Obj
^.Accel
.Y
< -LIMIT_ACCEL
then Obj
^.Accel
.Y
:= -LIMIT_ACCEL
370 else if Obj
^.Accel
.Y
> LIMIT_ACCEL
then Obj
^.Accel
.Y
:= LIMIT_ACCEL
;
372 // Âûëåòåë çà íèæíþþ ãðàíèöó êàðòû:
373 if Obj
^.Y
> gMapInfo
.Height
+128 then
375 Result
:= MOVE_FALLOUT
;
379 // Ìåíÿåì ñêîðîñòü è óñêîðåíèå òîëüêî ïî ÷åòíûì êàäðàì:
380 c
:= gTime
mod (GAME_TICK
*2) <> 0;
385 case CollideLift(Obj
, 0, 0) of
388 Obj
^.Vel
.Y
:= Obj
^.Vel
.Y
- 1; // Ëèôò ââåðõ
389 if Obj
^.Vel
.Y
< -5 then
390 Obj
^.Vel
.Y
:= Obj
^.Vel
.Y
+ 1;
395 if Obj
^.Vel
.Y
> 5 then
396 Obj
^.Vel
.Y
:= Obj
^.Vel
.Y
- 1;
397 Obj
^.Vel
.Y
:= Obj
^.Vel
.Y
+ 1; // Ãðàâèòàöèÿ èëè ëèôò âíèç
403 Obj
^.Vel
.Y
:= Obj
^.Vel
.Y
+ 1; // Ãðàâèòàöèÿ
404 if Obj
^.Vel
.Y
> MAX_YV
then
405 Obj
^.Vel
.Y
:= Obj
^.Vel
.Y
- 1;
409 case CollideHorLift(Obj
, 0, 0) of
412 Obj
^.Vel
.X
:= Obj
^.Vel
.X
- 3; // Ëèôò ââåðõ
413 if Obj
^.Vel
.X
< -9 then
414 Obj
^.Vel
.X
:= Obj
^.Vel
.X
+ 3;
419 Obj
^.Vel
.X
:= Obj
^.Vel
.X
+ 3;
420 if Obj
^.Vel
.X
> 9 then
421 Obj
^.Vel
.X
:= Obj
^.Vel
.X
- 3;
423 // 0 is not needed here
426 inwater
:= CollideLiquid(Obj
, 0, 0);
429 xv
:= Abs(Obj
^.Vel
.X
)+1;
431 Obj
^.Vel
.X
:= z_dec(Obj
^.Vel
.X
, (xv
div 2)-2);
433 yv
:= Abs(Obj
^.Vel
.Y
)+1;
435 Obj
^.Vel
.Y
:= z_dec(Obj
^.Vel
.Y
, (yv
div 2)-2);
437 xv
:= Abs(Obj
^.Accel
.X
)+1;
439 Obj
^.Accel
.X
:= z_dec(Obj
^.Accel
.X
, (xv
div 2)-2);
441 yv
:= Abs(Obj
^.Accel
.Y
)+1;
443 Obj
^.Accel
.Y
:= z_dec(Obj
^.Accel
.Y
, (yv
div 2)-2);
446 // Óìåíüøàåì ïðèáàâêó ê ñêîðîñòè:
447 Obj
^.Accel
.X
:= z_dec(Obj
^.Accel
.X
, 1);
448 Obj
^.Accel
.Y
:= z_dec(Obj
^.Accel
.Y
, 1);
452 xv
:= Obj
^.Vel
.X
+ Obj
^.Accel
.X
;
453 yv
:= Obj
^.Vel
.Y
+ Obj
^.Accel
.Y
;
458 Result
:= move(Obj
, dx
, dy
, ClimbSlopes
);
460 // Áðûçãè (åñëè íóæíû):
462 if WordBool(Result
and MOVE_HITWATER
) then
464 wtx
:= g_Map_CollideLiquid_Texture(Obj
^.X
+Obj
^.Rect
.X
,
467 Obj
^.Rect
.Height
*2 div 3);
469 TEXTURE_SPECIAL_WATER
:
470 g_Obj_Splash(Obj
, 3);
471 TEXTURE_SPECIAL_ACID1
:
472 g_Obj_Splash(Obj
, 2);
473 TEXTURE_SPECIAL_ACID2
:
474 g_Obj_Splash(Obj
, 1);
478 g_Obj_Splash(Obj
, 0);
482 // Ìåíÿåì ñêîðîñòü è óñêîðåíèå òîëüêî ïî ÷åòíûì êàäðàì:
486 // Âðåçàëèñü â ñòåíó - ñòîï:
487 if WordBool(Result
and MOVE_HITWALL
) then
493 // Âðåçàëèñü â ïîë èëè ïîòîëîê - ñòîï:
494 if WordBool(Result
and (MOVE_HITCEIL
or MOVE_HITLAND
)) then
501 function g_Obj_Collide(Obj1
, Obj2
: PObj
): Boolean;
503 Result
:= g_Collide(Obj1
^.X
+Obj1
^.Rect
.X
, Obj1
^.Y
+Obj1
^.Rect
.Y
,
504 Obj1
^.Rect
.Width
, Obj1
^.Rect
.Height
,
505 Obj2
^.X
+Obj2
^.Rect
.X
, Obj2
^.Y
+Obj2
^.Rect
.Y
,
506 Obj2
^.Rect
.Width
, Obj2
^.Rect
.Height
);
509 function g_Obj_Collide(X
, Y
: Integer; Width
, Height
: Word; Obj
: PObj
): Boolean;
511 Result
:= g_Collide(X
, Y
,
513 Obj
^.X
+Obj
^.Rect
.X
, Obj
^.Y
+Obj
^.Rect
.Y
,
514 Obj
^.Rect
.Width
, Obj
^.Rect
.Height
);
517 function g_Obj_CollidePoint(X
, Y
: Integer; Obj
: PObj
): Boolean;
519 Result
:= g_CollidePoint(X
, Y
, Obj
^.X
+Obj
^.Rect
.X
, Obj
^.Y
+Obj
^.Rect
.Y
,
520 Obj
^.Rect
.Width
, Obj
^.Rect
.Height
);
523 procedure g_Obj_Push(Obj
: PObj
; VelX
, VelY
: Integer);
525 Obj
^.Vel
.X
:= Obj
^.Vel
.X
+ VelX
;
526 Obj
^.Vel
.Y
:= Obj
^.Vel
.Y
+ VelY
;
529 procedure g_Obj_PushA(Obj
: PObj
; Vel
: Integer; Angle
: SmallInt);
534 SinCos(DegToRad(-Angle
), s
, c
);
536 Obj
^.Vel
.X
:= Obj
^.Vel
.X
+ Round(Vel
*c
);
537 Obj
^.Vel
.Y
:= Obj
^.Vel
.Y
+ Round(Vel
*s
);
540 procedure g_Obj_SetSpeed(Obj
: PObj
; s
: Integer);
547 m
:= Max(Abs(vx
), Abs(vy
));
551 Obj
^.Vel
.X
:= (vx
*s
) div m
;
552 Obj
^.Vel
.Y
:= (vy
*s
) div m
;
555 function z_dec(a
, b
: Integer): Integer;
557 // Ïðèáëèæàåì a ê 0 íà b åäèíèö:
570 function z_fdec(a
, b
: Double): Double;
572 // Ïðèáëèæàåì a ê 0.0 íà b åäèíèö: