25a2dd7bfe6ea22e51efe94dc9a5ecc84bc3d286
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}
20 uses g_player
, e_graphics
; // TPlayer, TRGB
22 procedure r_Player_DrawAll
;
23 procedure r_Player_DrawDebug (p
: TPlayer
);
24 procedure r_Player_DrawHealth
;
26 procedure r_Player_DrawCorpses
;
27 procedure r_Player_DrawShells
;
29 procedure r_Player_Draw (p
: TPlayer
);
30 procedure r_Player_DrawIndicator (p
: TPlayer
; Color
: TRGB
);
31 procedure r_Player_DrawBubble (p
: TPlayer
);
32 procedure r_Player_DrawAim (p
: TPlayer
);
33 procedure r_Player_DrawGUI (pl
: TPlayer
);
34 procedure r_Player_DrawRulez (p
: TPlayer
);
35 procedure r_Player_DrawPain (p
: TPlayer
);
36 procedure r_Player_DrawPickup (p
: TPlayer
);
38 procedure r_Player_DrawCorpse (p
: TCorpse
);
43 SysUtils
, Classes
, Math
,
45 g_basic
, g_game
, g_phys
, g_map
, g_textures
, g_menu
, g_language
, g_weapons
, g_items
, g_net
, g_options
,
49 procedure r_Player_DrawAll
;
52 if gPlayers
<> nil then
53 for i
:= 0 to High(gPlayers
) do
54 if gPlayers
[i
] <> nil then
55 r_Player_Draw(gPlayers
[i
])
58 procedure r_Player_DrawDebug (p
: TPlayer
);
63 if (@p
.Obj
) = nil then Exit
;
65 e_TextureFontGetSize(gStdFont
, fW
, fH
);
67 e_TextureFontPrint(0, 0 , 'Pos X: ' + IntToStr(p
.Obj
.X
), gStdFont
);
68 e_TextureFontPrint(0, fH
, 'Pos Y: ' + IntToStr(p
.Obj
.Y
), gStdFont
);
69 e_TextureFontPrint(0, fH
* 2, 'Vel X: ' + IntToStr(p
.Obj
.Vel
.X
), gStdFont
);
70 e_TextureFontPrint(0, fH
* 3, 'Vel Y: ' + IntToStr(p
.Obj
.Vel
.Y
), gStdFont
);
71 e_TextureFontPrint(0, fH
* 4, 'Acc X: ' + IntToStr(p
.Obj
.Accel
.X
), gStdFont
);
72 e_TextureFontPrint(0, fH
* 5, 'Acc Y: ' + IntToStr(p
.Obj
.Accel
.Y
), gStdFont
);
73 e_TextureFontPrint(0, fH
* 6, 'Old X: ' + IntToStr(p
.Obj
.oldX
), gStdFont
);
74 e_TextureFontPrint(0, fH
* 7, 'Old Y: ' + IntToStr(p
.Obj
.oldY
), gStdFont
);
77 procedure r_Player_DrawHealth
;
82 if gPlayers
= nil then Exit
;
83 e_TextureFontGetSize(gStdFont
, fW
, fH
);
85 for i
:= 0 to High(gPlayers
) do
86 if gPlayers
[i
] <> nil then
88 e_TextureFontPrint(gPlayers
[i
].Obj
.X
+ gPlayers
[i
].Obj
.Rect
.X
,
89 gPlayers
[i
].Obj
.Y
+ gPlayers
[i
].Obj
.Rect
.Y
+ gPlayers
[i
].Obj
.Rect
.Height
- fH
* 2,
90 IntToStr(gPlayers
[i
].Health
), gStdFont
);
91 e_TextureFontPrint(gPlayers
[i
].Obj
.X
+ gPlayers
[i
].Obj
.Rect
.X
,
92 gPlayers
[i
].Obj
.Y
+ gPlayers
[i
].Obj
.Rect
.Y
+ gPlayers
[i
].Obj
.Rect
.Height
- fH
,
93 IntToStr(gPlayers
[i
].Armor
), gStdFont
);
97 procedure r_Player_DrawCorpses
;
103 for i
:= 0 to High(gGibs
) do
104 if gGibs
[i
].alive
then
107 if not g_Obj_Collide(sX
, sY
, sWidth
, sHeight
, @Obj
) then
110 Obj
.lerp(gLerpFactor
, fX
, fY
);
112 a
.X
:= Obj
.Rect
.X
+(Obj
.Rect
.Width
div 2);
113 a
.y
:= Obj
.Rect
.Y
+(Obj
.Rect
.Height
div 2);
115 e_DrawAdv(ID
, fX
, fY
, 0, True, False, RAngle
, @a
, TMirrorType
.None
);
118 e_DrawAdv(MaskID
, fX
, fY
, 0, True, False, RAngle
, @a
, TMirrorType
.None
);
124 if gCorpses
<> nil then
125 for i
:= 0 to High(gCorpses
) do
126 if gCorpses
[i
] <> nil then
127 r_Player_DrawCorpse(gCorpses
[i
])
130 procedure r_Player_DrawShells
;
135 if gShells
<> nil then
136 for i
:= 0 to High(gShells
) do
137 if gShells
[i
].alive
then
140 if not g_Obj_Collide(sX
, sY
, sWidth
, sHeight
, @Obj
) then
143 Obj
.lerp(gLerpFactor
, fX
, fY
);
148 e_DrawAdv(SpriteID
, fX
, fY
, 0, True, False, RAngle
, @a
, TMirrorType
.None
);
152 procedure r_Player_DrawIndicator (p
: TPlayer
; Color
: TRGB
);
154 indX
, indY
, fX
, fY
, fSlope
: Integer;
164 p
.Obj
.lerp(gLerpFactor
, fX
, fY
);
165 fSlope
:= nlerp(p
.SlopeOld
, p
.Obj
.slopeUpLeft
, gLerpFactor
);
167 case gPlayerIndicatorStyle
of
170 if g_Texture_Get('TEXTURE_PLAYER_INDICATOR', ID
) then
172 e_GetTextureSize(ID
, @indW
, @indH
);
176 if (p
.Obj
.X
+ p
.Obj
.Rect
.X
) < 0 then
179 indX
:= fX
+ p
.Obj
.Rect
.X
+ p
.Obj
.Rect
.Width
;
180 indY
:= fY
+ p
.Obj
.Rect
.Y
+ (p
.Obj
.Rect
.Height
- indW
) div 2;
183 else if (p
.Obj
.X
+ p
.Obj
.Rect
.X
+ p
.Obj
.Rect
.Width
) > Max(gMapInfo
.Width
, gPlayerScreenSize
.X
) then
186 indX
:= fX
+ p
.Obj
.Rect
.X
- indH
;
187 indY
:= fY
+ p
.Obj
.Rect
.Y
+ (p
.Obj
.Rect
.Height
- indW
) div 2;
190 else if (p
.Obj
.Y
- indH
) < 0 then
193 indX
:= fX
+ p
.Obj
.Rect
.X
+ (p
.Obj
.Rect
.Width
- indW
) div 2;
194 indY
:= fY
+ p
.Obj
.Rect
.Y
+ p
.Obj
.Rect
.Height
;
200 indX
:= fX
+ p
.Obj
.Rect
.X
+ (p
.Obj
.Rect
.Width
- indW
) div 2;
204 indY
:= indY
+ fSlope
;
205 indX
:= EnsureRange(indX
, 0, Max(gMapInfo
.Width
, gPlayerScreenSize
.X
) - indW
);
206 indY
:= EnsureRange(indY
, 0, Max(gMapInfo
.Height
, gPlayerScreenSize
.Y
) - indH
);
210 e_DrawAdv(ID
, indX
, indY
, 0, True, False, indA
, @a
);
217 e_TextureFontGetSize(gStdFont
, nW
, nH
);
218 indX
:= fX
+ p
.Obj
.Rect
.X
+ (p
.Obj
.Rect
.Width
- Length(p
.Name
) * nW
) div 2;
219 indY
:= fY
- nH
+ fSlope
;
220 e_TextureFontPrintEx(indX
, indY
, p
.Name
, gStdFont
, Color
.R
, Color
.G
, Color
.B
, 1.0, True);
226 procedure r_Player_DrawBubble (p
: TPlayer
);
228 bubX
, bubY
, fX
, fY
: Integer;
231 Rw
, Gw
, Bw
: SmallInt;
235 CObj
:= p
.getCameraObj();
236 CObj
.lerp(gLerpFactor
, fX
, fY
);
237 // NB: _F_Obj.Rect is used to keep the bubble higher; this is not a mistake
238 bubX
:= fX
+ p
.Obj
.Rect
.X
+ IfThen(p
.Direction
= TDirection
.D_LEFT
, -4, 18);
239 bubY
:= fY
+ p
.Obj
.Rect
.Y
- 18;
247 1: // simple textual non-bubble
249 bubX
:= fX
+ p
.Obj
.Rect
.X
- 11;
250 bubY
:= fY
+ p
.Obj
.Rect
.Y
- 17;
251 e_TextureFontPrint(bubX
, bubY
, '[...]', gStdFont
);
254 2: // advanced pixel-perfect bubble
256 if p
.Team
= TEAM_RED
then
259 if p
.Team
= TEAM_BLUE
then
264 Rb
:= p
.Model
.Color
.R
;
265 Gb
:= p
.Model
.Color
.G
;
266 Bb
:= p
.Model
.Color
.B
;
267 Rw
:= Min(Rb
* 2 + 64, 255);
268 Gw
:= Min(Gb
* 2 + 64, 255);
269 Bw
:= Min(Bb
* 2 + 64, 255);
270 if (Abs(Rw
- Rb
) < 32)
271 or (Abs(Gw
- Gb
) < 32)
272 or (Abs(Bw
- Bb
) < 32) then
274 Rb
:= Max(Rw
div 2 - 16, 0);
275 Gb
:= Max(Gw
div 2 - 16, 0);
276 Bb
:= Max(Bw
div 2 - 16, 0);
279 4: // custom textured bubble
281 if g_Texture_Get('TEXTURE_PLAYER_TALKBUBBLE', ID
) then
282 if p
.Direction
= TDirection
.D_RIGHT
then
283 e_Draw(ID
, bubX
- 6, bubY
- 7, 0, True, False)
285 e_Draw(ID
, bubX
- 6, bubY
- 7, 0, True, False, TMirrorType
.Horizontal
);
291 e_DrawQuad(bubX
+ 1, bubY
, bubX
+ 18, bubY
+ 13, Rb
, Gb
, Bb
);
292 e_DrawQuad(bubX
, bubY
+ 1, bubX
+ 19, bubY
+ 12, Rb
, Gb
, Bb
);
294 e_DrawFillQuad(bubX
+ 1, bubY
+ 1, bubX
+ 18, bubY
+ 12, Rw
, Gw
, Bw
, 0);
297 Dot
:= IfThen(p
.Direction
= TDirection
.D_LEFT
, 14, 5);
298 e_DrawLine(1, bubX
+ Dot
, bubY
+ 14, bubX
+ Dot
, bubY
+ 16, Rb
, Gb
, Bb
);
299 e_DrawLine(1, bubX
+ IfThen(p
.Direction
= TDirection
.D_LEFT
, Dot
- 1, Dot
+ 1), bubY
+ 13, bubX
+ IfThen(p
.Direction
= TDirection
.D_LEFT
, Dot
- 1, Dot
+ 1), bubY
+ 15, Rw
, Gw
, Bw
);
300 e_DrawLine(1, bubX
+ IfThen(p
.Direction
= TDirection
.D_LEFT
, Dot
- 2, Dot
+ 2), bubY
+ 13, bubX
+ IfThen(p
.Direction
= TDirection
.D_LEFT
, Dot
- 2, Dot
+ 2), bubY
+ 14, Rw
, Gw
, Bw
);
301 e_DrawLine(1, bubX
+ IfThen(p
.Direction
= TDirection
.D_LEFT
, Dot
- 3, Dot
+ 3), bubY
+ 13, bubX
+ IfThen(p
.Direction
= TDirection
.D_LEFT
, Dot
- 3, Dot
+ 3), bubY
+ 13, Rw
, Gw
, Bw
);
302 e_DrawLine(1, bubX
+ IfThen(p
.Direction
= TDirection
.D_LEFT
, Dot
- 3, Dot
+ 3), bubY
+ 14, bubX
+ IfThen(p
.Direction
= TDirection
.D_LEFT
, Dot
- 1, Dot
+ 1), bubY
+ 16, Rb
, Gb
, Bb
);
306 e_DrawFillQuad(bubX
+ Dot
, bubY
+ 8, bubX
+ Dot
+ 1, bubY
+ 9, Rb
, Gb
, Bb
, 0);
307 e_DrawFillQuad(bubX
+ Dot
+ 3, bubY
+ 8, bubX
+ Dot
+ 4, bubY
+ 9, Rb
, Gb
, Bb
, 0);
308 e_DrawFillQuad(bubX
+ Dot
+ 6, bubY
+ 8, bubX
+ Dot
+ 7, bubY
+ 9, Rb
, Gb
, Bb
, 0);
311 procedure r_Player_Draw (p
: TPlayer
);
317 fX
, fY
, fSlope
: Integer;
319 p
.Obj
.lerp(gLerpFactor
, fX
, fY
);
320 fSlope
:= nlerp(p
.SlopeOld
, p
.Obj
.slopeUpLeft
, gLerpFactor
);
324 if p
.Direction
= TDirection
.D_RIGHT
then
325 Mirror
:= TMirrorType
.None
327 Mirror
:= TMirrorType
.Horizontal
;
329 if p
.PunchAnim
<> nil then
331 p
.PunchAnim
.Draw(fX
+ IfThen(p
.Direction
= TDirection
.D_LEFT
, 15 - p
.Obj
.Rect
.X
, p
.Obj
.Rect
.X
- 15), fY
+ fSlope
+ p
.Obj
.Rect
.Y
- 11, Mirror
);
332 if p
.PunchAnim
.played
then
339 if (p
.FMegaRulez
[MR_INVUL
] > gTime
) and ((gPlayerDrawn
<> p
) or (p
.SpawnInvul
>= gTime
)) then
340 if g_Texture_Get('TEXTURE_PLAYER_INVULPENTA', ID
) then
342 e_GetTextureSize(ID
, @w
, @h
);
343 if p
.Direction
= TDirection
.D_LEFT
then
344 e_Draw(ID
, fX
+ p
.Obj
.Rect
.X
+ (p
.Obj
.Rect
.Width
div 2) - (w
div 2) + 4,
345 fY
+ p
.Obj
.Rect
.Y
+ (p
.Obj
.Rect
.Height
div 2) - (h
div 2) - 7 + fSlope
, 0, True, False)
347 e_Draw(ID
, fX
+ p
.Obj
.Rect
.X
+ (p
.Obj
.Rect
.Width
div 2) - (w
div 2) - 2,
348 fY
+ p
.Obj
.Rect
.Y
+ (p
.Obj
.Rect
.Height
div 2) - (h
div 2) - 7 + fSlope
, 0, True, False)
351 if p
.FMegaRulez
[MR_INVIS
] > gTime
then
353 if (gPlayerDrawn
<> nil) and ((p
= gPlayerDrawn
) or
354 ((p
.Team
= gPlayerDrawn
.Team
) and (gGameSettings
.GameMode
<> GM_DM
))) then
356 if (p
.FMegaRulez
[MR_INVIS
] - gTime
) <= 2100 then
357 dr
:= not Odd((p
.FMegaRulez
[MR_INVIS
] - gTime
) div 300)
361 r_PlayerModel_Draw(p
.Model
, fX
, fY
+ fSlope
, 200)
363 r_PlayerModel_Draw(p
.Model
, fX
, fY
+ fSlope
);
366 r_PlayerModel_Draw(p
.Model
, fX
, fY
+ fSlope
, 254);
369 r_PlayerModel_Draw(p
.Model
, fX
, fY
+ fSlope
);
372 if g_debug_Frames
then
374 e_DrawQuad(p
.Obj
.X
+ p
.Obj
.Rect
.X
,
375 p
.Obj
.Y
+ p
.Obj
.Rect
.Y
,
376 p
.Obj
.X
+ p
.Obj
.Rect
.X
+ p
.Obj
.Rect
.Width
- 1,
377 p
.Obj
.Y
+ p
.Obj
.Rect
.Y
+ p
.Obj
.Rect
.Height
- 1,
381 if (gChatBubble
> 0) and (p
.FKeys
[KEY_CHAT
].Pressed
) and not p
.Ghost
then
382 if (p
.FMegaRulez
[MR_INVIS
] <= gTime
) or ((gPlayerDrawn
<> nil) and ((p
= gPlayerDrawn
) or
383 ((p
.Team
= gPlayerDrawn
.Team
) and (gGameSettings
.GameMode
<> GM_DM
)))) then
384 r_Player_DrawBubble(p
);
386 // e_DrawPoint(5, 335, 288, 255, 0, 0); // DL, UR, DL, UR
387 if gAimLine
and p
.Alive
and ((p
= gPlayer1
) or (p
= gPlayer2
)) then
391 procedure r_Player_DrawAim (p
: TPlayer
);
393 procedure drawCast (sz
: Integer; ax0
, ay0
, ax1
, ay1
: Integer);
398 {$IFDEF ENABLE_HOLMES}
399 if isValidViewPort
and (self
= gPlayer1
) then
401 g_Holmes_plrLaser(ax0
, ay0
, ax1
, ay1
);
405 e_DrawLine(sz
, ax0
, ay0
, ax1
, ay1
, 255, 0, 0, 96);
406 if (g_Map_traceToNearestWall(ax0
, ay0
, ax1
, ay1
, @ex
, @ey
) <> nil) then
408 e_DrawLine(sz
, ax0
, ay0
, ex
, ey
, 0, 255, 0, 96);
412 e_DrawLine(sz
, ax0
, ay0
, ex
, ey
, 0, 0, 255, 96);
417 wx
, wy
, xx
, yy
: Integer;
421 wx
:= p
.Obj
.X
+ WEAPONPOINT
[p
.Direction
].X
+ IfThen(p
.Direction
= TDirection
.D_LEFT
, 7, -7);
422 wy
:= p
.Obj
.Y
+ WEAPONPOINT
[p
.Direction
].Y
;
438 if angle
= ANGLE_RIGHTUP
then Dec(angle
, 2);
439 if angle
= ANGLE_RIGHTDOWN
then Inc(angle
, 4);
440 if angle
= ANGLE_LEFTUP
then Inc(angle
, 2);
441 if angle
= ANGLE_LEFTDOWN
then Dec(angle
, 4);
446 if angle
= ANGLE_RIGHTUP
then Dec(angle
, 2);
447 if angle
= ANGLE_RIGHTDOWN
then Inc(angle
, 4);
448 if angle
= ANGLE_LEFTUP
then Inc(angle
, 2);
449 if angle
= ANGLE_LEFTDOWN
then Dec(angle
, 4);
451 4: begin // Double Shotgun
454 if angle
= ANGLE_RIGHTUP
then Dec(angle
, 2);
455 if angle
= ANGLE_RIGHTDOWN
then Inc(angle
, 4);
456 if angle
= ANGLE_LEFTUP
then Inc(angle
, 2);
457 if angle
= ANGLE_LEFTDOWN
then Dec(angle
, 4);
462 if angle
= ANGLE_RIGHTUP
then Dec(angle
, 2);
463 if angle
= ANGLE_RIGHTDOWN
then Inc(angle
, 4);
464 if angle
= ANGLE_LEFTUP
then Inc(angle
, 2);
465 if angle
= ANGLE_LEFTDOWN
then Dec(angle
, 4);
467 6: begin // Rocket Launcher
470 if angle
= ANGLE_RIGHTUP
then Inc(angle
, 2);
471 if angle
= ANGLE_RIGHTDOWN
then Inc(angle
, 4);
472 if angle
= ANGLE_LEFTUP
then Dec(angle
, 2);
473 if angle
= ANGLE_LEFTDOWN
then Dec(angle
, 4);
475 7: begin // Plasmagun
478 if angle
= ANGLE_RIGHTUP
then Inc(angle
);
479 if angle
= ANGLE_RIGHTDOWN
then Inc(angle
, 3);
480 if angle
= ANGLE_LEFTUP
then Dec(angle
);
481 if angle
= ANGLE_LEFTDOWN
then Dec(angle
, 3);
486 if angle
= ANGLE_RIGHTUP
then Inc(angle
, 1);
487 if angle
= ANGLE_RIGHTDOWN
then Inc(angle
, 2);
488 if angle
= ANGLE_LEFTUP
then Dec(angle
, 1);
489 if angle
= ANGLE_LEFTDOWN
then Dec(angle
, 2);
491 9: begin // Super Chaingun
494 if angle
= ANGLE_RIGHTUP
then Dec(angle
, 2);
495 if angle
= ANGLE_RIGHTDOWN
then Inc(angle
, 4);
496 if angle
= ANGLE_LEFTUP
then Inc(angle
, 2);
497 if angle
= ANGLE_LEFTDOWN
then Dec(angle
, 4);
500 xx
:= Trunc(Cos(-DegToRad(angle
)) * len
) + wx
;
501 yy
:= Trunc(Sin(-DegToRad(angle
)) * len
) + wy
;
502 {$IF DEFINED(D2F_DEBUG)}
503 drawCast(sz
, wx
, wy
, xx
, yy
);
505 e_DrawLine(sz
, wx
, wy
, xx
, yy
, 255, 0, 0, 96);
509 procedure r_Player_DrawGUI (pl
: TPlayer
);
512 X
, Y
, SY
, a
, p
, m
: Integer;
516 stat
: TPlayerStatArray
;
518 X
:= gPlayerScreenSize
.X
;
519 SY
:= gPlayerScreenSize
.Y
;
522 if gShowGoals
and (gGameSettings
.GameMode
in [GM_TDM
, GM_CTF
]) then
524 if gGameSettings
.GameMode
= GM_CTF
then
528 if gGameSettings
.GameMode
= GM_CTF
then
530 s
:= 'TEXTURE_PLAYER_REDFLAG';
531 if gFlags
[FLAG_RED
].State
= FLAG_STATE_CAPTURED
then
532 s
:= 'TEXTURE_PLAYER_REDFLAG_S';
533 if gFlags
[FLAG_RED
].State
= FLAG_STATE_DROPPED
then
534 s
:= 'TEXTURE_PLAYER_REDFLAG_D';
535 if g_Texture_Get(s
, ID
) then
536 e_Draw(ID
, X
-16-32, 240-72-4, 0, True, False);
539 s
:= IntToStr(gTeamStat
[TEAM_RED
].Goals
);
540 e_CharFont_GetSize(gMenuFont
, s
, tw
, th
);
541 e_CharFont_PrintEx(gMenuFont
, X
-16-a
-tw
, 240-72-4, s
, TEAMCOLOR
[TEAM_RED
]);
543 if gGameSettings
.GameMode
= GM_CTF
then
545 s
:= 'TEXTURE_PLAYER_BLUEFLAG';
546 if gFlags
[FLAG_BLUE
].State
= FLAG_STATE_CAPTURED
then
547 s
:= 'TEXTURE_PLAYER_BLUEFLAG_S';
548 if gFlags
[FLAG_BLUE
].State
= FLAG_STATE_DROPPED
then
549 s
:= 'TEXTURE_PLAYER_BLUEFLAG_D';
550 if g_Texture_Get(s
, ID
) then
551 e_Draw(ID
, X
-16-32, 240-32-4, 0, True, False);
554 s
:= IntToStr(gTeamStat
[TEAM_BLUE
].Goals
);
555 e_CharFont_GetSize(gMenuFont
, s
, tw
, th
);
556 e_CharFont_PrintEx(gMenuFont
, X
-16-a
-tw
, 240-32-4, s
, TEAMCOLOR
[TEAM_BLUE
]);
559 if g_Texture_Get('TEXTURE_PLAYER_HUDBG', ID
) then
560 e_DrawFill(ID
, X
, 0, 1, (gPlayerScreenSize
.Y
div 256)+IfThen(gPlayerScreenSize
.Y
mod 256 > 0, 1, 0),
563 if g_Texture_Get('TEXTURE_PLAYER_HUD', ID
) then
564 e_Draw(ID
, X
+2, Y
, 0, True, False);
566 if gGameSettings
.GameType
in [GT_CUSTOM
, GT_SERVER
, GT_CLIENT
] then
570 s
:= IntToStr(pl
.Frags
);
571 e_CharFont_GetSize(gMenuFont
, s
, tw
, th
);
572 e_CharFont_PrintEx(gMenuFont
, X
-16-tw
, Y
, s
, _RGB(255, 0, 0));
577 stat
:= g_Player_GetStats();
582 for a
:= 0 to High(stat
) do
583 if stat
[a
].Name
<> pl
.Name
then
585 if stat
[a
].Frags
> m
then m
:= stat
[a
].Frags
;
586 if stat
[a
].Frags
> pl
.Frags
then p
:= p
+1;
590 s
:= IntToStr(p
)+' / '+IntToStr(Length(stat
))+' ';
591 if pl
.Frags
>= m
then s
:= s
+'+' else s
:= s
+'-';
592 s
:= s
+IntToStr(Abs(pl
.Frags
-m
));
594 e_CharFont_GetSize(gMenuSmallFont
, s
, tw
, th
);
595 e_CharFont_PrintEx(gMenuSmallFont
, X
-16-tw
, Y
+32, s
, _RGB(255, 0, 0));
598 if gLMSRespawn
> LMS_RESPAWN_NONE
then
600 s
:= _lc
[I_GAME_WARMUP
];
601 e_CharFont_GetSize(gMenuFont
, s
, tw
, th
);
602 s
:= s
+ ': ' + IntToStr((gLMSRespawnTime
- gTime
) div 1000);
603 e_CharFont_PrintEx(gMenuFont
, X
-64-tw
, SY
-32, s
, _RGB(0, 255, 0));
605 else if gShowLives
and (gGameSettings
.MaxLives
> 0) then
607 s
:= IntToStr(pl
.Lives
);
608 e_CharFont_GetSize(gMenuFont
, s
, tw
, th
);
609 e_CharFont_PrintEx(gMenuFont
, X
-16-tw
, SY
-32, s
, _RGB(0, 255, 0));
613 e_CharFont_GetSize(gMenuSmallFont
, pl
.Name
, tw
, th
);
614 e_CharFont_PrintEx(gMenuSmallFont
, X
+98-(tw
div 2), Y
+8, pl
.Name
, _RGB(255, 0, 0));
616 if R_BERSERK
in pl
.FRulez
then
617 e_Draw(gItemsTexturesID
[ITEM_MEDKIT_BLACK
], X
+37, Y
+45, 0, True, False)
619 e_Draw(gItemsTexturesID
[ITEM_MEDKIT_LARGE
], X
+37, Y
+45, 0, True, False);
621 if g_Texture_Get('TEXTURE_PLAYER_ARMORHUD', ID
) then
622 e_Draw(ID
, X
+36, Y
+77, 0, True, False);
624 s
:= IntToStr(IfThen(pl
.Health
> 0, pl
.Health
, 0));
625 e_CharFont_GetSize(gMenuFont
, s
, tw
, th
);
626 e_CharFont_PrintEx(gMenuFont
, X
+178-tw
, Y
+40, s
, _RGB(255, 0, 0));
628 s
:= IntToStr(pl
.Armor
);
629 e_CharFont_GetSize(gMenuFont
, s
, tw
, th
);
630 e_CharFont_PrintEx(gMenuFont
, X
+178-tw
, Y
+68, s
, _RGB(255, 0, 0));
632 s
:= IntToStr(pl
.GetAmmoByWeapon(pl
.CurrWeap
));
638 ID
:= gItemsTexturesID
[ITEM_WEAPON_KASTET
];
643 ID
:= gItemsTexturesID
[ITEM_WEAPON_SAW
];
645 WEAPON_PISTOL
: ID
:= gItemsTexturesID
[ITEM_WEAPON_PISTOL
];
646 WEAPON_CHAINGUN
: ID
:= gItemsTexturesID
[ITEM_WEAPON_CHAINGUN
];
647 WEAPON_SHOTGUN1
: ID
:= gItemsTexturesID
[ITEM_WEAPON_SHOTGUN1
];
648 WEAPON_SHOTGUN2
: ID
:= gItemsTexturesID
[ITEM_WEAPON_SHOTGUN2
];
649 WEAPON_SUPERPULEMET
: ID
:= gItemsTexturesID
[ITEM_WEAPON_SUPERPULEMET
];
650 WEAPON_ROCKETLAUNCHER
: ID
:= gItemsTexturesID
[ITEM_WEAPON_ROCKETLAUNCHER
];
651 WEAPON_PLASMA
: ID
:= gItemsTexturesID
[ITEM_WEAPON_PLASMA
];
652 WEAPON_BFG
: ID
:= gItemsTexturesID
[ITEM_WEAPON_BFG
];
653 WEAPON_FLAMETHROWER
: ID
:= gItemsTexturesID
[ITEM_WEAPON_FLAMETHROWER
];
656 e_CharFont_GetSize(gMenuFont
, s
, tw
, th
);
657 e_CharFont_PrintEx(gMenuFont
, X
+178-tw
, Y
+158, s
, _RGB(255, 0, 0));
658 e_Draw(ID
, X
+20, Y
+160, 0, True, False);
660 if R_KEY_RED
in pl
.FRulez
then
661 e_Draw(gItemsTexturesID
[ITEM_KEY_RED
], X
+78, Y
+214, 0, True, False);
663 if R_KEY_GREEN
in pl
.FRulez
then
664 e_Draw(gItemsTexturesID
[ITEM_KEY_GREEN
], X
+95, Y
+214, 0, True, False);
666 if R_KEY_BLUE
in pl
.FRulez
then
667 e_Draw(gItemsTexturesID
[ITEM_KEY_BLUE
], X
+112, Y
+214, 0, True, False);
669 if pl
.JetFuel
> 0 then
671 if g_Texture_Get('TEXTURE_PLAYER_HUDAIR', ID
) then
672 e_Draw(ID
, X
+2, Y
+116, 0, True, False);
673 if g_Texture_Get('TEXTURE_PLAYER_HUDJET', ID
) then
674 e_Draw(ID
, X
+2, Y
+126, 0, True, False);
675 e_DrawLine(4, X
+16, Y
+122, X
+16+Trunc(168*IfThen(pl
.Air
> 0, pl
.Air
, 0)/AIR_MAX
), Y
+122, 0, 0, 196);
676 e_DrawLine(4, X
+16, Y
+132, X
+16+Trunc(168*pl
.JetFuel
/JET_MAX
), Y
+132, 208, 0, 0);
680 if g_Texture_Get('TEXTURE_PLAYER_HUDAIR', ID
) then
681 e_Draw(ID
, X
+2, Y
+124, 0, True, False);
682 e_DrawLine(4, X
+16, Y
+130, X
+16+Trunc(168*IfThen(pl
.Air
> 0, pl
.Air
, 0)/AIR_MAX
), Y
+130, 0, 0, 196);
685 if gShowPing
and g_Game_IsClient
then
687 s
:= _lc
[I_GAME_PING_HUD
] + IntToStr(NetPeer
.lastRoundTripTime
) + _lc
[I_NET_SLIST_PING_MS
];
688 e_TextureFontPrint(X
+ 4, Y
+ 242, s
, gStdFont
);
694 e_TextureFontPrint(X
+ 4, Y
+ 242, _lc
[I_PLAYER_SPECT
], gStdFont
);
695 e_TextureFontPrint(X
+ 4, Y
+ 258, _lc
[I_PLAYER_SPECT2
], gStdFont
);
696 e_TextureFontPrint(X
+ 4, Y
+ 274, _lc
[I_PLAYER_SPECT1
], gStdFont
);
699 e_TextureFontGetSize(gStdFont
, cw
, ch
);
700 s
:= _lc
[I_PLAYER_SPECT4
];
701 e_TextureFontPrintEx(gScreenWidth
div 2 - cw
*(Length(s
) div 2),
702 gScreenHeight
-4-ch
, s
, gStdFont
, 255, 255, 255, 1, True);
703 e_TextureFontPrint(X
+ 4, Y
+ 290, _lc
[I_PLAYER_SPECT1S
], gStdFont
);
709 procedure r_Player_DrawRulez (p
: TPlayer
);
713 // При взятии неуязвимости рисуется инверсионный белый фон
714 if (p
.FMegaRulez
[MR_INVUL
] >= gTime
) and (p
.SpawnInvul
< gTime
) then
716 if (p
.FMegaRulez
[MR_INVUL
]-gTime
) <= 2100 then
717 dr
:= not Odd((p
.FMegaRulez
[MR_INVUL
]-gTime
) div 300)
722 e_DrawFillQuad(0, 0, gPlayerScreenSize
.X
-1, gPlayerScreenSize
.Y
-1,
723 191, 191, 191, 0, TBlending
.Invert
);
726 // При взятии защитного костюма рисуется зеленоватый фон
727 if p
.FMegaRulez
[MR_SUIT
] >= gTime
then
729 if (p
.FMegaRulez
[MR_SUIT
]-gTime
) <= 2100 then
730 dr
:= not Odd((p
.FMegaRulez
[MR_SUIT
]-gTime
) div 300)
735 e_DrawFillQuad(0, 0, gPlayerScreenSize
.X
-1, gPlayerScreenSize
.Y
-1,
736 0, 96, 0, 200, TBlending
.None
);
739 // При взятии берсерка рисуется красноватый фон
740 if (p
.Berserk
>= 0) and (LongWord(p
.Berserk
) >= gTime
) and (gFlash
= 2) then
742 e_DrawFillQuad(0, 0, gPlayerScreenSize
.X
-1, gPlayerScreenSize
.Y
-1,
743 255, 0, 0, 200, TBlending
.None
);
747 procedure r_Player_DrawPain (p
: TPlayer
);
751 if p
.Pain
= 0 then Exit
;
755 if a
< 15 then h
:= 0
756 else if a
< 35 then h
:= 1
757 else if a
< 55 then h
:= 2
758 else if a
< 75 then h
:= 3
759 else if a
< 95 then h
:= 4
762 //if a > 255 then a := 255;
764 e_DrawFillQuad(0, 0, gPlayerScreenSize
.X
-1, gPlayerScreenSize
.Y
-1, 255, 0, 0, 255-h
*50);
765 //e_DrawFillQuad(0, 0, gPlayerScreenSize.X-1, gPlayerScreenSize.Y-1, 255-min(128, a), 255-a, 255-a, 0, B_FILTER);
768 procedure r_Player_DrawPickup (p
: TPlayer
);
772 if p
.Pickup
= 0 then Exit
;
776 if a
< 15 then h
:= 1
777 else if a
< 35 then h
:= 2
778 else if a
< 55 then h
:= 3
779 else if a
< 75 then h
:= 4
782 e_DrawFillQuad(0, 0, gPlayerScreenSize
.X
-1, gPlayerScreenSize
.Y
-1, 150, 200, 150, 255-h
*50);
785 procedure r_Player_DrawCorpse (p
: TCorpse
);
789 if p
.State
= CORPSE_STATE_REMOVEME
then
792 p
.Obj
.lerp(gLerpFactor
, fX
, fY
);
794 if p
.Animation
<> nil then
795 p
.Animation
.Draw(fX
, fY
, TMirrorType
.None
);
797 if p
.AnimationMask
<> nil then
800 p
.AnimationMask
.Draw(fX
, fY
, TMirrorType
.None
);