DEADSOFTWARE

25a2dd7bfe6ea22e51efe94dc9a5ecc84bc3d286
[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, 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);
40 implementation
42 uses
43 SysUtils, Classes, Math,
44 MAPDEF, utils,
45 g_basic, g_game, g_phys, g_map, g_textures, g_menu, g_language, g_weapons, g_items, g_net, g_options,
46 r_playermodel
47 ;
49 procedure r_Player_DrawAll;
50 var i: Integer;
51 begin
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])
56 end;
58 procedure r_Player_DrawDebug (p: TPlayer);
59 var
60 fW, fH: Byte;
61 begin
62 if p = nil then Exit;
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);
75 end;
77 procedure r_Player_DrawHealth;
78 var
79 i: Integer;
80 fW, fH: Byte;
81 begin
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
87 begin
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);
94 end;
95 end;
97 procedure r_Player_DrawCorpses;
98 var
99 i, fX, fY: Integer;
100 a: TDFPoint;
101 begin
102 if gGibs <> nil then
103 for i := 0 to High(gGibs) do
104 if gGibs[i].alive then
105 with gGibs[i] do
106 begin
107 if not g_Obj_Collide(sX, sY, sWidth, sHeight, @Obj) then
108 Continue;
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);
117 e_Colors := Color;
118 e_DrawAdv(MaskID, fX, fY, 0, True, False, RAngle, @a, TMirrorType.None);
119 e_Colors.R := 255;
120 e_Colors.G := 255;
121 e_Colors.B := 255;
122 end;
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])
128 end;
130 procedure r_Player_DrawShells;
131 var
132 i, fX, fY: Integer;
133 a: TDFPoint;
134 begin
135 if gShells <> nil then
136 for i := 0 to High(gShells) do
137 if gShells[i].alive then
138 with gShells[i] do
139 begin
140 if not g_Obj_Collide(sX, sY, sWidth, sHeight, @Obj) then
141 Continue;
143 Obj.lerp(gLerpFactor, fX, fY);
145 a.X := CX;
146 a.Y := CY;
148 e_DrawAdv(SpriteID, fX, fY, 0, True, False, RAngle, @a, TMirrorType.None);
149 end;
150 end;
152 procedure r_Player_DrawIndicator (p: TPlayer; Color: TRGB);
153 var
154 indX, indY, fX, fY, fSlope: Integer;
155 indW, indH: Word;
156 indA: Single;
157 a: TDFPoint;
158 nW, nH: Byte;
159 ID: DWORD;
160 c: TRGB;
161 begin
162 if p.Alive then
163 begin
164 p.Obj.lerp(gLerpFactor, fX, fY);
165 fSlope := nlerp(p.SlopeOld, p.Obj.slopeUpLeft, gLerpFactor);
167 case gPlayerIndicatorStyle of
168 0:
169 begin
170 if g_Texture_Get('TEXTURE_PLAYER_INDICATOR', ID) then
171 begin
172 e_GetTextureSize(ID, @indW, @indH);
173 a.X := indW div 2;
174 a.Y := indH div 2;
176 if (p.Obj.X + p.Obj.Rect.X) < 0 then
177 begin
178 indA := 90;
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;
181 end
183 else if (p.Obj.X + p.Obj.Rect.X + p.Obj.Rect.Width) > Max(gMapInfo.Width, gPlayerScreenSize.X) then
184 begin
185 indA := 270;
186 indX := fX + p.Obj.Rect.X - indH;
187 indY := fY + p.Obj.Rect.Y + (p.Obj.Rect.Height - indW) div 2;
188 end
190 else if (p.Obj.Y - indH) < 0 then
191 begin
192 indA := 180;
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;
195 end
197 else
198 begin
199 indA := 0;
200 indX := fX + p.Obj.Rect.X + (p.Obj.Rect.Width - indW) div 2;
201 indY := fY - indH;
202 end;
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);
208 c := e_Colors;
209 e_Colors := Color;
210 e_DrawAdv(ID, indX, indY, 0, True, False, indA, @a);
211 e_Colors := c;
212 end;
213 end;
215 1:
216 begin
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);
221 end;
222 end;
223 end
224 end;
226 procedure r_Player_DrawBubble (p: TPlayer);
227 var
228 bubX, bubY, fX, fY: Integer;
229 ID: LongWord;
230 Rb, Gb, Bb,
231 Rw, Gw, Bw: SmallInt;
232 Dot: Byte;
233 CObj: TObj;
234 begin
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;
240 Rb := 64;
241 Gb := 64;
242 Bb := 64;
243 Rw := 240;
244 Gw := 240;
245 Bw := 240;
246 case gChatBubble of
247 1: // simple textual non-bubble
248 begin
249 bubX := fX + p.Obj.Rect.X - 11;
250 bubY := fY + p.Obj.Rect.Y - 17;
251 e_TextureFontPrint(bubX, bubY, '[...]', gStdFont);
252 Exit;
253 end;
254 2: // advanced pixel-perfect bubble
255 begin
256 if p.Team = TEAM_RED then
257 Rb := 255
258 else
259 if p.Team = TEAM_BLUE then
260 Bb := 255;
261 end;
262 3: // colored bubble
263 begin
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
273 begin
274 Rb := Max(Rw div 2 - 16, 0);
275 Gb := Max(Gw div 2 - 16, 0);
276 Bb := Max(Bw div 2 - 16, 0);
277 end;
278 end;
279 4: // custom textured bubble
280 begin
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)
284 else
285 e_Draw(ID, bubX - 6, bubY - 7, 0, True, False, TMirrorType.Horizontal);
286 Exit;
287 end;
288 end;
290 // Outer borders
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);
293 // Inner box
294 e_DrawFillQuad(bubX + 1, bubY + 1, bubX + 18, bubY + 12, Rw, Gw, Bw, 0);
296 // Tail
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);
304 // Dots
305 Dot := 6;
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);
309 end;
311 procedure r_Player_Draw (p: TPlayer);
312 var
313 ID: DWORD;
314 w, h: Word;
315 dr: Boolean;
316 Mirror: TMirrorType;
317 fX, fY, fSlope: Integer;
318 begin
319 p.Obj.lerp(gLerpFactor, fX, fY);
320 fSlope := nlerp(p.SlopeOld, p.Obj.slopeUpLeft, gLerpFactor);
322 if p.Alive then
323 begin
324 if p.Direction = TDirection.D_RIGHT then
325 Mirror := TMirrorType.None
326 else
327 Mirror := TMirrorType.Horizontal;
329 if p.PunchAnim <> nil then
330 begin
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
333 begin
334 p.PunchAnim.Free;
335 p.PunchAnim := nil;
336 end;
337 end;
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
341 begin
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)
346 else
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)
349 end;
351 if p.FMegaRulez[MR_INVIS] > gTime then
352 begin
353 if (gPlayerDrawn <> nil) and ((p = gPlayerDrawn) or
354 ((p.Team = gPlayerDrawn.Team) and (gGameSettings.GameMode <> GM_DM))) then
355 begin
356 if (p.FMegaRulez[MR_INVIS] - gTime) <= 2100 then
357 dr := not Odd((p.FMegaRulez[MR_INVIS] - gTime) div 300)
358 else
359 dr := True;
360 if dr then
361 r_PlayerModel_Draw(p.Model, fX, fY + fSlope, 200)
362 else
363 r_PlayerModel_Draw(p.Model, fX, fY + fSlope);
364 end
365 else
366 r_PlayerModel_Draw(p.Model, fX, fY + fSlope, 254);
367 end
368 else
369 r_PlayerModel_Draw(p.Model, fX, fY + fSlope);
370 end;
372 if g_debug_Frames then
373 begin
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,
378 0, 255, 0);
379 end;
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
388 r_Player_DrawAim(p);
389 end;
391 procedure r_Player_DrawAim (p: TPlayer);
393 procedure drawCast (sz: Integer; ax0, ay0, ax1, ay1: Integer);
394 var
395 ex, ey: Integer;
396 begin
398 {$IFDEF ENABLE_HOLMES}
399 if isValidViewPort and (self = gPlayer1) then
400 begin
401 g_Holmes_plrLaser(ax0, ay0, ax1, ay1);
402 end;
403 {$ENDIF}
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
407 begin
408 e_DrawLine(sz, ax0, ay0, ex, ey, 0, 255, 0, 96);
409 end
410 else
411 begin
412 e_DrawLine(sz, ax0, ay0, ex, ey, 0, 0, 255, 96);
413 end;
414 end;
416 var
417 wx, wy, xx, yy: Integer;
418 angle: SmallInt;
419 sz, len: Word;
420 begin
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;
423 angle := p.Angle_;
424 len := 1024;
425 sz := 2;
426 case p.CurrWeap of
427 0: begin // Punch
428 len := 12;
429 sz := 4;
430 end;
431 1: begin // Chainsaw
432 len := 24;
433 sz := 6;
434 end;
435 2: begin // Pistol
436 len := 1024;
437 sz := 2;
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);
442 end;
443 3: begin // Shotgun
444 len := 1024;
445 sz := 3;
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);
450 end;
451 4: begin // Double Shotgun
452 len := 1024;
453 sz := 4;
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);
458 end;
459 5: begin // Chaingun
460 len := 1024;
461 sz := 3;
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);
466 end;
467 6: begin // Rocket Launcher
468 len := 1024;
469 sz := 7;
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);
474 end;
475 7: begin // Plasmagun
476 len := 1024;
477 sz := 5;
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);
482 end;
483 8: begin // BFG
484 len := 1024;
485 sz := 12;
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);
490 end;
491 9: begin // Super Chaingun
492 len := 1024;
493 sz := 4;
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);
498 end;
499 end;
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);
504 {$ELSE}
505 e_DrawLine(sz, wx, wy, xx, yy, 255, 0, 0, 96);
506 {$ENDIF}
507 end;
509 procedure r_Player_DrawGUI (pl: TPlayer);
510 var
511 ID: DWORD;
512 X, Y, SY, a, p, m: Integer;
513 tw, th: Word;
514 cw, ch: Byte;
515 s: string;
516 stat: TPlayerStatArray;
517 begin
518 X := gPlayerScreenSize.X;
519 SY := gPlayerScreenSize.Y;
520 Y := 0;
522 if gShowGoals and (gGameSettings.GameMode in [GM_TDM, GM_CTF]) then
523 begin
524 if gGameSettings.GameMode = GM_CTF then
525 a := 32 + 8
526 else
527 a := 0;
528 if gGameSettings.GameMode = GM_CTF then
529 begin
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);
537 end;
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
544 begin
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);
552 end;
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]);
557 end;
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),
561 0, False, False);
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
567 begin
568 if gShowStat then
569 begin
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));
574 s := '';
575 p := 1;
576 m := 0;
577 stat := g_Player_GetStats();
578 if stat <> nil then
579 begin
580 p := 1;
582 for a := 0 to High(stat) do
583 if stat[a].Name <> pl.Name then
584 begin
585 if stat[a].Frags > m then m := stat[a].Frags;
586 if stat[a].Frags > pl.Frags then p := p+1;
587 end;
588 end;
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));
596 end;
598 if gLMSRespawn > LMS_RESPAWN_NONE then
599 begin
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));
604 end
605 else if gShowLives and (gGameSettings.MaxLives > 0) then
606 begin
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));
610 end;
611 end;
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)
618 else
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));
634 case pl.CurrWeap of
635 WEAPON_KASTET:
636 begin
637 s := '--';
638 ID := gItemsTexturesID[ITEM_WEAPON_KASTET];
639 end;
640 WEAPON_SAW:
641 begin
642 s := '--';
643 ID := gItemsTexturesID[ITEM_WEAPON_SAW];
644 end;
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];
654 end;
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
670 begin
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);
677 end
678 else
679 begin
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);
683 end;
685 if gShowPing and g_Game_IsClient then
686 begin
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);
689 Y := Y + 16;
690 end;
692 if pl.Spectator then
693 begin
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);
697 if pl.NoRespawn then
698 begin
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);
704 end;
706 end;
707 end;
709 procedure r_Player_DrawRulez (p: TPlayer);
710 var
711 dr: Boolean;
712 begin
713 // При взятии неуязвимости рисуется инверсионный белый фон
714 if (p.FMegaRulez[MR_INVUL] >= gTime) and (p.SpawnInvul < gTime) then
715 begin
716 if (p.FMegaRulez[MR_INVUL]-gTime) <= 2100 then
717 dr := not Odd((p.FMegaRulez[MR_INVUL]-gTime) div 300)
718 else
719 dr := True;
721 if dr then
722 e_DrawFillQuad(0, 0, gPlayerScreenSize.X-1, gPlayerScreenSize.Y-1,
723 191, 191, 191, 0, TBlending.Invert);
724 end;
726 // При взятии защитного костюма рисуется зеленоватый фон
727 if p.FMegaRulez[MR_SUIT] >= gTime then
728 begin
729 if (p.FMegaRulez[MR_SUIT]-gTime) <= 2100 then
730 dr := not Odd((p.FMegaRulez[MR_SUIT]-gTime) div 300)
731 else
732 dr := True;
734 if dr then
735 e_DrawFillQuad(0, 0, gPlayerScreenSize.X-1, gPlayerScreenSize.Y-1,
736 0, 96, 0, 200, TBlending.None);
737 end;
739 // При взятии берсерка рисуется красноватый фон
740 if (p.Berserk >= 0) and (LongWord(p.Berserk) >= gTime) and (gFlash = 2) then
741 begin
742 e_DrawFillQuad(0, 0, gPlayerScreenSize.X-1, gPlayerScreenSize.Y-1,
743 255, 0, 0, 200, TBlending.None);
744 end;
745 end;
747 procedure r_Player_DrawPain (p: TPlayer);
748 var
749 a, h: Integer;
750 begin
751 if p.Pain = 0 then Exit;
753 a := p.Pain;
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
760 else h := 5;
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);
766 end;
768 procedure r_Player_DrawPickup (p: TPlayer);
769 var
770 a, h: Integer;
771 begin
772 if p.Pickup = 0 then Exit;
774 a := p.Pickup;
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
780 else h := 5;
782 e_DrawFillQuad(0, 0, gPlayerScreenSize.X-1, gPlayerScreenSize.Y-1, 150, 200, 150, 255-h*50);
783 end;
785 procedure r_Player_DrawCorpse (p: TCorpse);
786 var
787 fX, fY: Integer;
788 begin
789 if p.State = CORPSE_STATE_REMOVEME then
790 Exit;
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
798 begin
799 e_Colors := p.Color;
800 p.AnimationMask.Draw(fX, fY, TMirrorType.None);
801 e_Colors.R := 255;
802 e_Colors.G := 255;
803 e_Colors.B := 255;
804 end;
805 end;
807 end.