DEADSOFTWARE

render: separate weapon shots logic and drawing
[d2df-sdl.git] / src / game / opengl / r_game.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_game;
18 interface
20 procedure r_Game_Draw;
21 procedure r_Game_DrawLoadingStat;
22 procedure r_Game_DrawMenuBackground (tex: AnsiString);
24 implementation
26 uses
27 {$INCLUDE ../nogl/noGLuses.inc}
28 SysUtils, Classes, Math,
29 e_graphics,
30 g_system, g_touch,
31 MAPDEF, xprofiler, utils, wadreader,
32 g_textures, e_input, e_sound,
33 g_language, g_console, g_menu, g_triggers, g_player, g_options, g_monsters, g_map, g_panel, g_window,
34 g_items, g_weapons, g_gfx, g_phys, g_net, g_gui, g_netmaster,
35 g_game, r_console, r_gfx, r_items, r_map, r_panel, r_monsters, r_weapons
36 ;
38 var
39 profileFrameDraw: TProfiler = nil;
41 FPS: Word;
42 FPSCounter: Word;
43 FPSTime: LongWord;
45 function GetActivePlayer_ByID(ID: Integer): TPlayer;
46 var
47 a: Integer;
48 begin
49 Result := nil;
50 if ID < 0 then
51 Exit;
52 if gPlayers = nil then
53 Exit;
54 for a := Low(gPlayers) to High(gPlayers) do
55 if IsActivePlayer(gPlayers[a]) then
56 begin
57 if gPlayers[a].UID <> ID then
58 continue;
59 Result := gPlayers[a];
60 break;
61 end;
62 end;
64 function calcProfilesHeight (prof: TProfiler): Integer;
65 begin
66 result := 0;
67 if (prof = nil) then exit;
68 if (length(prof.bars) = 0) then exit;
69 result := length(prof.bars)*(16+2);
70 end;
72 // returns width
73 function drawProfiles (x, y: Integer; prof: TProfiler): Integer;
74 var
75 wdt, hgt: Integer;
76 yy: Integer;
77 ii: Integer;
78 begin
79 result := 0;
80 if (prof = nil) then exit;
81 // gScreenWidth
82 if (length(prof.bars) = 0) then exit;
83 wdt := 192;
84 hgt := calcProfilesHeight(prof);
85 if (x < 0) then x := gScreenWidth-(wdt-1)+x;
86 if (y < 0) then y := gScreenHeight-(hgt-1)+y;
87 // background
88 //e_DrawFillQuad(x, y, x+wdt-1, y+hgt-1, 255, 255, 255, 200, B_BLEND);
89 //e_DrawFillQuad(x, y, x+wdt-1, y+hgt-1, 20, 20, 20, 0, B_NONE);
90 e_DarkenQuadWH(x, y, wdt, hgt, 150);
91 // title
92 yy := y+2;
93 for ii := 0 to High(prof.bars) do
94 begin
95 e_TextureFontPrintEx(x+2+4*prof.bars[ii].level, yy, Format('%s: %d', [prof.bars[ii].name, prof.bars[ii].value]), gStdFont, 255, 255, 0, 1, false);
96 Inc(yy, 16+2);
97 end;
98 result := wdt;
99 end;
101 procedure drawTime(X, Y: Integer); inline;
102 begin
103 e_TextureFontPrint(x, y, Format('%d:%.2d:%.2d', [gTime div 1000 div 3600, (gTime div 1000 div 60) mod 60, gTime div 1000 mod 60]), gStdFont);
104 end;
106 procedure DrawStat();
107 var
108 pc, x, y, w, h: Integer;
109 w1, w2, w3, w4: Integer;
110 a, aa: Integer;
111 cw, ch, r, g, b, rr, gg, bb: Byte;
112 s1, s2, s3: String;
113 _y: Integer;
114 stat: TPlayerStatArray;
115 wad, map: string;
116 mapstr: string;
117 namestr: string;
118 begin
119 s1 := '';
120 s2 := '';
121 s3 := '';
122 pc := g_Player_GetCount;
123 e_TextureFontGetSize(gStdFont, cw, ch);
125 w := gScreenWidth-(gScreenWidth div 5);
126 if gGameSettings.GameMode in [GM_TDM, GM_CTF] then
127 h := 32+ch*(11+pc)
128 else
129 h := 40+ch*5+(ch+8)*pc;
130 x := (gScreenWidth div 2)-(w div 2);
131 y := (gScreenHeight div 2)-(h div 2);
133 e_DrawFillQuad(x, y, x+w-1, y+h-1, 64, 64, 64, 32);
134 e_DrawQuad(x, y, x+w-1, y+h-1, 255, 127, 0);
136 drawTime(x+w-78, y+8);
138 wad := g_ExtractWadNameNoPath(gMapInfo.Map);
139 map := g_ExtractFileName(gMapInfo.Map);
140 mapstr := wad + ':\' + map + ' - ' + gMapInfo.Name;
142 case gGameSettings.GameMode of
143 GM_DM:
144 begin
145 if gGameSettings.MaxLives = 0 then
146 s1 := _lc[I_GAME_DM]
147 else
148 s1 := _lc[I_GAME_LMS];
149 s2 := Format(_lc[I_GAME_FRAG_LIMIT], [gGameSettings.ScoreLimit]);
150 s3 := Format(_lc[I_GAME_TIME_LIMIT], [gGameSettings.TimeLimit div 3600, (gGameSettings.TimeLimit div 60) mod 60, gGameSettings.TimeLimit mod 60]);
151 end;
153 GM_TDM:
154 begin
155 if gGameSettings.MaxLives = 0 then
156 s1 := _lc[I_GAME_TDM]
157 else
158 s1 := _lc[I_GAME_TLMS];
159 s2 := Format(_lc[I_GAME_FRAG_LIMIT], [gGameSettings.ScoreLimit]);
160 s3 := Format(_lc[I_GAME_TIME_LIMIT], [gGameSettings.TimeLimit div 3600, (gGameSettings.TimeLimit div 60) mod 60, gGameSettings.TimeLimit mod 60]);
161 end;
163 GM_CTF:
164 begin
165 s1 := _lc[I_GAME_CTF];
166 s2 := Format(_lc[I_GAME_SCORE_LIMIT], [gGameSettings.ScoreLimit]);
167 s3 := Format(_lc[I_GAME_TIME_LIMIT], [gGameSettings.TimeLimit div 3600, (gGameSettings.TimeLimit div 60) mod 60, gGameSettings.TimeLimit mod 60]);
168 end;
170 GM_COOP:
171 begin
172 if gGameSettings.MaxLives = 0 then
173 s1 := _lc[I_GAME_COOP]
174 else
175 s1 := _lc[I_GAME_SURV];
176 s2 := _lc[I_GAME_MONSTERS] + ' ' + IntToStr(gCoopMonstersKilled) + '/' + IntToStr(gTotalMonsters);
177 s3 := _lc[I_GAME_SECRETS] + ' ' + IntToStr(gCoopSecretsFound) + '/' + IntToStr(gSecretsCount);
178 end;
180 else
181 begin
182 s1 := '';
183 s2 := '';
184 end;
185 end;
186 _y := y+8;
187 e_TextureFontPrintEx(x+(w div 2)-(Length(s1)*cw div 2), _y, s1, gStdFont, 255, 255, 255, 1);
188 _y := _y+ch+8;
189 e_TextureFontPrintEx(x+(w div 2)-(Length(mapstr)*cw div 2), _y, mapstr, gStdFont, 200, 200, 200, 1);
190 _y := _y+ch+8;
191 e_TextureFontPrintEx(x+16, _y, s2, gStdFont, 200, 200, 200, 1);
193 e_TextureFontPrintEx(x+w-16-(Length(s3))*cw, _y, s3,
194 gStdFont, 200, 200, 200, 1);
196 if NetMode = NET_SERVER then
197 e_TextureFontPrintEx(x+8, y + 8, _lc[I_NET_SERVER], gStdFont, 255, 255, 255, 1)
198 else
199 if NetMode = NET_CLIENT then
200 e_TextureFontPrintEx(x+8, y + 8,
201 NetClientIP + ':' + IntToStr(NetClientPort), gStdFont, 255, 255, 255, 1);
203 if pc = 0 then
204 Exit;
205 stat := g_Player_GetStats();
206 SortGameStat(stat);
208 w2 := (w-16) div 6 + 48; // ширина 2 столбца
209 w3 := (w-16) div 6; // ширина 3 и 4 столбцов
210 w4 := w3;
211 w1 := w-16-w2-w3-w4; // оставшееся пространство - для цвета и имени игрока
213 if gGameSettings.GameMode in [GM_TDM, GM_CTF] then
214 begin
215 _y := _y+ch+ch;
217 for a := TEAM_RED to TEAM_BLUE do
218 begin
219 if a = TEAM_RED then
220 begin
221 s1 := _lc[I_GAME_TEAM_RED];
222 r := 255;
223 g := 0;
224 b := 0;
225 end
226 else
227 begin
228 s1 := _lc[I_GAME_TEAM_BLUE];
229 r := 0;
230 g := 0;
231 b := 255;
232 end;
234 e_TextureFontPrintEx(x+16, _y, s1, gStdFont, r, g, b, 1);
235 e_TextureFontPrintEx(x+w1+16, _y, IntToStr(gTeamStat[a].Score),
236 gStdFont, r, g, b, 1);
238 _y := _y+ch+(ch div 4);
239 e_DrawLine(1, x+16, _y, x+w-16, _y, r, g, b);
240 _y := _y+(ch div 4);
242 for aa := 0 to High(stat) do
243 if stat[aa].Team = a then
244 with stat[aa] do
245 begin
246 if Spectator then
247 begin
248 rr := r div 2;
249 gg := g div 2;
250 bb := b div 2;
251 end
252 else
253 begin
254 rr := r;
255 gg := g;
256 bb := b;
257 end;
258 if gShowPIDs then
259 namestr := Format('[%5d] %s', [UID, Name])
260 else
261 namestr := Name;
262 // Имя
263 e_TextureFontPrintEx(x+16, _y, namestr, gStdFont, rr, gg, bb, 1);
264 // Пинг/потери
265 e_TextureFontPrintEx(x+w1+16, _y, Format(_lc[I_GAME_PING_MS], [Ping, Loss]), gStdFont, rr, gg, bb, 1);
266 // Фраги
267 e_TextureFontPrintEx(x+w1+w2+16, _y, IntToStr(Frags), gStdFont, rr, gg, bb, 1);
268 // Смерти
269 e_TextureFontPrintEx(x+w1+w2+w3+16, _y, IntToStr(Deaths), gStdFont, rr, gg, bb, 1);
270 _y := _y+ch;
271 end;
273 _y := _y+ch;
274 end;
275 end
276 else if gGameSettings.GameMode in [GM_DM, GM_COOP] then
277 begin
278 _y := _y+ch+ch;
279 e_TextureFontPrintEx(x+16, _y, _lc[I_GAME_PLAYER_NAME], gStdFont, 255, 127, 0, 1);
280 e_TextureFontPrintEx(x+16+w1, _y, _lc[I_GAME_PING], gStdFont, 255, 127, 0, 1);
281 e_TextureFontPrintEx(x+16+w1+w2, _y, _lc[I_GAME_FRAGS], gStdFont, 255, 127, 0, 1);
282 e_TextureFontPrintEx(x+16+w1+w2+w3, _y, _lc[I_GAME_DEATHS], gStdFont, 255, 127, 0, 1);
284 _y := _y+ch+8;
285 for aa := 0 to High(stat) do
286 with stat[aa] do
287 begin
288 if Spectator then
289 begin
290 r := 127;
291 g := 64;
292 end
293 else
294 begin
295 r := 255;
296 g := 127;
297 end;
298 if gShowPIDs then
299 namestr := Format('[%5d] %s', [UID, Name])
300 else
301 namestr := Name;
302 // Цвет игрока
303 e_DrawFillQuad(x+16, _y+4, x+32-1, _y+16+4-1, Color.R, Color.G, Color.B, 0);
304 e_DrawQuad(x+16, _y+4, x+32-1, _y+16+4-1, 192, 192, 192);
305 // Имя
306 e_TextureFontPrintEx(x+16+16+8, _y+4, namestr, gStdFont, r, g, 0, 1);
307 // Пинг/потери
308 e_TextureFontPrintEx(x+w1+16, _y+4, Format(_lc[I_GAME_PING_MS], [Ping, Loss]), gStdFont, r, g, 0, 1);
309 // Фраги
310 e_TextureFontPrintEx(x+w1+w2+16, _y+4, IntToStr(Frags), gStdFont, r, g, 0, 1);
311 // Смерти
312 e_TextureFontPrintEx(x+w1+w2+w3+16, _y+4, IntToStr(Deaths), gStdFont, r, g, 0, 1);
313 _y := _y+ch+8;
314 end;
315 end
316 end;
318 procedure DrawCustomStat();
319 var
320 pc, x, y, w, _y,
321 w1, w2, w3,
322 t, p, m: Integer;
323 ww1, hh1: Word;
324 ww2, hh2, r, g, b, rr, gg, bb: Byte;
325 s1, s2, topstr: String;
326 begin
327 e_TextureFontGetSize(gStdFont, ww2, hh2);
329 sys_HandleInput;
331 if g_Console_Action(ACTION_SCORES) then
332 begin
333 if not gStatsPressed then
334 begin
335 gStatsOff := not gStatsOff;
336 gStatsPressed := True;
337 end;
338 end
339 else
340 gStatsPressed := False;
342 if gStatsOff then
343 begin
344 s1 := _lc[I_MENU_INTER_NOTICE_TAB];
345 w := (Length(s1) * ww2) div 2;
346 x := gScreenWidth div 2 - w;
347 y := 8;
348 e_TextureFontPrint(x, y, s1, gStdFont);
349 Exit;
350 end;
352 if (gGameSettings.GameMode = GM_COOP) then
353 begin
354 if gMissionFailed then
355 topstr := _lc[I_MENU_INTER_MISSION_FAIL]
356 else
357 topstr := _lc[I_MENU_INTER_LEVEL_COMPLETE];
358 end
359 else
360 topstr := _lc[I_MENU_INTER_ROUND_OVER];
362 e_CharFont_GetSize(gMenuFont, topstr, ww1, hh1);
363 e_CharFont_Print(gMenuFont, (gScreenWidth div 2)-(ww1 div 2), 16, topstr);
365 if g_Game_IsNet then
366 begin
367 topstr := Format(_lc[I_MENU_INTER_NOTICE_TIME], [gServInterTime]);
368 if not gChatShow then
369 e_TextureFontPrintEx((gScreenWidth div 2)-(Length(topstr)*ww2 div 2),
370 gScreenHeight-(hh2+4)*2, topstr, gStdFont, 255, 255, 255, 1);
371 end;
373 if g_Game_IsClient then
374 topstr := _lc[I_MENU_INTER_NOTICE_MAP]
375 else
376 topstr := _lc[I_MENU_INTER_NOTICE_SPACE];
377 if not gChatShow then
378 e_TextureFontPrintEx((gScreenWidth div 2)-(Length(topstr)*ww2 div 2),
379 gScreenHeight-(hh2+4), topstr, gStdFont, 255, 255, 255, 1);
381 x := 32;
382 y := 16+hh1+16;
384 w := gScreenWidth-x*2;
386 w2 := (w-16) div 6;
387 w3 := w2;
388 w1 := w-16-w2-w3;
390 e_DrawFillQuad(x, y, gScreenWidth-x-1, gScreenHeight-y-1, 64, 64, 64, 32);
391 e_DrawQuad(x, y, gScreenWidth-x-1, gScreenHeight-y-1, 255, 127, 0);
393 m := Max(Length(_lc[I_MENU_MAP])+1, Length(_lc[I_GAME_GAME_TIME])+1)*ww2;
395 case CustomStat.GameMode of
396 GM_DM:
397 begin
398 if gGameSettings.MaxLives = 0 then
399 s1 := _lc[I_GAME_DM]
400 else
401 s1 := _lc[I_GAME_LMS];
402 end;
403 GM_TDM:
404 begin
405 if gGameSettings.MaxLives = 0 then
406 s1 := _lc[I_GAME_TDM]
407 else
408 s1 := _lc[I_GAME_TLMS];
409 end;
410 GM_CTF: s1 := _lc[I_GAME_CTF];
411 GM_COOP:
412 begin
413 if gGameSettings.MaxLives = 0 then
414 s1 := _lc[I_GAME_COOP]
415 else
416 s1 := _lc[I_GAME_SURV];
417 end;
418 else s1 := '';
419 end;
421 _y := y+16;
422 e_TextureFontPrintEx(x+(w div 2)-(Length(s1)*ww2 div 2), _y, s1, gStdFont, 255, 255, 255, 1);
423 _y := _y+8;
425 _y := _y+16;
426 e_TextureFontPrintEx(x+8, _y, _lc[I_MENU_MAP], gStdFont, 255, 127, 0, 1);
427 e_TextureFontPrint(x+8+m, _y, Format('%s - %s', [CustomStat.Map, CustomStat.MapName]), gStdFont);
429 _y := _y+16;
430 e_TextureFontPrintEx(x+8, _y, _lc[I_GAME_GAME_TIME], gStdFont, 255, 127, 0, 1);
431 e_TextureFontPrint(x+8+m, _y, Format('%d:%.2d:%.2d', [CustomStat.GameTime div 1000 div 3600,
432 (CustomStat.GameTime div 1000 div 60) mod 60,
433 CustomStat.GameTime div 1000 mod 60]), gStdFont);
435 pc := Length(CustomStat.PlayerStat);
436 if pc = 0 then Exit;
438 if CustomStat.GameMode = GM_COOP then
439 begin
440 m := Max(Length(_lc[I_GAME_MONSTERS])+1, Length(_lc[I_GAME_SECRETS])+1)*ww2;
441 _y := _y+32;
442 s2 := _lc[I_GAME_MONSTERS];
443 e_TextureFontPrintEx(x+8, _y, s2, gStdFont, 255, 127, 0, 1);
444 e_TextureFontPrintEx(x+8+m, _y, IntToStr(gCoopMonstersKilled) + '/' + IntToStr(gTotalMonsters), gStdFont, 255, 255, 255, 1);
445 _y := _y+16;
446 s2 := _lc[I_GAME_SECRETS];
447 e_TextureFontPrintEx(x+8, _y, s2, gStdFont, 255, 127, 0, 1);
448 e_TextureFontPrintEx(x+8+m, _y, IntToStr(gCoopSecretsFound) + '/' + IntToStr(gSecretsCount), gStdFont, 255, 255, 255, 1);
449 if gLastMap then
450 begin
451 m := Max(Length(_lc[I_GAME_MONSTERS_TOTAL])+1, Length(_lc[I_GAME_SECRETS_TOTAL])+1)*ww2;
452 _y := _y-16;
453 s2 := _lc[I_GAME_MONSTERS_TOTAL];
454 e_TextureFontPrintEx(x+250, _y, s2, gStdFont, 255, 127, 0, 1);
455 e_TextureFontPrintEx(x+250+m, _y, IntToStr(gCoopTotalMonstersKilled) + '/' + IntToStr(gCoopTotalMonsters), gStdFont, 255, 255, 255, 1);
456 _y := _y+16;
457 s2 := _lc[I_GAME_SECRETS_TOTAL];
458 e_TextureFontPrintEx(x+250, _y, s2, gStdFont, 255, 127, 0, 1);
459 e_TextureFontPrintEx(x+250+m, _y, IntToStr(gCoopTotalSecretsFound) + '/' + IntToStr(gCoopTotalSecrets), gStdFont, 255, 255, 255, 1);
460 end;
461 end;
463 if CustomStat.GameMode in [GM_TDM, GM_CTF] then
464 begin
465 _y := _y+16+16;
467 with CustomStat do
468 if TeamStat[TEAM_RED].Score > TeamStat[TEAM_BLUE].Score then s1 := _lc[I_GAME_WIN_RED]
469 else if TeamStat[TEAM_BLUE].Score > TeamStat[TEAM_RED].Score then s1 := _lc[I_GAME_WIN_BLUE]
470 else s1 := _lc[I_GAME_WIN_DRAW];
472 e_TextureFontPrintEx(x+8+(w div 2)-(Length(s1)*ww2 div 2), _y, s1, gStdFont, 255, 255, 255, 1);
473 _y := _y+40;
475 for t := TEAM_RED to TEAM_BLUE do
476 begin
477 if t = TEAM_RED then
478 begin
479 e_TextureFontPrintEx(x+8, _y, _lc[I_GAME_TEAM_RED],
480 gStdFont, 255, 0, 0, 1);
481 e_TextureFontPrintEx(x+w1+8, _y, IntToStr(CustomStat.TeamStat[TEAM_RED].Score),
482 gStdFont, 255, 0, 0, 1);
483 r := 255;
484 g := 0;
485 b := 0;
486 end
487 else
488 begin
489 e_TextureFontPrintEx(x+8, _y, _lc[I_GAME_TEAM_BLUE],
490 gStdFont, 0, 0, 255, 1);
491 e_TextureFontPrintEx(x+w1+8, _y, IntToStr(CustomStat.TeamStat[TEAM_BLUE].Score),
492 gStdFont, 0, 0, 255, 1);
493 r := 0;
494 g := 0;
495 b := 255;
496 end;
498 e_DrawLine(1, x+8, _y+20, x-8+w, _y+20, r, g, b);
499 _y := _y+24;
501 for p := 0 to High(CustomStat.PlayerStat) do
502 if CustomStat.PlayerStat[p].Team = t then
503 with CustomStat.PlayerStat[p] do
504 begin
505 if Spectator then
506 begin
507 rr := r div 2;
508 gg := g div 2;
509 bb := b div 2;
510 end
511 else
512 begin
513 rr := r;
514 gg := g;
515 bb := b;
516 end;
517 if (gPlayers[Num] <> nil) and (gPlayers[Num].FReady) then
518 e_TextureFontPrintEx(x+16, _y, Name + ' *', gStdFont, rr, gg, bb, 1)
519 else
520 e_TextureFontPrintEx(x+16, _y, Name, gStdFont, rr, gg, bb, 1);
521 e_TextureFontPrintEx(x+w1+16, _y, IntToStr(Frags), gStdFont, rr, gg, bb, 1);
522 e_TextureFontPrintEx(x+w1+w2+16, _y, IntToStr(Deaths), gStdFont, rr, gg, bb, 1);
523 _y := _y+24;
524 end;
526 _y := _y+16+16;
527 end;
528 end
529 else if CustomStat.GameMode in [GM_DM, GM_COOP] then
530 begin
531 _y := _y+40;
532 e_TextureFontPrintEx(x+8, _y, _lc[I_GAME_PLAYER_NAME], gStdFont, 255, 127, 0, 1);
533 e_TextureFontPrintEx(x+8+w1, _y, _lc[I_GAME_FRAGS], gStdFont, 255, 127, 0, 1);
534 e_TextureFontPrintEx(x+8+w1+w2, _y, _lc[I_GAME_DEATHS], gStdFont, 255, 127, 0, 1);
536 _y := _y+24;
537 for p := 0 to High(CustomStat.PlayerStat) do
538 with CustomStat.PlayerStat[p] do
539 begin
540 e_DrawFillQuad(x+8, _y+4, x+24-1, _y+16+4-1, Color.R, Color.G, Color.B, 0);
542 if Spectator then
543 r := 127
544 else
545 r := 255;
547 if (gPlayers[Num] <> nil) and (gPlayers[Num].FReady) then
548 e_TextureFontPrintEx(x+8+16+8, _y+4, Name + ' *', gStdFont, r, r, r, 1, True)
549 else
550 e_TextureFontPrintEx(x+8+16+8, _y+4, Name, gStdFont, r, r, r, 1, True);
551 e_TextureFontPrintEx(x+w1+8+16+8, _y+4, IntToStr(Frags), gStdFont, r, r, r, 1, True);
552 e_TextureFontPrintEx(x+w1+w2+8+16+8, _y+4, IntToStr(Deaths), gStdFont, r, r, r, 1, True);
553 _y := _y+24;
554 end;
555 end;
557 // HACK: take stats screenshot immediately after the first frame of the stats showing
558 if gScreenshotStats and (not StatShotDone) and (Length(CustomStat.PlayerStat) > 1) then
559 begin
560 g_TakeScreenShot('stats/' + StatFilename);
561 StatShotDone := True;
562 end;
563 end;
565 procedure DrawSingleStat();
566 var
567 tm, key_x, val_x, y: Integer;
568 w1, w2, h: Word;
569 s1, s2: String;
571 procedure player_stat(n: Integer);
572 var
573 kpm: Real;
575 begin
576 // "Kills: # / #":
577 s1 := Format(' %d ', [SingleStat.PlayerStat[n].Kills]);
578 s2 := Format(' %d', [gTotalMonsters]);
580 e_CharFont_Print(gMenuFont, key_x, y, _lc[I_MENU_INTER_KILLS]);
581 e_CharFont_PrintEx(gMenuFont, val_x, y, s1, _RGB(255, 0, 0));
582 e_CharFont_GetSize(gMenuFont, s1, w1, h);
583 e_CharFont_Print(gMenuFont, val_x+w1, y, '/');
584 s1 := s1 + '/';
585 e_CharFont_GetSize(gMenuFont, s1, w1, h);
586 e_CharFont_PrintEx(gMenuFont, val_x+w1, y, s2, _RGB(255, 0, 0));
588 // "Kills-per-minute: ##.#":
589 s1 := _lc[I_MENU_INTER_KPM];
590 if tm > 0 then
591 kpm := (SingleStat.PlayerStat[n].Kills / tm) * 60
592 else
593 kpm := SingleStat.PlayerStat[n].Kills;
594 s2 := Format(' %.1f', [kpm]);
596 e_CharFont_Print(gMenuFont, key_x, y+32, s1);
597 e_CharFont_PrintEx(gMenuFont, val_x, y+32, s2, _RGB(255, 0, 0));
599 // "Secrets found: # / #":
600 s1 := Format(' %d ', [SingleStat.PlayerStat[n].Secrets]);
601 s2 := Format(' %d', [SingleStat.TotalSecrets]);
603 e_CharFont_Print(gMenuFont, key_x, y+64, _lc[I_MENU_INTER_SECRETS]);
604 e_CharFont_PrintEx(gMenuFont, val_x, y+64, s1, _RGB(255, 0, 0));
605 e_CharFont_GetSize(gMenuFont, s1, w1, h);
606 e_CharFont_Print(gMenuFont, val_x+w1, y+64, '/');
607 s1 := s1 + '/';
608 e_CharFont_GetSize(gMenuFont, s1, w1, h);
609 e_CharFont_PrintEx(gMenuFont, val_x+w1, y+64, s2, _RGB(255, 0, 0));
610 end;
612 begin
613 // "Level Complete":
614 e_CharFont_GetSize(gMenuFont, _lc[I_MENU_INTER_LEVEL_COMPLETE], w1, h);
615 e_CharFont_Print(gMenuFont, (gScreenWidth-w1) div 2, 32, _lc[I_MENU_INTER_LEVEL_COMPLETE]);
617 // Определяем координаты выравнивания по самой длинной строке:
618 s1 := _lc[I_MENU_INTER_KPM];
619 e_CharFont_GetSize(gMenuFont, s1, w1, h);
620 Inc(w1, 16);
621 s1 := ' 9999.9';
622 e_CharFont_GetSize(gMenuFont, s1, w2, h);
624 key_x := (gScreenWidth-w1-w2) div 2;
625 val_x := key_x + w1;
627 // "Time: #:##:##":
628 tm := SingleStat.GameTime div 1000;
629 s1 := _lc[I_MENU_INTER_TIME];
630 s2 := Format(' %d:%.2d:%.2d', [tm div (60*60), (tm mod (60*60)) div 60, tm mod 60]);
632 e_CharFont_Print(gMenuFont, key_x, 80, s1);
633 e_CharFont_PrintEx(gMenuFont, val_x, 80, s2, _RGB(255, 0, 0));
635 if SingleStat.TwoPlayers then
636 begin
637 // "Player 1":
638 s1 := _lc[I_MENU_PLAYER_1];
639 e_CharFont_GetSize(gMenuFont, s1, w1, h);
640 e_CharFont_Print(gMenuFont, (gScreenWidth-w1) div 2, 128, s1);
642 // Статистика первого игрока:
643 y := 176;
644 player_stat(0);
646 // "Player 2":
647 s1 := _lc[I_MENU_PLAYER_2];
648 e_CharFont_GetSize(gMenuFont, s1, w1, h);
649 e_CharFont_Print(gMenuFont, (gScreenWidth-w1) div 2, 288, s1);
651 // Статистика второго игрока:
652 y := 336;
653 player_stat(1);
654 end
655 else
656 begin
657 // Статистика первого игрока:
658 y := 128;
659 player_stat(0);
660 end;
661 end;
663 procedure r_Game_DrawLoadingStat;
664 procedure drawRect (x, y, w, h: Integer);
665 begin
666 if (w < 1) or (h < 1) then exit;
667 glBegin(GL_QUADS);
668 glVertex2f(x+0.375, y+0.375);
669 glVertex2f(x+w+0.375, y+0.375);
670 glVertex2f(x+w+0.375, y+h+0.375);
671 glVertex2f(x+0.375, y+h+0.375);
672 glEnd();
673 end;
675 function drawPBar (cur, total: Integer; washere: Boolean): Boolean;
676 var
677 rectW, rectH: Integer;
678 x0, y0: Integer;
679 wdt: Integer;
680 wl, hl: Integer;
681 wr, hr: Integer;
682 wb, hb: Integer;
683 wm, hm: Integer;
684 idl, idr, idb, idm: LongWord;
685 f, my: Integer;
686 begin
687 result := false;
688 if (total < 1) then exit;
689 if (cur < 1) then exit; // don't blink
690 if (not washere) and (cur >= total) then exit; // don't blink
691 //if (cur < 0) then cur := 0;
692 //if (cur > total) then cur := total;
693 result := true;
695 if (hasPBarGfx) then
696 begin
697 g_Texture_Get('UI_GFX_PBAR_LEFT', idl);
698 g_Texture_GetSize('UI_GFX_PBAR_LEFT', wl, hl);
699 g_Texture_Get('UI_GFX_PBAR_RIGHT', idr);
700 g_Texture_GetSize('UI_GFX_PBAR_RIGHT', wr, hr);
701 g_Texture_Get('UI_GFX_PBAR_MIDDLE', idb);
702 g_Texture_GetSize('UI_GFX_PBAR_MIDDLE', wb, hb);
703 g_Texture_Get('UI_GFX_PBAR_MARKER', idm);
704 g_Texture_GetSize('UI_GFX_PBAR_MARKER', wm, hm);
706 //rectW := gScreenWidth-360;
707 rectW := trunc(624.0*gScreenWidth/1024.0);
708 rectH := hl;
710 x0 := (gScreenWidth-rectW) div 2;
711 y0 := gScreenHeight-rectH-64;
712 if (y0 < 2) then y0 := 2;
714 glEnable(GL_SCISSOR_TEST);
716 // left and right
717 glScissor(x0, gScreenHeight-y0-rectH, rectW, rectH);
718 e_DrawSize(idl, x0, y0, 0, true, false, wl, hl);
719 e_DrawSize(idr, x0+rectW-wr, y0, 0, true, false, wr, hr);
721 // body
722 glScissor(x0+wl, gScreenHeight-y0-rectH, rectW-wl-wr, rectH);
723 f := x0+wl;
724 while (f < x0+rectW) do
725 begin
726 e_DrawSize(idb, f, y0, 0, true, false, wb, hb);
727 f += wb;
728 end;
730 // filled part
731 wdt := (rectW-wl-wr)*cur div total;
732 if (wdt > rectW-wl-wr) then wdt := rectW-wr-wr;
733 if (wdt > 0) then
734 begin
735 my := y0; // don't be so smart, ketmar: +(rectH-wm) div 2;
736 glScissor(x0+wl, gScreenHeight-my-rectH, wdt, hm);
737 f := x0+wl;
738 while (wdt > 0) do
739 begin
740 e_DrawSize(idm, f, y0, 0, true, false, wm, hm);
741 f += wm;
742 wdt -= wm;
743 end;
744 end;
746 glScissor(0, 0, gScreenWidth, gScreenHeight);
747 end
748 else
749 begin
750 rectW := gScreenWidth-64;
751 rectH := 16;
753 x0 := (gScreenWidth-rectW) div 2;
754 y0 := gScreenHeight-rectH-64;
755 if (y0 < 2) then y0 := 2;
757 glDisable(GL_BLEND);
758 glDisable(GL_TEXTURE_2D);
760 //glClearColor(0, 0, 0, 0);
761 //glClear(GL_COLOR_BUFFER_BIT);
763 glColor4ub(127, 127, 127, 255);
764 drawRect(x0-2, y0-2, rectW+4, rectH+4);
766 glColor4ub(0, 0, 0, 255);
767 drawRect(x0-1, y0-1, rectW+2, rectH+2);
769 glColor4ub(127, 127, 127, 255);
770 wdt := rectW*cur div total;
771 if (wdt > rectW) then wdt := rectW;
772 drawRect(x0, y0, wdt, rectH);
773 end;
774 end;
776 var
777 ww, hh: Word;
778 xx, yy, i: Integer;
779 s: String;
780 begin
781 if (Length(LoadingStat.Msgs) = 0) then exit;
783 e_CharFont_GetSize(gMenuFont, _lc[I_MENU_LOADING], ww, hh);
784 yy := (gScreenHeight div 3);
785 e_CharFont_Print(gMenuFont, (gScreenWidth div 2)-(ww div 2), yy-2*hh, _lc[I_MENU_LOADING]);
786 xx := (gScreenWidth div 3);
788 with LoadingStat do
789 begin
790 for i := 0 to NextMsg-1 do
791 begin
792 if (i = (NextMsg-1)) and (MaxValue > 0) then
793 s := Format('%s: %d/%d', [Msgs[i], CurValue, MaxValue])
794 else
795 s := Msgs[i];
797 e_CharFont_PrintEx(gMenuSmallFont, xx, yy, s, _RGB(255, 0, 0));
798 yy := yy + LOADING_INTERLINE;
799 PBarWasHere := drawPBar(CurValue, MaxValue, PBarWasHere);
800 end;
801 end;
802 end;
804 procedure r_Game_DrawMenuBackground (tex: AnsiString);
805 var
806 w, h: Word;
807 ID: DWord;
809 begin
810 if g_Texture_Get(tex, ID) then
811 begin
812 e_Clear(GL_COLOR_BUFFER_BIT, 0, 0, 0);
813 e_GetTextureSize(ID, @w, @h);
814 if w = h then
815 w := round(w * 1.333 * (gScreenHeight / h))
816 else
817 w := trunc(w * (gScreenHeight / h));
818 e_DrawSize(ID, (gScreenWidth - w) div 2, 0, 0, False, False, w, gScreenHeight);
819 end
820 else e_Clear(GL_COLOR_BUFFER_BIT, 0, 0, 0);
821 end;
823 procedure DrawMinimap(p: TPlayer; RenderRect: e_graphics.TRect);
824 var
825 a, aX, aY, aX2, aY2, Scale, ScaleSz: Integer;
827 function monDraw (mon: TMonster): Boolean;
828 begin
829 result := false; // don't stop
830 with mon do
831 begin
832 if alive then
833 begin
834 // Левый верхний угол
835 aX := Obj.X div ScaleSz + 1;
836 aY := Obj.Y div ScaleSz + 1;
837 // Размеры
838 aX2 := max(Obj.Rect.Width div ScaleSz, 1);
839 aY2 := max(Obj.Rect.Height div ScaleSz, 1);
840 // Правый нижний угол
841 aX2 := aX + aX2 - 1;
842 aY2 := aY + aY2 - 1;
843 e_DrawFillQuad(aX, aY, aX2, aY2, 255, 255, 0, 0);
844 end;
845 end;
846 end;
848 begin
849 if (gMapInfo.Width > RenderRect.Right - RenderRect.Left) or
850 (gMapInfo.Height > RenderRect.Bottom - RenderRect.Top) then
851 begin
852 Scale := 1;
853 // Сколько пикселов карты в 1 пикселе мини-карты:
854 ScaleSz := 16 div Scale;
855 // Размеры мини-карты:
856 aX := max(gMapInfo.Width div ScaleSz, 1);
857 aY := max(gMapInfo.Height div ScaleSz, 1);
858 // Рамка карты:
859 e_DrawFillQuad(0, 0, aX-1, aY-1, 0, 0, 0, 0);
861 if gWalls <> nil then
862 begin
863 // Рисуем стены:
864 for a := 0 to High(gWalls) do
865 with gWalls[a] do
866 if PanelType <> 0 then
867 begin
868 // Левый верхний угол:
869 aX := X div ScaleSz;
870 aY := Y div ScaleSz;
871 // Размеры:
872 aX2 := max(Width div ScaleSz, 1);
873 aY2 := max(Height div ScaleSz, 1);
874 // Правый нижний угол:
875 aX2 := aX + aX2 - 1;
876 aY2 := aY + aY2 - 1;
878 case PanelType of
879 PANEL_WALL: e_DrawFillQuad(aX, aY, aX2, aY2, 208, 208, 208, 0);
880 PANEL_OPENDOOR, PANEL_CLOSEDOOR:
881 if Enabled then e_DrawFillQuad(aX, aY, aX2, aY2, 160, 160, 160, 0);
882 end;
883 end;
884 end;
885 if gSteps <> nil then
886 begin
887 // Рисуем ступени:
888 for a := 0 to High(gSteps) do
889 with gSteps[a] do
890 if PanelType <> 0 then
891 begin
892 // Левый верхний угол:
893 aX := X div ScaleSz;
894 aY := Y div ScaleSz;
895 // Размеры:
896 aX2 := max(Width div ScaleSz, 1);
897 aY2 := max(Height div ScaleSz, 1);
898 // Правый нижний угол:
899 aX2 := aX + aX2 - 1;
900 aY2 := aY + aY2 - 1;
902 e_DrawFillQuad(aX, aY, aX2, aY2, 128, 128, 128, 0);
903 end;
904 end;
905 if gLifts <> nil then
906 begin
907 // Рисуем лифты:
908 for a := 0 to High(gLifts) do
909 with gLifts[a] do
910 if PanelType <> 0 then
911 begin
912 // Левый верхний угол:
913 aX := X div ScaleSz;
914 aY := Y div ScaleSz;
915 // Размеры:
916 aX2 := max(Width div ScaleSz, 1);
917 aY2 := max(Height div ScaleSz, 1);
918 // Правый нижний угол:
919 aX2 := aX + aX2 - 1;
920 aY2 := aY + aY2 - 1;
922 case LiftType of
923 LIFTTYPE_UP: e_DrawFillQuad(aX, aY, aX2, aY2, 116, 72, 36, 0);
924 LIFTTYPE_DOWN: e_DrawFillQuad(aX, aY, aX2, aY2, 116, 124, 96, 0);
925 LIFTTYPE_LEFT: e_DrawFillQuad(aX, aY, aX2, aY2, 200, 80, 4, 0);
926 LIFTTYPE_RIGHT: e_DrawFillQuad(aX, aY, aX2, aY2, 252, 140, 56, 0);
927 end;
928 end;
929 end;
930 if gWater <> nil then
931 begin
932 // Рисуем воду:
933 for a := 0 to High(gWater) do
934 with gWater[a] do
935 if PanelType <> 0 then
936 begin
937 // Левый верхний угол:
938 aX := X div ScaleSz;
939 aY := Y div ScaleSz;
940 // Размеры:
941 aX2 := max(Width div ScaleSz, 1);
942 aY2 := max(Height div ScaleSz, 1);
943 // Правый нижний угол:
944 aX2 := aX + aX2 - 1;
945 aY2 := aY + aY2 - 1;
947 e_DrawFillQuad(aX, aY, aX2, aY2, 0, 0, 192, 0);
948 end;
949 end;
950 if gAcid1 <> nil then
951 begin
952 // Рисуем кислоту 1:
953 for a := 0 to High(gAcid1) do
954 with gAcid1[a] do
955 if PanelType <> 0 then
956 begin
957 // Левый верхний угол:
958 aX := X div ScaleSz;
959 aY := Y div ScaleSz;
960 // Размеры:
961 aX2 := max(Width div ScaleSz, 1);
962 aY2 := max(Height div ScaleSz, 1);
963 // Правый нижний угол:
964 aX2 := aX + aX2 - 1;
965 aY2 := aY + aY2 - 1;
967 e_DrawFillQuad(aX, aY, aX2, aY2, 0, 176, 0, 0);
968 end;
969 end;
970 if gAcid2 <> nil then
971 begin
972 // Рисуем кислоту 2:
973 for a := 0 to High(gAcid2) do
974 with gAcid2[a] do
975 if PanelType <> 0 then
976 begin
977 // Левый верхний угол:
978 aX := X div ScaleSz;
979 aY := Y div ScaleSz;
980 // Размеры:
981 aX2 := max(Width div ScaleSz, 1);
982 aY2 := max(Height div ScaleSz, 1);
983 // Правый нижний угол:
984 aX2 := aX + aX2 - 1;
985 aY2 := aY + aY2 - 1;
987 e_DrawFillQuad(aX, aY, aX2, aY2, 176, 0, 0, 0);
988 end;
989 end;
990 if gPlayers <> nil then
991 begin
992 // Рисуем игроков:
993 for a := 0 to High(gPlayers) do
994 if gPlayers[a] <> nil then with gPlayers[a] do
995 if alive then begin
996 // Левый верхний угол:
997 aX := Obj.X div ScaleSz + 1;
998 aY := Obj.Y div ScaleSz + 1;
999 // Размеры:
1000 aX2 := max(Obj.Rect.Width div ScaleSz, 1);
1001 aY2 := max(Obj.Rect.Height div ScaleSz, 1);
1002 // Правый нижний угол:
1003 aX2 := aX + aX2 - 1;
1004 aY2 := aY + aY2 - 1;
1006 if gPlayers[a] = p then
1007 e_DrawFillQuad(aX, aY, aX2, aY2, 0, 255, 0, 0)
1008 else
1009 case Team of
1010 TEAM_RED: e_DrawFillQuad(aX, aY, aX2, aY2, 255, 0, 0, 0);
1011 TEAM_BLUE: e_DrawFillQuad(aX, aY, aX2, aY2, 0, 0, 255, 0);
1012 else e_DrawFillQuad(aX, aY, aX2, aY2, 255, 128, 0, 0);
1013 end;
1014 end;
1015 end;
1016 // Рисуем монстров
1017 g_Mons_ForEach(monDraw);
1018 end;
1019 end;
1022 procedure renderAmbientQuad (hasAmbient: Boolean; constref ambColor: TDFColor);
1023 begin
1024 if not hasAmbient then exit;
1025 e_AmbientQuad(sX, sY, sWidth, sHeight, ambColor.r, ambColor.g, ambColor.b, ambColor.a);
1026 end;
1029 // setup sX, sY, sWidth, sHeight, and transformation matrix before calling this!
1030 //FIXME: broken for splitscreen mode
1031 procedure renderDynLightsInternal ();
1032 var
1033 //hasAmbient: Boolean;
1034 //ambColor: TDFColor;
1035 lln: Integer;
1036 lx, ly, lrad: Integer;
1037 scxywh: array[0..3] of GLint;
1038 wassc: Boolean;
1039 begin
1040 if e_NoGraphics then exit;
1042 //TODO: lights should be in separate grid, i think
1043 // but on the other side: grid may be slower for dynlights, as their lifetime is short
1044 if (not gwin_k8_enable_light_experiments) or (not gwin_has_stencil) or (g_dynLightCount < 1) then exit;
1046 // rendering mode
1047 //ambColor := gCurrentMap['light_ambient'].rgba;
1048 //hasAmbient := (not ambColor.isOpaque) or (not ambColor.isBlack);
1050 { // this will multiply incoming color to alpha from framebuffer
1051 glEnable(GL_BLEND);
1052 glBlendFunc(GL_DST_ALPHA, GL_ONE);
1055 (*
1056 * light rendering: (INVALID!)
1057 * glStencilFunc(GL_EQUAL, 0, $ff);
1058 * for each light:
1059 * glClear(GL_STENCIL_BUFFER_BIT);
1060 * glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
1061 * draw shadow volume into stencil buffer
1062 * glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // modify color buffer
1063 * glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // don't modify stencil buffer
1064 * turn off blending
1065 * draw color-less quad with light alpha (WARNING! don't touch color!)
1066 * glEnable(GL_BLEND);
1067 * glBlendFunc(GL_DST_ALPHA, GL_ONE);
1068 * draw all geometry up to and including walls (with alpha-testing, probably) -- this does lighting
1069 *)
1070 wassc := (glIsEnabled(GL_SCISSOR_TEST) <> 0);
1071 if wassc then glGetIntegerv(GL_SCISSOR_BOX, @scxywh[0]) else glGetIntegerv(GL_VIEWPORT, @scxywh[0]);
1073 // setup OpenGL parameters
1074 glStencilMask($FFFFFFFF);
1075 glStencilFunc(GL_ALWAYS, 0, $FFFFFFFF);
1076 glEnable(GL_STENCIL_TEST);
1077 glEnable(GL_SCISSOR_TEST);
1078 glClear(GL_STENCIL_BUFFER_BIT);
1079 glStencilFunc(GL_EQUAL, 0, $ff);
1081 for lln := 0 to g_dynLightCount-1 do
1082 begin
1083 lx := g_dynLights[lln].x;
1084 ly := g_dynLights[lln].y;
1085 lrad := g_dynLights[lln].radius;
1086 if (lrad < 3) then continue;
1088 if (lx-sX+lrad < 0) then continue;
1089 if (ly-sY+lrad < 0) then continue;
1090 if (lx-sX-lrad >= gPlayerScreenSize.X) then continue;
1091 if (ly-sY-lrad >= gPlayerScreenSize.Y) then continue;
1093 // set scissor to optimize drawing
1094 if (g_dbg_scale = 1.0) then
1095 begin
1096 glScissor((lx-sX)-lrad+2, gPlayerScreenSize.Y-(ly-sY)-lrad-1+2, lrad*2-4, lrad*2-4);
1097 end
1098 else
1099 begin
1100 glScissor(0, 0, gScreenWidth, gScreenHeight);
1101 end;
1102 // no need to clear stencil buffer, light blitting will do it for us... but only for normal scale
1103 if (g_dbg_scale <> 1.0) then glClear(GL_STENCIL_BUFFER_BIT);
1104 glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
1105 // draw extruded panels
1106 glDisable(GL_TEXTURE_2D);
1107 glDisable(GL_BLEND);
1108 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // no need to modify color buffer
1109 if (lrad > 4) then r_Map_DrawPanelShadowVolumes(lx, ly, lrad);
1110 // render light texture
1111 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // modify color buffer
1112 glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); // draw light, and clear stencil buffer
1113 // blend it
1114 glEnable(GL_BLEND);
1115 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1116 glEnable(GL_TEXTURE_2D);
1117 // color and opacity
1118 glColor4f(g_dynLights[lln].r, g_dynLights[lln].g, g_dynLights[lln].b, g_dynLights[lln].a);
1119 glBindTexture(GL_TEXTURE_2D, g_Texture_Light());
1120 glBegin(GL_QUADS);
1121 glTexCoord2f(0.0, 0.0); glVertex2i(lx-lrad, ly-lrad); // top-left
1122 glTexCoord2f(1.0, 0.0); glVertex2i(lx+lrad, ly-lrad); // top-right
1123 glTexCoord2f(1.0, 1.0); glVertex2i(lx+lrad, ly+lrad); // bottom-right
1124 glTexCoord2f(0.0, 1.0); glVertex2i(lx-lrad, ly+lrad); // bottom-left
1125 glEnd();
1126 end;
1128 // done
1129 glDisable(GL_STENCIL_TEST);
1130 glDisable(GL_BLEND);
1131 glDisable(GL_SCISSOR_TEST);
1132 //glScissor(0, 0, sWidth, sHeight);
1134 glScissor(scxywh[0], scxywh[1], scxywh[2], scxywh[3]);
1135 if wassc then glEnable(GL_SCISSOR_TEST) else glDisable(GL_SCISSOR_TEST);
1136 end;
1139 function fixViewportForScale (): Boolean;
1140 var
1141 nx0, ny0, nw, nh: Integer;
1142 begin
1143 result := false;
1144 if (g_dbg_scale <> 1.0) then
1145 begin
1146 result := true;
1147 nx0 := round(sX-(gPlayerScreenSize.X-(sWidth*g_dbg_scale))/2/g_dbg_scale);
1148 ny0 := round(sY-(gPlayerScreenSize.Y-(sHeight*g_dbg_scale))/2/g_dbg_scale);
1149 nw := round(sWidth/g_dbg_scale);
1150 nh := round(sHeight/g_dbg_scale);
1151 sX := nx0;
1152 sY := ny0;
1153 sWidth := nw;
1154 sHeight := nh;
1155 end;
1156 end;
1159 // setup sX, sY, sWidth, sHeight, and transformation matrix before calling this!
1160 // WARNING! this WILL CALL `glTranslatef()`, but won't restore matrices!
1161 procedure renderMapInternal (backXOfs, backYOfs: Integer; setTransMatrix: Boolean);
1162 type
1163 TDrawCB = procedure ();
1165 var
1166 hasAmbient: Boolean;
1167 ambColor: TDFColor;
1168 doAmbient: Boolean = false;
1170 procedure drawPanelType (profname: AnsiString; panType: DWord; doDraw: Boolean);
1171 var
1172 tagmask: Integer;
1173 pan: TPanel;
1174 begin
1175 if (profileFrameDraw <> nil) then profileFrameDraw.sectionBegin(profname);
1176 if gdbg_map_use_accel_render then
1177 begin
1178 tagmask := panelTypeToTag(panType);
1179 while (gDrawPanelList.count > 0) do
1180 begin
1181 pan := TPanel(gDrawPanelList.front());
1182 if ((pan.tag and tagmask) = 0) then break;
1183 if doDraw then r_Panel_Draw(pan, doAmbient, ambColor);
1184 gDrawPanelList.popFront();
1185 end;
1186 end
1187 else
1188 begin
1189 if doDraw then r_Map_DrawPanels(panType, hasAmbient, ambColor);
1190 end;
1191 if (profileFrameDraw <> nil) then profileFrameDraw.sectionEnd();
1192 end;
1194 procedure drawOther (profname: AnsiString; cb: TDrawCB);
1195 begin
1196 if (profileFrameDraw <> nil) then profileFrameDraw.sectionBegin(profname);
1197 if assigned(cb) then cb();
1198 if (profileFrameDraw <> nil) then profileFrameDraw.sectionEnd();
1199 end;
1201 begin
1202 if (profileFrameDraw <> nil) then profileFrameDraw.sectionBegin('total');
1204 // our accelerated renderer will collect all panels to gDrawPanelList
1205 // we can use panel tag to render level parts (see GridTagXXX in g_map.pas)
1206 if (profileFrameDraw <> nil) then profileFrameDraw.sectionBegin('collect');
1207 if gdbg_map_use_accel_render then
1208 begin
1209 r_Map_CollectDrawPanels(sX, sY, sWidth, sHeight);
1210 end;
1211 if (profileFrameDraw <> nil) then profileFrameDraw.sectionEnd();
1213 if (profileFrameDraw <> nil) then profileFrameDraw.sectionBegin('skyback');
1214 r_Map_DrawBack(backXOfs, backYOfs);
1215 if (profileFrameDraw <> nil) then profileFrameDraw.sectionEnd();
1217 if setTransMatrix then
1218 begin
1219 //if (g_dbg_scale <> 1.0) then glTranslatef(0.0, -0.375/2, 0);
1220 glScalef(g_dbg_scale, g_dbg_scale, 1.0);
1221 glTranslatef(-sX, -sY, 0);
1222 end;
1224 // rendering mode
1225 ambColor := gCurrentMap['light_ambient'].rgba;
1226 hasAmbient := (not ambColor.isOpaque) or (not ambColor.isBlack);
1229 if hasAmbient then
1230 begin
1231 //writeln('color: (', ambColor.r, ',', ambColor.g, ',', ambColor.b, ',', ambColor.a, ')');
1232 glColor4ub(ambColor.r, ambColor.g, ambColor.b, ambColor.a);
1233 glClear(GL_COLOR_BUFFER_BIT);
1234 end;
1236 //writeln('color: (', ambColor.r, ',', ambColor.g, ',', ambColor.b, ',', ambColor.a, ')');
1239 drawPanelType('*back', PANEL_BACK, g_rlayer_back);
1240 drawPanelType('*step', PANEL_STEP, g_rlayer_step);
1241 drawOther('items', @r_Items_Draw);
1242 drawOther('weapons', @r_Weapon_Draw);
1243 drawOther('shells', @g_Player_DrawShells);
1244 drawOther('drawall', @g_Player_DrawAll);
1245 drawOther('corpses', @g_Player_DrawCorpses);
1246 drawPanelType('*wall', PANEL_WALL, g_rlayer_wall);
1247 drawOther('monsters', @r_Monsters_Draw);
1248 drawOther('itemdrop', @r_Items_DrawDrop);
1249 drawPanelType('*door', PANEL_CLOSEDOOR, g_rlayer_door);
1250 drawOther('gfx', @r_GFX_Draw);
1251 drawOther('flags', @r_Map_DrawFlags);
1252 drawPanelType('*acid1', PANEL_ACID1, g_rlayer_acid1);
1253 drawPanelType('*acid2', PANEL_ACID2, g_rlayer_acid2);
1254 drawPanelType('*water', PANEL_WATER, g_rlayer_water);
1255 drawOther('dynlights', @renderDynLightsInternal);
1257 if hasAmbient {and ((not g_playerLight) or (not gwin_has_stencil) or (g_dynLightCount < 1))} then
1258 begin
1259 renderAmbientQuad(hasAmbient, ambColor);
1260 end;
1262 doAmbient := true;
1263 drawPanelType('*fore', PANEL_FORE, g_rlayer_fore);
1266 if g_debug_HealthBar then
1267 begin
1268 r_Monsters_DrawHealth();
1269 g_Player_DrawHealth();
1270 end;
1272 if (profileFrameDraw <> nil) then profileFrameDraw.mainEnd(); // map rendering
1273 end;
1276 procedure DrawMapView(x, y, w, h: Integer);
1278 var
1279 bx, by: Integer;
1280 begin
1281 glPushMatrix();
1283 bx := Round(x/(gMapInfo.Width - w)*(gBackSize.X - w));
1284 by := Round(y/(gMapInfo.Height - h)*(gBackSize.Y - h));
1286 sX := x;
1287 sY := y;
1288 sWidth := w;
1289 sHeight := h;
1291 fixViewportForScale();
1292 renderMapInternal(-bx, -by, true);
1294 glPopMatrix();
1295 end;
1298 procedure DrawPlayer(p: TPlayer);
1299 var
1300 px, py, a, b, c, d, i, fX, fY: Integer;
1301 camObj: TObj;
1302 //R: TRect;
1303 begin
1304 if (p = nil) or (p.FDummy) then
1305 begin
1306 glPushMatrix();
1307 r_Map_DrawBack(0, 0);
1308 glPopMatrix();
1309 Exit;
1310 end;
1312 if (profileFrameDraw = nil) then profileFrameDraw := TProfiler.Create('RENDER', g_profile_history_size);
1313 if (profileFrameDraw <> nil) then profileFrameDraw.mainBegin(g_profile_frame_draw);
1315 gPlayerDrawn := p;
1317 glPushMatrix();
1319 camObj := p.getCameraObj();
1320 camObj.lerp(gLerpFactor, fX, fY);
1321 px := fX + PLAYER_RECT_CX;
1322 py := fY + PLAYER_RECT_CY+nlerp(p.SlopeOld, camObj.slopeUpLeft, gLerpFactor);
1324 if (g_dbg_scale = 1.0) and (not g_dbg_ignore_bounds) then
1325 begin
1326 if (px > (gPlayerScreenSize.X div 2)) then a := -px+(gPlayerScreenSize.X div 2) else a := 0;
1327 if (py > (gPlayerScreenSize.Y div 2)) then b := -py+(gPlayerScreenSize.Y div 2) else b := 0;
1329 if (px > gMapInfo.Width-(gPlayerScreenSize.X div 2)) then a := -gMapInfo.Width+gPlayerScreenSize.X;
1330 if (py > gMapInfo.Height-(gPlayerScreenSize.Y div 2)) then b := -gMapInfo.Height+gPlayerScreenSize.Y;
1332 if (gMapInfo.Width = gPlayerScreenSize.X) then a := 0
1333 else if (gMapInfo.Width < gPlayerScreenSize.X) then
1334 begin
1335 // hcenter
1336 a := (gPlayerScreenSize.X-gMapInfo.Width) div 2;
1337 end;
1339 if (gMapInfo.Height = gPlayerScreenSize.Y) then b := 0
1340 else if (gMapInfo.Height < gPlayerScreenSize.Y) then
1341 begin
1342 // vcenter
1343 b := (gPlayerScreenSize.Y-gMapInfo.Height) div 2;
1344 end;
1345 end
1346 else
1347 begin
1348 // scaled, ignore level bounds
1349 a := -px+(gPlayerScreenSize.X div 2);
1350 b := -py+(gPlayerScreenSize.Y div 2);
1351 end;
1353 sX := -a;
1354 sY := -b;
1355 sWidth := gPlayerScreenSize.X;
1356 sHeight := gPlayerScreenSize.Y;
1357 fixViewportForScale();
1359 i := py - (sY + sHeight div 2);
1360 if (p.IncCam > 0) then
1361 begin
1362 // clamp to level bounds
1363 if (sY - p.IncCam < 0) then
1364 p.IncCam := nclamp(sY, 0, 120);
1365 // clamp around player position
1366 if (i > 0) then
1367 p.IncCam := nclamp(p.IncCam, 0, max(0, 120 - i));
1368 end
1369 else if (p.IncCam < 0) then
1370 begin
1371 // clamp to level bounds
1372 if (sY + sHeight - p.IncCam > gMapInfo.Height) then
1373 p.IncCam := nclamp(sY + sHeight - gMapInfo.Height, -120, 0);
1374 // clamp around player position
1375 if (i < 0) then
1376 p.IncCam := nclamp(p.IncCam, min(0, -120 - i), 0);
1377 end;
1379 sY := sY - nlerp(p.IncCamOld, p.IncCam, gLerpFactor);
1381 if (not g_dbg_ignore_bounds) then
1382 begin
1383 if (sX+sWidth > gMapInfo.Width) then sX := gMapInfo.Width-sWidth;
1384 if (sY+sHeight > gMapInfo.Height) then sY := gMapInfo.Height-sHeight;
1385 if (sX < 0) then sX := 0;
1386 if (sY < 0) then sY := 0;
1387 end;
1389 if (gBackSize.X <= gPlayerScreenSize.X) or (gMapInfo.Width <= sWidth) then c := 0 else c := trunc((gBackSize.X-gPlayerScreenSize.X)*sX/(gMapInfo.Width-sWidth));
1390 if (gBackSize.Y <= gPlayerScreenSize.Y) or (gMapInfo.Height <= sHeight) then d := 0 else d := trunc((gBackSize.Y-gPlayerScreenSize.Y)*sY/(gMapInfo.Height-sHeight));
1392 //r_smallmap_h: 0: left; 1: center; 2: right
1393 //r_smallmap_v: 0: top; 1: center; 2: bottom
1394 // horiz small map?
1395 if (gMapInfo.Width = sWidth) then
1396 begin
1397 sX := 0;
1398 end
1399 else if (gMapInfo.Width < sWidth) then
1400 begin
1401 case r_smallmap_h of
1402 1: sX := -((sWidth-gMapInfo.Width) div 2); // center
1403 2: sX := -(sWidth-gMapInfo.Width); // right
1404 else sX := 0; // left
1405 end;
1406 end;
1407 // vert small map?
1408 if (gMapInfo.Height = sHeight) then
1409 begin
1410 sY := 0;
1411 end
1412 else if (gMapInfo.Height < sHeight) then
1413 begin
1414 case r_smallmap_v of
1415 1: sY := -((sHeight-gMapInfo.Height) div 2); // center
1416 2: sY := -(sHeight-gMapInfo.Height); // bottom
1417 else sY := 0; // top
1418 end;
1419 end;
1421 p.viewPortX := sX;
1422 p.viewPortY := sY;
1423 p.viewPortW := sWidth;
1424 p.viewPortH := sHeight;
1426 {$IFDEF ENABLE_HOLMES}
1427 if (p = gPlayer1) then
1428 begin
1429 g_Holmes_plrViewPos(sX, sY);
1430 g_Holmes_plrViewSize(sWidth, sHeight);
1431 end;
1432 {$ENDIF}
1434 renderMapInternal(-c, -d, true);
1436 if (gGameSettings.GameMode <> GM_SINGLE) and (gPlayerIndicator > 0) then
1437 case gPlayerIndicator of
1438 1:
1439 p.DrawIndicator(_RGB(255, 255, 255));
1441 2:
1442 for i := 0 to High(gPlayers) do
1443 if gPlayers[i] <> nil then
1444 if gPlayers[i] = p then p.DrawIndicator(_RGB(255, 255, 255))
1445 else if (gPlayers[i].Team = p.Team) and (gPlayers[i].Team <> TEAM_NONE) then
1446 if gPlayerIndicatorStyle = 1 then
1447 gPlayers[i].DrawIndicator(_RGB(192, 192, 192))
1448 else gPlayers[i].DrawIndicator(gPlayers[i].GetColor);
1449 end;
1452 for a := 0 to High(gCollideMap) do
1453 for b := 0 to High(gCollideMap[a]) do
1454 begin
1455 d := 0;
1456 if ByteBool(gCollideMap[a, b] and MARK_WALL) then
1457 d := d + 1;
1458 if ByteBool(gCollideMap[a, b] and MARK_DOOR) then
1459 d := d + 2;
1461 case d of
1462 1: e_DrawPoint(1, b, a, 200, 200, 200);
1463 2: e_DrawPoint(1, b, a, 64, 64, 255);
1464 3: e_DrawPoint(1, b, a, 255, 0, 255);
1465 end;
1466 end;
1469 glPopMatrix();
1471 p.DrawPain();
1472 p.DrawPickup();
1473 p.DrawRulez();
1474 if gShowMap then DrawMinimap(p, _TRect(0, 0, 128, 128));
1475 if g_Debug_Player then
1476 g_Player_DrawDebug(p);
1477 p.DrawGUI();
1478 end;
1480 procedure drawProfilers ();
1481 var
1482 px: Integer = -1;
1483 py: Integer = -1;
1484 begin
1485 if g_profile_frame_draw and (profileFrameDraw <> nil) then px := px-drawProfiles(px, py, profileFrameDraw);
1486 if g_profile_collision and (profMapCollision <> nil) then begin px := px-drawProfiles(px, py, profMapCollision); py -= calcProfilesHeight(profMonsLOS); end;
1487 if g_profile_los and (profMonsLOS <> nil) then begin px := px-drawProfiles(px, py, profMonsLOS); py -= calcProfilesHeight(profMonsLOS); end;
1488 end;
1490 procedure r_Game_Draw();
1491 var
1492 ID: DWORD;
1493 w, h: Word;
1494 ww, hh: Byte;
1495 Time: Int64;
1496 back: string;
1497 plView1, plView2: TPlayer;
1498 Split: Boolean;
1499 begin
1500 if gExit = EXIT_QUIT then Exit;
1502 Time := sys_GetTicks() {div 1000};
1503 FPSCounter := FPSCounter+1;
1504 if Time - FPSTime >= 1000 then
1505 begin
1506 FPS := FPSCounter;
1507 FPSCounter := 0;
1508 FPSTime := Time;
1509 end;
1511 e_SetRendertarget(True);
1512 e_SetViewPort(0, 0, gScreenWidth, gScreenHeight);
1514 if gGameOn or (gState = STATE_FOLD) then
1515 begin
1516 if (gPlayer1 <> nil) and (gPlayer2 <> nil) then
1517 begin
1518 gSpectMode := SPECT_NONE;
1519 if not gRevertPlayers then
1520 begin
1521 plView1 := gPlayer1;
1522 plView2 := gPlayer2;
1523 end
1524 else
1525 begin
1526 plView1 := gPlayer2;
1527 plView2 := gPlayer1;
1528 end;
1529 end
1530 else
1531 if (gPlayer1 <> nil) or (gPlayer2 <> nil) then
1532 begin
1533 gSpectMode := SPECT_NONE;
1534 if gPlayer2 = nil then
1535 plView1 := gPlayer1
1536 else
1537 plView1 := gPlayer2;
1538 plView2 := nil;
1539 end
1540 else
1541 begin
1542 plView1 := nil;
1543 plView2 := nil;
1544 end;
1546 if (plView1 = nil) and (plView2 = nil) and (gSpectMode = SPECT_NONE) then
1547 gSpectMode := SPECT_STATS;
1549 if gSpectMode = SPECT_PLAYERS then
1550 if gPlayers <> nil then
1551 begin
1552 plView1 := GetActivePlayer_ByID(gSpectPID1);
1553 if plView1 = nil then
1554 begin
1555 gSpectPID1 := GetActivePlayerID_Next();
1556 plView1 := GetActivePlayer_ByID(gSpectPID1);
1557 end;
1558 if gSpectViewTwo then
1559 begin
1560 plView2 := GetActivePlayer_ByID(gSpectPID2);
1561 if plView2 = nil then
1562 begin
1563 gSpectPID2 := GetActivePlayerID_Next();
1564 plView2 := GetActivePlayer_ByID(gSpectPID2);
1565 end;
1566 end;
1567 end;
1569 if gSpectMode = SPECT_MAPVIEW then
1570 begin
1571 // Режим просмотра карты
1572 Split := False;
1573 e_SetViewPort(0, 0, gScreenWidth, gScreenHeight);
1574 DrawMapView(gSpectX, gSpectY, gScreenWidth, gScreenHeight);
1575 gHearPoint1.Active := True;
1576 gHearPoint1.Coords.X := gScreenWidth div 2 + gSpectX;
1577 gHearPoint1.Coords.Y := gScreenHeight div 2 + gSpectY;
1578 gHearPoint2.Active := False;
1579 end
1580 else
1581 begin
1582 Split := (plView1 <> nil) and (plView2 <> nil);
1584 // Точки слуха игроков
1585 if plView1 <> nil then
1586 begin
1587 gHearPoint1.Active := True;
1588 gHearPoint1.Coords.X := plView1.GameX + PLAYER_RECT.Width;
1589 gHearPoint1.Coords.Y := plView1.GameY + PLAYER_RECT.Height DIV 2;
1590 end else
1591 gHearPoint1.Active := False;
1592 if plView2 <> nil then
1593 begin
1594 gHearPoint2.Active := True;
1595 gHearPoint2.Coords.X := plView2.GameX + PLAYER_RECT.Width;
1596 gHearPoint2.Coords.Y := plView2.GameY + PLAYER_RECT.Height DIV 2;
1597 end else
1598 gHearPoint2.Active := False;
1600 // Размер экранов игроков:
1601 gPlayerScreenSize.X := gScreenWidth-196;
1602 if Split then
1603 begin
1604 gPlayerScreenSize.Y := gScreenHeight div 2;
1605 if gScreenHeight mod 2 = 0 then
1606 Dec(gPlayerScreenSize.Y);
1607 end
1608 else
1609 gPlayerScreenSize.Y := gScreenHeight;
1611 if Split then
1612 if gScreenHeight mod 2 = 0 then
1613 e_SetViewPort(0, gPlayerScreenSize.Y+2, gPlayerScreenSize.X+196, gPlayerScreenSize.Y)
1614 else
1615 e_SetViewPort(0, gPlayerScreenSize.Y+1, gPlayerScreenSize.X+196, gPlayerScreenSize.Y);
1617 DrawPlayer(plView1);
1618 gPlayer1ScreenCoord.X := sX;
1619 gPlayer1ScreenCoord.Y := sY;
1621 if Split then
1622 begin
1623 e_SetViewPort(0, 0, gPlayerScreenSize.X+196, gPlayerScreenSize.Y);
1625 DrawPlayer(plView2);
1626 gPlayer2ScreenCoord.X := sX;
1627 gPlayer2ScreenCoord.Y := sY;
1628 end;
1630 e_SetViewPort(0, 0, gScreenWidth, gScreenHeight);
1632 if Split then
1633 e_DrawLine(2, 0, gScreenHeight div 2, gScreenWidth, gScreenHeight div 2, 0, 0, 0);
1634 end;
1636 {$IFDEF ENABLE_HOLMES}
1637 // draw inspector
1638 if (g_holmes_enabled) then g_Holmes_Draw();
1639 {$ENDIF}
1641 if MessageText <> '' then
1642 begin
1643 w := 0;
1644 h := 0;
1645 e_CharFont_GetSizeFmt(gMenuFont, MessageText, w, h);
1646 if Split then
1647 e_CharFont_PrintFmt(gMenuFont, (gScreenWidth div 2)-(w div 2),
1648 (gScreenHeight div 2)-(h div 2), MessageText)
1649 else
1650 e_CharFont_PrintFmt(gMenuFont, (gScreenWidth div 2)-(w div 2),
1651 Round(gScreenHeight / 2.75)-(h div 2), MessageText);
1652 end;
1654 if IsDrawStat or (gSpectMode = SPECT_STATS) then
1655 DrawStat();
1657 if gSpectHUD and (not gChatShow) and (gSpectMode <> SPECT_NONE) and (not gSpectAuto) then
1658 begin
1659 // Draw spectator GUI
1660 ww := 0;
1661 hh := 0;
1662 e_TextureFontGetSize(gStdFont, ww, hh);
1663 case gSpectMode of
1664 SPECT_STATS:
1665 e_TextureFontPrintEx(0, gScreenHeight - (hh+2)*2, 'MODE: Stats', gStdFont, 255, 255, 255, 1);
1666 SPECT_MAPVIEW:
1667 e_TextureFontPrintEx(0, gScreenHeight - (hh+2)*2, 'MODE: Observe Map', gStdFont, 255, 255, 255, 1);
1668 SPECT_PLAYERS:
1669 e_TextureFontPrintEx(0, gScreenHeight - (hh+2)*2, 'MODE: Watch Players', gStdFont, 255, 255, 255, 1);
1670 end;
1671 e_TextureFontPrintEx(2*ww, gScreenHeight - (hh+2), '< jump >', gStdFont, 255, 255, 255, 1);
1672 if gSpectMode = SPECT_STATS then
1673 begin
1674 e_TextureFontPrintEx(16*ww, gScreenHeight - (hh+2)*2, 'Autoview', gStdFont, 255, 255, 255, 1);
1675 e_TextureFontPrintEx(16*ww, gScreenHeight - (hh+2), '< fire >', gStdFont, 255, 255, 255, 1);
1676 end;
1677 if gSpectMode = SPECT_MAPVIEW then
1678 begin
1679 e_TextureFontPrintEx(22*ww, gScreenHeight - (hh+2)*2, '[-]', gStdFont, 255, 255, 255, 1);
1680 e_TextureFontPrintEx(26*ww, gScreenHeight - (hh+2)*2, 'Step ' + IntToStr(gSpectStep), gStdFont, 255, 255, 255, 1);
1681 e_TextureFontPrintEx(34*ww, gScreenHeight - (hh+2)*2, '[+]', gStdFont, 255, 255, 255, 1);
1682 e_TextureFontPrintEx(18*ww, gScreenHeight - (hh+2), '<prev weap>', gStdFont, 255, 255, 255, 1);
1683 e_TextureFontPrintEx(30*ww, gScreenHeight - (hh+2), '<next weap>', gStdFont, 255, 255, 255, 1);
1684 end;
1685 if gSpectMode = SPECT_PLAYERS then
1686 begin
1687 e_TextureFontPrintEx(22*ww, gScreenHeight - (hh+2)*2, 'Player 1', gStdFont, 255, 255, 255, 1);
1688 e_TextureFontPrintEx(20*ww, gScreenHeight - (hh+2), '<left/right>', gStdFont, 255, 255, 255, 1);
1689 if gSpectViewTwo then
1690 begin
1691 e_TextureFontPrintEx(37*ww, gScreenHeight - (hh+2)*2, 'Player 2', gStdFont, 255, 255, 255, 1);
1692 e_TextureFontPrintEx(34*ww, gScreenHeight - (hh+2), '<prev w/next w>', gStdFont, 255, 255, 255, 1);
1693 e_TextureFontPrintEx(52*ww, gScreenHeight - (hh+2)*2, '2x View', gStdFont, 255, 255, 255, 1);
1694 e_TextureFontPrintEx(51*ww, gScreenHeight - (hh+2), '<up/down>', gStdFont, 255, 255, 255, 1);
1695 end
1696 else
1697 begin
1698 e_TextureFontPrintEx(35*ww, gScreenHeight - (hh+2)*2, '2x View', gStdFont, 255, 255, 255, 1);
1699 e_TextureFontPrintEx(34*ww, gScreenHeight - (hh+2), '<up/down>', gStdFont, 255, 255, 255, 1);
1700 end;
1701 end;
1702 end;
1703 end;
1705 if gPauseMain and gGameOn and (g_ActiveWindow = nil) then
1706 begin
1707 //e_DrawFillQuad(0, 0, gScreenWidth-1, gScreenHeight-1, 48, 48, 48, 180);
1708 e_DarkenQuadWH(0, 0, gScreenWidth, gScreenHeight, 150);
1710 e_CharFont_GetSize(gMenuFont, _lc[I_MENU_PAUSE], w, h);
1711 e_CharFont_Print(gMenuFont, (gScreenWidth div 2)-(w div 2),
1712 (gScreenHeight div 2)-(h div 2), _lc[I_MENU_PAUSE]);
1713 end;
1715 if not gGameOn then
1716 begin
1717 if (gState = STATE_MENU) then
1718 begin
1719 if (g_ActiveWindow = nil) or (g_ActiveWindow.BackTexture = '') then r_Game_DrawMenuBackground('MENU_BACKGROUND');
1720 // F3 at menu will show game loading dialog
1721 if e_KeyPressed(IK_F3) then g_Menu_Show_LoadMenu(true);
1722 if (g_ActiveWindow <> nil) then
1723 begin
1724 //e_DrawFillQuad(0, 0, gScreenWidth-1, gScreenHeight-1, 48, 48, 48, 180);
1725 e_DarkenQuadWH(0, 0, gScreenWidth, gScreenHeight, 150);
1726 end
1727 else
1728 begin
1729 // F3 at titlepic will show game loading dialog
1730 if e_KeyPressed(IK_F3) then
1731 begin
1732 g_Menu_Show_LoadMenu(true);
1733 if (g_ActiveWindow <> nil) then e_DarkenQuadWH(0, 0, gScreenWidth, gScreenHeight, 150);
1734 end;
1735 end;
1736 end;
1738 if gState = STATE_FOLD then
1739 begin
1740 e_DrawFillQuad(0, 0, gScreenWidth-1, gScreenHeight-1, 0, 0, 0, EndingGameCounter);
1741 end;
1743 if gState = STATE_INTERCUSTOM then
1744 begin
1745 if gLastMap and (gGameSettings.GameMode = GM_COOP) then
1746 begin
1747 back := 'TEXTURE_endpic';
1748 if not g_Texture_Get(back, ID) then
1749 back := _lc[I_TEXTURE_ENDPIC];
1750 end
1751 else
1752 back := 'INTER';
1754 r_Game_DrawMenuBackground(back);
1756 DrawCustomStat();
1758 if g_ActiveWindow <> nil then
1759 begin
1760 //e_DrawFillQuad(0, 0, gScreenWidth-1, gScreenHeight-1, 48, 48, 48, 180);
1761 e_DarkenQuadWH(0, 0, gScreenWidth, gScreenHeight, 150);
1762 end;
1763 end;
1765 if gState = STATE_INTERSINGLE then
1766 begin
1767 if EndingGameCounter > 0 then
1768 begin
1769 e_DrawFillQuad(0, 0, gScreenWidth-1, gScreenHeight-1, 0, 0, 0, EndingGameCounter);
1770 end
1771 else
1772 begin
1773 back := 'INTER';
1775 r_Game_DrawMenuBackground(back);
1777 DrawSingleStat();
1779 if g_ActiveWindow <> nil then
1780 begin
1781 //e_DrawFillQuad(0, 0, gScreenWidth-1, gScreenHeight-1, 48, 48, 48, 180);
1782 e_DarkenQuadWH(0, 0, gScreenWidth, gScreenHeight, 150);
1783 end;
1784 end;
1785 end;
1787 if gState = STATE_ENDPIC then
1788 begin
1789 ID := DWORD(-1);
1790 if g_Texture_Get('TEXTURE_endpic', ID) then r_Game_DrawMenuBackground('TEXTURE_endpic')
1791 else r_Game_DrawMenuBackground(_lc[I_TEXTURE_ENDPIC]);
1793 if g_ActiveWindow <> nil then
1794 begin
1795 //e_DrawFillQuad(0, 0, gScreenWidth-1, gScreenHeight-1, 48, 48, 48, 180);
1796 e_DarkenQuadWH(0, 0, gScreenWidth, gScreenHeight, 150);
1797 end;
1798 end;
1800 if gState = STATE_SLIST then
1801 begin
1802 // if g_Texture_Get('MENU_BACKGROUND', ID) then
1803 // begin
1804 // e_DrawSize(ID, 0, 0, 0, False, False, gScreenWidth, gScreenHeight);
1805 // //e_DrawFillQuad(0, 0, gScreenWidth-1, gScreenHeight-1, 48, 48, 48, 180);
1806 // end;
1807 r_Game_DrawMenuBackground('MENU_BACKGROUND');
1808 e_DarkenQuadWH(0, 0, gScreenWidth, gScreenHeight, 150);
1809 g_Serverlist_Draw(slCurrent, slTable);
1810 end;
1811 end;
1813 if g_ActiveWindow <> nil then
1814 begin
1815 if gGameOn then
1816 begin
1817 //e_DrawFillQuad(0, 0, gScreenWidth-1, gScreenHeight-1, 48, 48, 48, 180);
1818 e_DarkenQuadWH(0, 0, gScreenWidth, gScreenHeight, 150);
1819 end;
1820 g_ActiveWindow.Draw();
1821 end;
1823 {$IFNDEF HEADLESS}
1824 r_Console_Draw();
1825 {$ENDIF}
1827 if g_debug_Sounds and gGameOn then
1828 begin
1829 for w := 0 to High(e_SoundsArray) do
1830 for h := 0 to e_SoundsArray[w].nRefs do
1831 e_DrawPoint(1, w+100, h+100, 255, 0, 0);
1832 end;
1834 if gShowFPS then
1835 begin
1836 e_TextureFontPrint(0, 0, Format('FPS: %d', [FPS]), gStdFont);
1837 e_TextureFontPrint(0, 16, Format('UPS: %d', [UPS]), gStdFont);
1838 end;
1840 if gGameOn and gShowTime then
1841 drawTime(gScreenWidth-72, gScreenHeight-16);
1843 if gGameOn then drawProfilers();
1845 // TODO: draw this after the FBO and remap mouse click coordinates
1847 {$IFDEF ENABLE_HOLMES}
1848 g_Holmes_DrawUI();
1849 {$ENDIF}
1851 // blit framebuffer to screen
1853 e_SetRendertarget(False);
1854 e_SetViewPort(0, 0, gWinSizeX, gWinSizeY);
1855 e_BlitFramebuffer(gWinSizeX, gWinSizeY);
1857 // draw the overlay stuff on top of it
1859 g_Touch_Draw;
1860 end;
1862 end.