DEADSOFTWARE

28eaf3d8af3810ce0d6961110b4fe87d2e9aae6c
[d2df-sdl.git] / src / game / opengl / r_player.pas
1 (* Copyright (C) Doom 2D: Forever Developers
2 *
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.
6 *
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.
11 *
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/>.
14 *)
15 {$INCLUDE ../../shared/a_modes.inc}
16 unit r_player;
18 interface
20 uses g_player, g_base; // 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);
40 implementation
42 uses
43 SysUtils, Classes, Math,
44 MAPDEF, utils,
45 g_basic, g_game, g_phys, g_map, g_menu, g_language, g_weapons, g_items, g_net, g_options,
46 {$IFDEF ENABLE_HOLMES}
47 g_holmes,
48 {$ENDIF}
49 r_playermodel, r_graphics, r_animations, r_textures, r_items
50 ;
52 procedure r_Player_DrawAll;
53 var i: Integer;
54 begin
55 if gPlayers <> nil then
56 for i := 0 to High(gPlayers) do
57 if gPlayers[i] <> nil then
58 r_Player_Draw(gPlayers[i])
59 end;
61 procedure r_Player_DrawDebug (p: TPlayer);
62 var
63 fW, fH: Byte;
64 begin
65 if p = nil then Exit;
66 if (@p.Obj) = nil then Exit;
68 e_TextureFontGetSize(gStdFont, fW, fH);
70 e_TextureFontPrint(0, 0 , 'Pos X: ' + IntToStr(p.Obj.X), gStdFont);
71 e_TextureFontPrint(0, fH , 'Pos Y: ' + IntToStr(p.Obj.Y), gStdFont);
72 e_TextureFontPrint(0, fH * 2, 'Vel X: ' + IntToStr(p.Obj.Vel.X), gStdFont);
73 e_TextureFontPrint(0, fH * 3, 'Vel Y: ' + IntToStr(p.Obj.Vel.Y), gStdFont);
74 e_TextureFontPrint(0, fH * 4, 'Acc X: ' + IntToStr(p.Obj.Accel.X), gStdFont);
75 e_TextureFontPrint(0, fH * 5, 'Acc Y: ' + IntToStr(p.Obj.Accel.Y), gStdFont);
76 e_TextureFontPrint(0, fH * 6, 'Old X: ' + IntToStr(p.Obj.oldX), gStdFont);
77 e_TextureFontPrint(0, fH * 7, 'Old Y: ' + IntToStr(p.Obj.oldY), gStdFont);
78 end;
80 procedure r_Player_DrawHealth;
81 var
82 i: Integer;
83 fW, fH: Byte;
84 begin
85 if gPlayers = nil then Exit;
86 e_TextureFontGetSize(gStdFont, fW, fH);
88 for i := 0 to High(gPlayers) do
89 if gPlayers[i] <> nil then
90 begin
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 * 2,
93 IntToStr(gPlayers[i].Health), gStdFont);
94 e_TextureFontPrint(gPlayers[i].Obj.X + gPlayers[i].Obj.Rect.X,
95 gPlayers[i].Obj.Y + gPlayers[i].Obj.Rect.Y + gPlayers[i].Obj.Rect.Height - fH,
96 IntToStr(gPlayers[i].Armor), gStdFont);
97 end;
98 end;
100 procedure r_Player_DrawCorpses;
101 var i: Integer;
102 begin
103 if gCorpses <> nil then
104 for i := 0 to High(gCorpses) do
105 if gCorpses[i] <> nil then
106 r_Player_DrawCorpse(gCorpses[i])
107 end;
109 procedure r_Player_DrawShells;
110 var
111 i, fX, fY: Integer;
112 a: TDFPoint;
113 begin
114 if gShells <> nil then
115 for i := 0 to High(gShells) do
116 if gShells[i].alive then
117 with gShells[i] do
118 begin
119 if not g_Obj_Collide(sX, sY, sWidth, sHeight, @Obj) then
120 Continue;
122 Obj.lerp(gLerpFactor, fX, fY);
124 a.X := CX;
125 a.Y := CY;
127 e_DrawAdv(SpriteID, fX, fY, 0, True, False, RAngle, @a, TMirrorType.None);
128 end;
129 end;
131 procedure r_Player_DrawIndicator (p: TPlayer; Color: TRGB);
132 var
133 indX, indY, fX, fY, fSlope: Integer;
134 indW, indH: Word;
135 indA: Single;
136 a: TDFPoint;
137 nW, nH: Byte;
138 ID: DWORD;
139 c: TRGB;
140 begin
141 if p.Alive then
142 begin
143 p.Obj.lerp(gLerpFactor, fX, fY);
144 fSlope := nlerp(p.SlopeOld, p.Obj.slopeUpLeft, gLerpFactor);
146 case gPlayerIndicatorStyle of
147 0:
148 begin
149 if g_Texture_Get('TEXTURE_PLAYER_INDICATOR', ID) then
150 begin
151 e_GetTextureSize(ID, @indW, @indH);
152 a.X := indW div 2;
153 a.Y := indH div 2;
155 if (p.Obj.X + p.Obj.Rect.X) < 0 then
156 begin
157 indA := 90;
158 indX := fX + p.Obj.Rect.X + p.Obj.Rect.Width;
159 indY := fY + p.Obj.Rect.Y + (p.Obj.Rect.Height - indW) div 2;
160 end
162 else if (p.Obj.X + p.Obj.Rect.X + p.Obj.Rect.Width) > Max(gMapInfo.Width, gPlayerScreenSize.X) then
163 begin
164 indA := 270;
165 indX := fX + p.Obj.Rect.X - indH;
166 indY := fY + p.Obj.Rect.Y + (p.Obj.Rect.Height - indW) div 2;
167 end
169 else if (p.Obj.Y - indH) < 0 then
170 begin
171 indA := 180;
172 indX := fX + p.Obj.Rect.X + (p.Obj.Rect.Width - indW) div 2;
173 indY := fY + p.Obj.Rect.Y + p.Obj.Rect.Height;
174 end
176 else
177 begin
178 indA := 0;
179 indX := fX + p.Obj.Rect.X + (p.Obj.Rect.Width - indW) div 2;
180 indY := fY - indH;
181 end;
183 indY := indY + fSlope;
184 indX := EnsureRange(indX, 0, Max(gMapInfo.Width, gPlayerScreenSize.X) - indW);
185 indY := EnsureRange(indY, 0, Max(gMapInfo.Height, gPlayerScreenSize.Y) - indH);
187 c := e_Colors;
188 e_Colors := Color;
189 e_DrawAdv(ID, indX, indY, 0, True, False, indA, @a);
190 e_Colors := c;
191 end;
192 end;
194 1:
195 begin
196 e_TextureFontGetSize(gStdFont, nW, nH);
197 indX := fX + p.Obj.Rect.X + (p.Obj.Rect.Width - Length(p.Name) * nW) div 2;
198 indY := fY - nH + fSlope;
199 e_TextureFontPrintEx(indX, indY, p.Name, gStdFont, Color.R, Color.G, Color.B, 1.0, True);
200 end;
201 end;
202 end
203 end;
205 procedure r_Player_DrawBubble (p: TPlayer);
206 var
207 bubX, bubY, fX, fY: Integer;
208 ID: LongWord;
209 Rb, Gb, Bb,
210 Rw, Gw, Bw: SmallInt;
211 Dot: Byte;
212 CObj: TObj;
213 begin
214 CObj := p.getCameraObj();
215 CObj.lerp(gLerpFactor, fX, fY);
216 // NB: _F_Obj.Rect is used to keep the bubble higher; this is not a mistake
217 bubX := fX + p.Obj.Rect.X + IfThen(p.Direction = TDirection.D_LEFT, -4, 18);
218 bubY := fY + p.Obj.Rect.Y - 18;
219 Rb := 64;
220 Gb := 64;
221 Bb := 64;
222 Rw := 240;
223 Gw := 240;
224 Bw := 240;
225 case gChatBubble of
226 1: // simple textual non-bubble
227 begin
228 bubX := fX + p.Obj.Rect.X - 11;
229 bubY := fY + p.Obj.Rect.Y - 17;
230 e_TextureFontPrint(bubX, bubY, '[...]', gStdFont);
231 Exit;
232 end;
233 2: // advanced pixel-perfect bubble
234 begin
235 if p.Team = TEAM_RED then
236 Rb := 255
237 else
238 if p.Team = TEAM_BLUE then
239 Bb := 255;
240 end;
241 3: // colored bubble
242 begin
243 Rb := p.Model.Color.R;
244 Gb := p.Model.Color.G;
245 Bb := p.Model.Color.B;
246 Rw := Min(Rb * 2 + 64, 255);
247 Gw := Min(Gb * 2 + 64, 255);
248 Bw := Min(Bb * 2 + 64, 255);
249 if (Abs(Rw - Rb) < 32)
250 or (Abs(Gw - Gb) < 32)
251 or (Abs(Bw - Bb) < 32) then
252 begin
253 Rb := Max(Rw div 2 - 16, 0);
254 Gb := Max(Gw div 2 - 16, 0);
255 Bb := Max(Bw div 2 - 16, 0);
256 end;
257 end;
258 4: // custom textured bubble
259 begin
260 if g_Texture_Get('TEXTURE_PLAYER_TALKBUBBLE', ID) then
261 if p.Direction = TDirection.D_RIGHT then
262 e_Draw(ID, bubX - 6, bubY - 7, 0, True, False)
263 else
264 e_Draw(ID, bubX - 6, bubY - 7, 0, True, False, TMirrorType.Horizontal);
265 Exit;
266 end;
267 end;
269 // Outer borders
270 e_DrawQuad(bubX + 1, bubY , bubX + 18, bubY + 13, Rb, Gb, Bb);
271 e_DrawQuad(bubX , bubY + 1, bubX + 19, bubY + 12, Rb, Gb, Bb);
272 // Inner box
273 e_DrawFillQuad(bubX + 1, bubY + 1, bubX + 18, bubY + 12, Rw, Gw, Bw, 0);
275 // Tail
276 Dot := IfThen(p.Direction = TDirection.D_LEFT, 14, 5);
277 e_DrawLine(1, bubX + Dot, bubY + 14, bubX + Dot, bubY + 16, Rb, Gb, Bb);
278 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);
279 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);
280 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);
281 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);
283 // Dots
284 Dot := 6;
285 e_DrawFillQuad(bubX + Dot, bubY + 8, bubX + Dot + 1, bubY + 9, Rb, Gb, Bb, 0);
286 e_DrawFillQuad(bubX + Dot + 3, bubY + 8, bubX + Dot + 4, bubY + 9, Rb, Gb, Bb, 0);
287 e_DrawFillQuad(bubX + Dot + 6, bubY + 8, bubX + Dot + 7, bubY + 9, Rb, Gb, Bb, 0);
288 end;
290 procedure r_Player_Draw (p: TPlayer);
291 var
292 ID: DWORD;
293 w, h: Word;
294 dr: Boolean;
295 Mirror: TMirrorType;
296 fX, fY, fSlope: Integer;
297 begin
298 p.Obj.lerp(gLerpFactor, fX, fY);
299 fSlope := nlerp(p.SlopeOld, p.Obj.slopeUpLeft, gLerpFactor);
301 if p.Alive then
302 begin
303 if p.Direction = TDirection.D_RIGHT then
304 Mirror := TMirrorType.None
305 else
306 Mirror := TMirrorType.Horizontal;
308 if p.PunchAnim <> nil then
309 begin
310 r_Animation_Draw(p.PunchAnim, 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);
311 if p.PunchAnim.played then
312 begin
313 p.PunchAnim.Free;
314 p.PunchAnim := nil;
315 end;
316 end;
318 if (p.FMegaRulez[MR_INVUL] > gTime) and ((gPlayerDrawn <> p) or (p.SpawnInvul >= gTime)) then
319 if g_Texture_Get('TEXTURE_PLAYER_INVULPENTA', ID) then
320 begin
321 e_GetTextureSize(ID, @w, @h);
322 if p.Direction = TDirection.D_LEFT then
323 e_Draw(ID, fX + p.Obj.Rect.X + (p.Obj.Rect.Width div 2) - (w div 2) + 4,
324 fY + p.Obj.Rect.Y + (p.Obj.Rect.Height div 2) - (h div 2) - 7 + fSlope, 0, True, False)
325 else
326 e_Draw(ID, fX + p.Obj.Rect.X + (p.Obj.Rect.Width div 2) - (w div 2) - 2,
327 fY + p.Obj.Rect.Y + (p.Obj.Rect.Height div 2) - (h div 2) - 7 + fSlope, 0, True, False)
328 end;
330 if p.FMegaRulez[MR_INVIS] > gTime then
331 begin
332 if (gPlayerDrawn <> nil) and ((p = gPlayerDrawn) or
333 ((p.Team = gPlayerDrawn.Team) and (gGameSettings.GameMode <> GM_DM))) then
334 begin
335 if (p.FMegaRulez[MR_INVIS] - gTime) <= 2100 then
336 dr := not Odd((p.FMegaRulez[MR_INVIS] - gTime) div 300)
337 else
338 dr := True;
339 if dr then
340 r_PlayerModel_Draw(p.Model, fX, fY + fSlope, 200)
341 else
342 r_PlayerModel_Draw(p.Model, fX, fY + fSlope);
343 end
344 else
345 r_PlayerModel_Draw(p.Model, fX, fY + fSlope, 254);
346 end
347 else
348 r_PlayerModel_Draw(p.Model, fX, fY + fSlope);
349 end;
351 if g_debug_Frames then
352 begin
353 e_DrawQuad(p.Obj.X + p.Obj.Rect.X,
354 p.Obj.Y + p.Obj.Rect.Y,
355 p.Obj.X + p.Obj.Rect.X + p.Obj.Rect.Width - 1,
356 p.Obj.Y + p.Obj.Rect.Y + p.Obj.Rect.Height - 1,
357 0, 255, 0);
358 end;
360 if (gChatBubble > 0) and (p.FKeys[KEY_CHAT].Pressed) and not p.Ghost then
361 if (p.FMegaRulez[MR_INVIS] <= gTime) or ((gPlayerDrawn <> nil) and ((p = gPlayerDrawn) or
362 ((p.Team = gPlayerDrawn.Team) and (gGameSettings.GameMode <> GM_DM)))) then
363 r_Player_DrawBubble(p);
365 // e_DrawPoint(5, 335, 288, 255, 0, 0); // DL, UR, DL, UR
366 if gAimLine and p.Alive and ((p = gPlayer1) or (p = gPlayer2)) then
367 r_Player_DrawAim(p);
368 end;
370 procedure r_Player_DrawAim (p: TPlayer);
372 procedure drawCast (sz: Integer; ax0, ay0, ax1, ay1: Integer);
373 var
374 ex, ey: Integer;
375 begin
377 {$IFDEF ENABLE_HOLMES}
378 if p.isValidViewPort() and (p = gPlayer1) then
379 begin
380 g_Holmes_plrLaser(ax0, ay0, ax1, ay1);
381 end;
382 {$ENDIF}
384 e_DrawLine(sz, ax0, ay0, ax1, ay1, 255, 0, 0, 96);
385 if (g_Map_traceToNearestWall(ax0, ay0, ax1, ay1, @ex, @ey) <> nil) then
386 begin
387 e_DrawLine(sz, ax0, ay0, ex, ey, 0, 255, 0, 96);
388 end
389 else
390 begin
391 e_DrawLine(sz, ax0, ay0, ex, ey, 0, 0, 255, 96);
392 end;
393 end;
395 var
396 wx, wy, xx, yy: Integer;
397 angle: SmallInt;
398 sz, len: Word;
399 begin
400 wx := p.Obj.X + WEAPONPOINT[p.Direction].X + IfThen(p.Direction = TDirection.D_LEFT, 7, -7);
401 wy := p.Obj.Y + WEAPONPOINT[p.Direction].Y;
402 angle := p.Angle_;
403 len := 1024;
404 sz := 2;
405 case p.CurrWeap of
406 0: begin // Punch
407 len := 12;
408 sz := 4;
409 end;
410 1: begin // Chainsaw
411 len := 24;
412 sz := 6;
413 end;
414 2: begin // Pistol
415 len := 1024;
416 sz := 2;
417 if angle = ANGLE_RIGHTUP then Dec(angle, 2);
418 if angle = ANGLE_RIGHTDOWN then Inc(angle, 4);
419 if angle = ANGLE_LEFTUP then Inc(angle, 2);
420 if angle = ANGLE_LEFTDOWN then Dec(angle, 4);
421 end;
422 3: begin // Shotgun
423 len := 1024;
424 sz := 3;
425 if angle = ANGLE_RIGHTUP then Dec(angle, 2);
426 if angle = ANGLE_RIGHTDOWN then Inc(angle, 4);
427 if angle = ANGLE_LEFTUP then Inc(angle, 2);
428 if angle = ANGLE_LEFTDOWN then Dec(angle, 4);
429 end;
430 4: begin // Double Shotgun
431 len := 1024;
432 sz := 4;
433 if angle = ANGLE_RIGHTUP then Dec(angle, 2);
434 if angle = ANGLE_RIGHTDOWN then Inc(angle, 4);
435 if angle = ANGLE_LEFTUP then Inc(angle, 2);
436 if angle = ANGLE_LEFTDOWN then Dec(angle, 4);
437 end;
438 5: begin // Chaingun
439 len := 1024;
440 sz := 3;
441 if angle = ANGLE_RIGHTUP then Dec(angle, 2);
442 if angle = ANGLE_RIGHTDOWN then Inc(angle, 4);
443 if angle = ANGLE_LEFTUP then Inc(angle, 2);
444 if angle = ANGLE_LEFTDOWN then Dec(angle, 4);
445 end;
446 6: begin // Rocket Launcher
447 len := 1024;
448 sz := 7;
449 if angle = ANGLE_RIGHTUP then Inc(angle, 2);
450 if angle = ANGLE_RIGHTDOWN then Inc(angle, 4);
451 if angle = ANGLE_LEFTUP then Dec(angle, 2);
452 if angle = ANGLE_LEFTDOWN then Dec(angle, 4);
453 end;
454 7: begin // Plasmagun
455 len := 1024;
456 sz := 5;
457 if angle = ANGLE_RIGHTUP then Inc(angle);
458 if angle = ANGLE_RIGHTDOWN then Inc(angle, 3);
459 if angle = ANGLE_LEFTUP then Dec(angle);
460 if angle = ANGLE_LEFTDOWN then Dec(angle, 3);
461 end;
462 8: begin // BFG
463 len := 1024;
464 sz := 12;
465 if angle = ANGLE_RIGHTUP then Inc(angle, 1);
466 if angle = ANGLE_RIGHTDOWN then Inc(angle, 2);
467 if angle = ANGLE_LEFTUP then Dec(angle, 1);
468 if angle = ANGLE_LEFTDOWN then Dec(angle, 2);
469 end;
470 9: begin // Super Chaingun
471 len := 1024;
472 sz := 4;
473 if angle = ANGLE_RIGHTUP then Dec(angle, 2);
474 if angle = ANGLE_RIGHTDOWN then Inc(angle, 4);
475 if angle = ANGLE_LEFTUP then Inc(angle, 2);
476 if angle = ANGLE_LEFTDOWN then Dec(angle, 4);
477 end;
478 end;
479 xx := Trunc(Cos(-DegToRad(angle)) * len) + wx;
480 yy := Trunc(Sin(-DegToRad(angle)) * len) + wy;
481 {$IF DEFINED(D2F_DEBUG)}
482 drawCast(sz, wx, wy, xx, yy);
483 {$ELSE}
484 e_DrawLine(sz, wx, wy, xx, yy, 255, 0, 0, 96);
485 {$ENDIF}
486 end;
488 procedure r_Player_DrawGUI (pl: TPlayer);
489 var
490 ID: DWORD;
491 X, Y, SY, a, p, m: Integer;
492 tw, th: Word;
493 cw, ch: Byte;
494 s: string;
495 stat: TPlayerStatArray;
496 begin
497 X := gPlayerScreenSize.X;
498 SY := gPlayerScreenSize.Y;
499 Y := 0;
501 if gShowGoals and (gGameSettings.GameMode in [GM_TDM, GM_CTF]) then
502 begin
503 if gGameSettings.GameMode = GM_CTF then
504 a := 32 + 8
505 else
506 a := 0;
507 if gGameSettings.GameMode = GM_CTF then
508 begin
509 s := 'TEXTURE_PLAYER_REDFLAG';
510 if gFlags[FLAG_RED].State = FLAG_STATE_CAPTURED then
511 s := 'TEXTURE_PLAYER_REDFLAG_S';
512 if gFlags[FLAG_RED].State = FLAG_STATE_DROPPED then
513 s := 'TEXTURE_PLAYER_REDFLAG_D';
514 if g_Texture_Get(s, ID) then
515 e_Draw(ID, X-16-32, 240-72-4, 0, True, False);
516 end;
518 s := IntToStr(gTeamStat[TEAM_RED].Goals);
519 e_CharFont_GetSize(gMenuFont, s, tw, th);
520 e_CharFont_PrintEx(gMenuFont, X-16-a-tw, 240-72-4, s, TEAMCOLOR[TEAM_RED]);
522 if gGameSettings.GameMode = GM_CTF then
523 begin
524 s := 'TEXTURE_PLAYER_BLUEFLAG';
525 if gFlags[FLAG_BLUE].State = FLAG_STATE_CAPTURED then
526 s := 'TEXTURE_PLAYER_BLUEFLAG_S';
527 if gFlags[FLAG_BLUE].State = FLAG_STATE_DROPPED then
528 s := 'TEXTURE_PLAYER_BLUEFLAG_D';
529 if g_Texture_Get(s, ID) then
530 e_Draw(ID, X-16-32, 240-32-4, 0, True, False);
531 end;
533 s := IntToStr(gTeamStat[TEAM_BLUE].Goals);
534 e_CharFont_GetSize(gMenuFont, s, tw, th);
535 e_CharFont_PrintEx(gMenuFont, X-16-a-tw, 240-32-4, s, TEAMCOLOR[TEAM_BLUE]);
536 end;
538 if g_Texture_Get('TEXTURE_PLAYER_HUDBG', ID) then
539 e_DrawFill(ID, X, 0, 1, (gPlayerScreenSize.Y div 256)+IfThen(gPlayerScreenSize.Y mod 256 > 0, 1, 0),
540 0, False, False);
542 if g_Texture_Get('TEXTURE_PLAYER_HUD', ID) then
543 e_Draw(ID, X+2, Y, 0, True, False);
545 if gGameSettings.GameType in [GT_CUSTOM, GT_SERVER, GT_CLIENT] then
546 begin
547 if gShowStat then
548 begin
549 s := IntToStr(pl.Frags);
550 e_CharFont_GetSize(gMenuFont, s, tw, th);
551 e_CharFont_PrintEx(gMenuFont, X-16-tw, Y, s, _RGB(255, 0, 0));
553 s := '';
554 p := 1;
555 m := 0;
556 stat := g_Player_GetStats();
557 if stat <> nil then
558 begin
559 p := 1;
561 for a := 0 to High(stat) do
562 if stat[a].Name <> pl.Name then
563 begin
564 if stat[a].Frags > m then m := stat[a].Frags;
565 if stat[a].Frags > pl.Frags then p := p+1;
566 end;
567 end;
569 s := IntToStr(p)+' / '+IntToStr(Length(stat))+' ';
570 if pl.Frags >= m then s := s+'+' else s := s+'-';
571 s := s+IntToStr(Abs(pl.Frags-m));
573 e_CharFont_GetSize(gMenuSmallFont, s, tw, th);
574 e_CharFont_PrintEx(gMenuSmallFont, X-16-tw, Y+32, s, _RGB(255, 0, 0));
575 end;
577 if gLMSRespawn > LMS_RESPAWN_NONE then
578 begin
579 s := _lc[I_GAME_WARMUP];
580 e_CharFont_GetSize(gMenuFont, s, tw, th);
581 s := s + ': ' + IntToStr((gLMSRespawnTime - gTime) div 1000);
582 e_CharFont_PrintEx(gMenuFont, X-64-tw, SY-32, s, _RGB(0, 255, 0));
583 end
584 else if gShowLives and (gGameSettings.MaxLives > 0) then
585 begin
586 s := IntToStr(pl.Lives);
587 e_CharFont_GetSize(gMenuFont, s, tw, th);
588 e_CharFont_PrintEx(gMenuFont, X-16-tw, SY-32, s, _RGB(0, 255, 0));
589 end;
590 end;
592 e_CharFont_GetSize(gMenuSmallFont, pl.Name, tw, th);
593 e_CharFont_PrintEx(gMenuSmallFont, X+98-(tw div 2), Y+8, pl.Name, _RGB(255, 0, 0));
595 if R_BERSERK in pl.FRulez then
596 e_Draw(gItemsTexturesID[ITEM_MEDKIT_BLACK], X+37, Y+45, 0, True, False)
597 else
598 e_Draw(gItemsTexturesID[ITEM_MEDKIT_LARGE], X+37, Y+45, 0, True, False);
600 if g_Texture_Get('TEXTURE_PLAYER_ARMORHUD', ID) then
601 e_Draw(ID, X+36, Y+77, 0, True, False);
603 s := IntToStr(IfThen(pl.Health > 0, pl.Health, 0));
604 e_CharFont_GetSize(gMenuFont, s, tw, th);
605 e_CharFont_PrintEx(gMenuFont, X+178-tw, Y+40, s, _RGB(255, 0, 0));
607 s := IntToStr(pl.Armor);
608 e_CharFont_GetSize(gMenuFont, s, tw, th);
609 e_CharFont_PrintEx(gMenuFont, X+178-tw, Y+68, s, _RGB(255, 0, 0));
611 s := IntToStr(pl.GetAmmoByWeapon(pl.CurrWeap));
613 case pl.CurrWeap of
614 WEAPON_KASTET:
615 begin
616 s := '--';
617 ID := gItemsTexturesID[ITEM_WEAPON_KASTET];
618 end;
619 WEAPON_SAW:
620 begin
621 s := '--';
622 ID := gItemsTexturesID[ITEM_WEAPON_SAW];
623 end;
624 WEAPON_PISTOL: ID := gItemsTexturesID[ITEM_WEAPON_PISTOL];
625 WEAPON_CHAINGUN: ID := gItemsTexturesID[ITEM_WEAPON_CHAINGUN];
626 WEAPON_SHOTGUN1: ID := gItemsTexturesID[ITEM_WEAPON_SHOTGUN1];
627 WEAPON_SHOTGUN2: ID := gItemsTexturesID[ITEM_WEAPON_SHOTGUN2];
628 WEAPON_SUPERPULEMET: ID := gItemsTexturesID[ITEM_WEAPON_SUPERPULEMET];
629 WEAPON_ROCKETLAUNCHER: ID := gItemsTexturesID[ITEM_WEAPON_ROCKETLAUNCHER];
630 WEAPON_PLASMA: ID := gItemsTexturesID[ITEM_WEAPON_PLASMA];
631 WEAPON_BFG: ID := gItemsTexturesID[ITEM_WEAPON_BFG];
632 WEAPON_FLAMETHROWER: ID := gItemsTexturesID[ITEM_WEAPON_FLAMETHROWER];
633 end;
635 e_CharFont_GetSize(gMenuFont, s, tw, th);
636 e_CharFont_PrintEx(gMenuFont, X+178-tw, Y+158, s, _RGB(255, 0, 0));
637 e_Draw(ID, X+20, Y+160, 0, True, False);
639 if R_KEY_RED in pl.FRulez then
640 e_Draw(gItemsTexturesID[ITEM_KEY_RED], X+78, Y+214, 0, True, False);
642 if R_KEY_GREEN in pl.FRulez then
643 e_Draw(gItemsTexturesID[ITEM_KEY_GREEN], X+95, Y+214, 0, True, False);
645 if R_KEY_BLUE in pl.FRulez then
646 e_Draw(gItemsTexturesID[ITEM_KEY_BLUE], X+112, Y+214, 0, True, False);
648 if pl.JetFuel > 0 then
649 begin
650 if g_Texture_Get('TEXTURE_PLAYER_HUDAIR', ID) then
651 e_Draw(ID, X+2, Y+116, 0, True, False);
652 if g_Texture_Get('TEXTURE_PLAYER_HUDJET', ID) then
653 e_Draw(ID, X+2, Y+126, 0, True, False);
654 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);
655 e_DrawLine(4, X+16, Y+132, X+16+Trunc(168*pl.JetFuel/JET_MAX), Y+132, 208, 0, 0);
656 end
657 else
658 begin
659 if g_Texture_Get('TEXTURE_PLAYER_HUDAIR', ID) then
660 e_Draw(ID, X+2, Y+124, 0, True, False);
661 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);
662 end;
664 if gShowPing and g_Game_IsClient then
665 begin
666 s := _lc[I_GAME_PING_HUD] + IntToStr(NetPeer.lastRoundTripTime) + _lc[I_NET_SLIST_PING_MS];
667 e_TextureFontPrint(X + 4, Y + 242, s, gStdFont);
668 Y := Y + 16;
669 end;
671 if pl.Spectator then
672 begin
673 e_TextureFontPrint(X + 4, Y + 242, _lc[I_PLAYER_SPECT], gStdFont);
674 e_TextureFontPrint(X + 4, Y + 258, _lc[I_PLAYER_SPECT2], gStdFont);
675 e_TextureFontPrint(X + 4, Y + 274, _lc[I_PLAYER_SPECT1], gStdFont);
676 if pl.NoRespawn then
677 begin
678 e_TextureFontGetSize(gStdFont, cw, ch);
679 s := _lc[I_PLAYER_SPECT4];
680 e_TextureFontPrintEx(gScreenWidth div 2 - cw*(Length(s) div 2),
681 gScreenHeight-4-ch, s, gStdFont, 255, 255, 255, 1, True);
682 e_TextureFontPrint(X + 4, Y + 290, _lc[I_PLAYER_SPECT1S], gStdFont);
683 end;
685 end;
686 end;
688 procedure r_Player_DrawRulez (p: TPlayer);
689 var
690 dr: Boolean;
691 begin
692 // При взятии неуязвимости рисуется инверсионный белый фон
693 if (p.FMegaRulez[MR_INVUL] >= gTime) and (p.SpawnInvul < gTime) then
694 begin
695 if (p.FMegaRulez[MR_INVUL]-gTime) <= 2100 then
696 dr := not Odd((p.FMegaRulez[MR_INVUL]-gTime) div 300)
697 else
698 dr := True;
700 if dr then
701 e_DrawFillQuad(0, 0, gPlayerScreenSize.X-1, gPlayerScreenSize.Y-1,
702 191, 191, 191, 0, TBlending.Invert);
703 end;
705 // При взятии защитного костюма рисуется зеленоватый фон
706 if p.FMegaRulez[MR_SUIT] >= gTime then
707 begin
708 if (p.FMegaRulez[MR_SUIT]-gTime) <= 2100 then
709 dr := not Odd((p.FMegaRulez[MR_SUIT]-gTime) div 300)
710 else
711 dr := True;
713 if dr then
714 e_DrawFillQuad(0, 0, gPlayerScreenSize.X-1, gPlayerScreenSize.Y-1,
715 0, 96, 0, 200, TBlending.None);
716 end;
718 // При взятии берсерка рисуется красноватый фон
719 if (p.Berserk >= 0) and (LongWord(p.Berserk) >= gTime) and (gFlash = 2) then
720 begin
721 e_DrawFillQuad(0, 0, gPlayerScreenSize.X-1, gPlayerScreenSize.Y-1,
722 255, 0, 0, 200, TBlending.None);
723 end;
724 end;
726 procedure r_Player_DrawPain (p: TPlayer);
727 var
728 a, h: Integer;
729 begin
730 if p.Pain = 0 then Exit;
732 a := p.Pain;
734 if a < 15 then h := 0
735 else if a < 35 then h := 1
736 else if a < 55 then h := 2
737 else if a < 75 then h := 3
738 else if a < 95 then h := 4
739 else h := 5;
741 //if a > 255 then a := 255;
743 e_DrawFillQuad(0, 0, gPlayerScreenSize.X-1, gPlayerScreenSize.Y-1, 255, 0, 0, 255-h*50);
744 //e_DrawFillQuad(0, 0, gPlayerScreenSize.X-1, gPlayerScreenSize.Y-1, 255-min(128, a), 255-a, 255-a, 0, B_FILTER);
745 end;
747 procedure r_Player_DrawPickup (p: TPlayer);
748 var
749 a, h: Integer;
750 begin
751 if p.Pickup = 0 then Exit;
753 a := p.Pickup;
755 if a < 15 then h := 1
756 else if a < 35 then h := 2
757 else if a < 55 then h := 3
758 else if a < 75 then h := 4
759 else h := 5;
761 e_DrawFillQuad(0, 0, gPlayerScreenSize.X-1, gPlayerScreenSize.Y-1, 150, 200, 150, 255-h*50);
762 end;
764 procedure r_Player_DrawCorpse (p: TCorpse);
765 var
766 fX, fY: Integer;
767 begin
768 if p.State = CORPSE_STATE_REMOVEME then
769 Exit;
771 p.Obj.lerp(gLerpFactor, fX, fY);
773 if p.Animation <> nil then
774 r_Animation_Draw(p.Animation, fX, fY, TMirrorType.None);
776 if p.AnimationMask <> nil then
777 begin
778 e_Colors := p.Color;
779 r_Animation_Draw(p.AnimationMask, fX, fY, TMirrorType.None);
780 e_Colors.R := 255;
781 e_Colors.G := 255;
782 e_Colors.B := 255;
783 end;
784 end;
786 end.