2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 // sbar.c -- status bar code
26 #define STAT_MINUS 10 // num frame for '-' stats digit
27 cachepic_t *sb_nums[2][11];
28 cachepic_t *sb_colon, *sb_slash;
31 cachepic_t *sb_scorebar;
32 // AK only used by NEX
33 cachepic_t *sb_sbar_minimal;
34 cachepic_t *sb_sbar_overlay;
36 // AK changed the bound to 9
37 cachepic_t *sb_weapons[7][9]; // 0 is active, 1 is owned, 2-5 are flashes
38 cachepic_t *sb_ammo[4];
39 cachepic_t *sb_sigil[4];
40 cachepic_t *sb_armor[3];
41 cachepic_t *sb_items[32];
43 // 0-4 are based on health (in 20 increments)
44 // 0 is static, 1 is temporary animation
45 cachepic_t *sb_faces[5][2];
47 cachepic_t *sb_face_invis;
48 cachepic_t *sb_face_quad;
49 cachepic_t *sb_face_invuln;
50 cachepic_t *sb_face_invis_invuln;
52 qboolean sb_showscores;
54 int sb_lines; // scan lines to draw
56 cachepic_t *rsb_invbar[2];
57 cachepic_t *rsb_weapons[5];
58 cachepic_t *rsb_items[2];
59 cachepic_t *rsb_ammo[3];
60 cachepic_t *rsb_teambord; // PGM 01/19/97 - team color border
62 //MED 01/04/97 added two more weapons + 3 alternates for grenade launcher
63 cachepic_t *hsb_weapons[7][5]; // 0 is active, 1 is owned, 2-5 are flashes
64 //MED 01/04/97 added array to simplify weapon parsing
65 int hipweapons[4] = {HIT_LASER_CANNON_BIT,HIT_MJOLNIR_BIT,4,HIT_PROXIMITY_GUN_BIT};
66 //MED 01/04/97 added hipnotic items array
67 cachepic_t *hsb_items[2];
70 cachepic_t *somsb_health;
71 cachepic_t *somsb_ammo[4];
72 cachepic_t *somsb_armor[3];
74 cachepic_t *zymsb_crosshair_center;
75 cachepic_t *zymsb_crosshair_line;
76 cachepic_t *zymsb_crosshair_health;
77 cachepic_t *zymsb_crosshair_ammo;
78 cachepic_t *zymsb_crosshair_clip;
79 cachepic_t *zymsb_crosshair_background;
80 cachepic_t *zymsb_crosshair_left1;
81 cachepic_t *zymsb_crosshair_left2;
82 cachepic_t *zymsb_crosshair_right;
84 cachepic_t *sb_ranking;
85 cachepic_t *sb_complete;
87 cachepic_t *sb_finale;
89 cvar_t showfps = {CVAR_SAVE, "showfps", "0", "shows your rendered fps (frames per second)"};
90 cvar_t showtime = {CVAR_SAVE, "showtime", "0", "shows current time of day (useful on screenshots)"};
91 cvar_t showtime_format = {CVAR_SAVE, "showtime_format", "%H:%M:%S", "format string for time of day"};
92 cvar_t showdate = {CVAR_SAVE, "showdate", "0", "shows current date (useful on screenshots)"};
93 cvar_t showdate_format = {CVAR_SAVE, "showdate_format", "%Y-%m-%d", "format string for date"};
94 cvar_t sbar_alpha_bg = {CVAR_SAVE, "sbar_alpha_bg", "0.4", "opacity value of the statusbar background image"};
95 cvar_t sbar_alpha_fg = {CVAR_SAVE, "sbar_alpha_fg", "1", "opacity value of the statusbar weapon/item icons and numbers"};
97 cvar_t cl_deathscoreboard = {0, "cl_deathscoreboard", "1", "shows scoreboard (+showscores) while dead"};
99 cvar_t crosshair_color_red = {CVAR_SAVE, "crosshair_color_red", "1", "customizable crosshair color"};
100 cvar_t crosshair_color_green = {CVAR_SAVE, "crosshair_color_green", "0", "customizable crosshair color"};
101 cvar_t crosshair_color_blue = {CVAR_SAVE, "crosshair_color_blue", "0", "customizable crosshair color"};
102 cvar_t crosshair_color_alpha = {CVAR_SAVE, "crosshair_color_alpha", "1", "how opaque the crosshair should be"};
103 cvar_t crosshair_size = {CVAR_SAVE, "crosshair_size", "1", "adjusts size of the crosshair on the screen"};
105 void Sbar_MiniDeathmatchOverlay (int x, int y);
106 void Sbar_DeathmatchOverlay (void);
107 void Sbar_IntermissionOverlay (void);
108 void Sbar_FinaleOverlay (void);
118 void Sbar_ShowScores (void)
122 sb_showscores = true;
132 void Sbar_DontShowScores (void)
134 sb_showscores = false;
137 void sbar_start(void)
141 if (gamemode == GAME_NETHERWORLD)
144 else if (gamemode == GAME_SOM)
146 sb_disc = Draw_CachePic("gfx/disc", true);
148 for (i = 0;i < 10;i++)
149 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
151 somsb_health = Draw_CachePic("gfx/hud_health", true);
152 somsb_ammo[0] = Draw_CachePic("gfx/sb_shells", true);
153 somsb_ammo[1] = Draw_CachePic("gfx/sb_nails", true);
154 somsb_ammo[2] = Draw_CachePic("gfx/sb_rocket", true);
155 somsb_ammo[3] = Draw_CachePic("gfx/sb_cells", true);
156 somsb_armor[0] = Draw_CachePic("gfx/sb_armor1", true);
157 somsb_armor[1] = Draw_CachePic("gfx/sb_armor2", true);
158 somsb_armor[2] = Draw_CachePic("gfx/sb_armor3", true);
160 else if (gamemode == GAME_NEXUIZ)
162 for (i = 0;i < 10;i++)
163 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
164 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus", true);
166 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells", true);
167 sb_ammo[1] = Draw_CachePic ("gfx/sb_bullets", true);
168 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket", true);
169 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells", true);
171 sb_items[2] = Draw_CachePic ("gfx/sb_slowmo", true);
172 sb_items[3] = Draw_CachePic ("gfx/sb_invinc", true);
173 sb_items[4] = Draw_CachePic ("gfx/sb_energy", true);
174 sb_items[5] = Draw_CachePic ("gfx/sb_str", true);
176 sb_items[11] = Draw_CachePic ("gfx/sb_flag_red_taken", true);
177 sb_items[12] = Draw_CachePic ("gfx/sb_flag_red_lost", true);
178 sb_items[13] = Draw_CachePic ("gfx/sb_flag_red_carrying", true);
179 sb_items[14] = Draw_CachePic ("gfx/sb_key_carrying", true);
180 sb_items[15] = Draw_CachePic ("gfx/sb_flag_blue_taken", true);
181 sb_items[16] = Draw_CachePic ("gfx/sb_flag_blue_lost", true);
182 sb_items[17] = Draw_CachePic ("gfx/sb_flag_blue_carrying", true);
184 sb_sbar = Draw_CachePic("gfx/sbar", true);
185 sb_sbar_minimal = Draw_CachePic("gfx/sbar_minimal", true);
186 sb_sbar_overlay = Draw_CachePic("gfx/sbar_overlay", true);
188 for(i = 0; i < 9;i++)
189 sb_weapons[0][i] = Draw_CachePic(va("gfx/inv_weapon%i",i), true);
191 else if (gamemode == GAME_ZYMOTIC)
193 zymsb_crosshair_center = Draw_CachePic ("gfx/hud/crosshair_center", true);
194 zymsb_crosshair_line = Draw_CachePic ("gfx/hud/crosshair_line", true);
195 zymsb_crosshair_health = Draw_CachePic ("gfx/hud/crosshair_health", true);
196 zymsb_crosshair_clip = Draw_CachePic ("gfx/hud/crosshair_clip", true);
197 zymsb_crosshair_ammo = Draw_CachePic ("gfx/hud/crosshair_ammo", true);
198 zymsb_crosshair_background = Draw_CachePic ("gfx/hud/crosshair_background", true);
199 zymsb_crosshair_left1 = Draw_CachePic ("gfx/hud/crosshair_left1", true);
200 zymsb_crosshair_left2 = Draw_CachePic ("gfx/hud/crosshair_left2", true);
201 zymsb_crosshair_right = Draw_CachePic ("gfx/hud/crosshair_right", true);
205 sb_disc = Draw_CachePic("gfx/disc", true);
207 for (i = 0;i < 10;i++)
209 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
210 sb_nums[1][i] = Draw_CachePic (va("gfx/anum_%i",i), true);
213 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus", true);
214 sb_nums[1][10] = Draw_CachePic ("gfx/anum_minus", true);
216 sb_colon = Draw_CachePic ("gfx/num_colon", true);
217 sb_slash = Draw_CachePic ("gfx/num_slash", true);
219 sb_weapons[0][0] = Draw_CachePic ("gfx/inv_shotgun", true);
220 sb_weapons[0][1] = Draw_CachePic ("gfx/inv_sshotgun", true);
221 sb_weapons[0][2] = Draw_CachePic ("gfx/inv_nailgun", true);
222 sb_weapons[0][3] = Draw_CachePic ("gfx/inv_snailgun", true);
223 sb_weapons[0][4] = Draw_CachePic ("gfx/inv_rlaunch", true);
224 sb_weapons[0][5] = Draw_CachePic ("gfx/inv_srlaunch", true);
225 sb_weapons[0][6] = Draw_CachePic ("gfx/inv_lightng", true);
227 sb_weapons[1][0] = Draw_CachePic ("gfx/inv2_shotgun", true);
228 sb_weapons[1][1] = Draw_CachePic ("gfx/inv2_sshotgun", true);
229 sb_weapons[1][2] = Draw_CachePic ("gfx/inv2_nailgun", true);
230 sb_weapons[1][3] = Draw_CachePic ("gfx/inv2_snailgun", true);
231 sb_weapons[1][4] = Draw_CachePic ("gfx/inv2_rlaunch", true);
232 sb_weapons[1][5] = Draw_CachePic ("gfx/inv2_srlaunch", true);
233 sb_weapons[1][6] = Draw_CachePic ("gfx/inv2_lightng", true);
235 for (i = 0;i < 5;i++)
237 sb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_shotgun",i+1), true);
238 sb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_sshotgun",i+1), true);
239 sb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_nailgun",i+1), true);
240 sb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_snailgun",i+1), true);
241 sb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_rlaunch",i+1), true);
242 sb_weapons[2+i][5] = Draw_CachePic (va("gfx/inva%i_srlaunch",i+1), true);
243 sb_weapons[2+i][6] = Draw_CachePic (va("gfx/inva%i_lightng",i+1), true);
246 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells", true);
247 sb_ammo[1] = Draw_CachePic ("gfx/sb_nails", true);
248 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket", true);
249 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells", true);
251 sb_armor[0] = Draw_CachePic ("gfx/sb_armor1", true);
252 sb_armor[1] = Draw_CachePic ("gfx/sb_armor2", true);
253 sb_armor[2] = Draw_CachePic ("gfx/sb_armor3", true);
255 sb_items[0] = Draw_CachePic ("gfx/sb_key1", true);
256 sb_items[1] = Draw_CachePic ("gfx/sb_key2", true);
257 sb_items[2] = Draw_CachePic ("gfx/sb_invis", true);
258 sb_items[3] = Draw_CachePic ("gfx/sb_invuln", true);
259 sb_items[4] = Draw_CachePic ("gfx/sb_suit", true);
260 sb_items[5] = Draw_CachePic ("gfx/sb_quad", true);
262 sb_sigil[0] = Draw_CachePic ("gfx/sb_sigil1", true);
263 sb_sigil[1] = Draw_CachePic ("gfx/sb_sigil2", true);
264 sb_sigil[2] = Draw_CachePic ("gfx/sb_sigil3", true);
265 sb_sigil[3] = Draw_CachePic ("gfx/sb_sigil4", true);
267 sb_faces[4][0] = Draw_CachePic ("gfx/face1", true);
268 sb_faces[4][1] = Draw_CachePic ("gfx/face_p1", true);
269 sb_faces[3][0] = Draw_CachePic ("gfx/face2", true);
270 sb_faces[3][1] = Draw_CachePic ("gfx/face_p2", true);
271 sb_faces[2][0] = Draw_CachePic ("gfx/face3", true);
272 sb_faces[2][1] = Draw_CachePic ("gfx/face_p3", true);
273 sb_faces[1][0] = Draw_CachePic ("gfx/face4", true);
274 sb_faces[1][1] = Draw_CachePic ("gfx/face_p4", true);
275 sb_faces[0][0] = Draw_CachePic ("gfx/face5", true);
276 sb_faces[0][1] = Draw_CachePic ("gfx/face_p5", true);
278 sb_face_invis = Draw_CachePic ("gfx/face_invis", true);
279 sb_face_invuln = Draw_CachePic ("gfx/face_invul2", true);
280 sb_face_invis_invuln = Draw_CachePic ("gfx/face_inv2", true);
281 sb_face_quad = Draw_CachePic ("gfx/face_quad", true);
283 sb_sbar = Draw_CachePic ("gfx/sbar", true);
284 sb_ibar = Draw_CachePic ("gfx/ibar", true);
285 sb_scorebar = Draw_CachePic ("gfx/scorebar", true);
287 //MED 01/04/97 added new hipnotic weapons
288 if (gamemode == GAME_HIPNOTIC)
290 hsb_weapons[0][0] = Draw_CachePic ("gfx/inv_laser", true);
291 hsb_weapons[0][1] = Draw_CachePic ("gfx/inv_mjolnir", true);
292 hsb_weapons[0][2] = Draw_CachePic ("gfx/inv_gren_prox", true);
293 hsb_weapons[0][3] = Draw_CachePic ("gfx/inv_prox_gren", true);
294 hsb_weapons[0][4] = Draw_CachePic ("gfx/inv_prox", true);
296 hsb_weapons[1][0] = Draw_CachePic ("gfx/inv2_laser", true);
297 hsb_weapons[1][1] = Draw_CachePic ("gfx/inv2_mjolnir", true);
298 hsb_weapons[1][2] = Draw_CachePic ("gfx/inv2_gren_prox", true);
299 hsb_weapons[1][3] = Draw_CachePic ("gfx/inv2_prox_gren", true);
300 hsb_weapons[1][4] = Draw_CachePic ("gfx/inv2_prox", true);
302 for (i = 0;i < 5;i++)
304 hsb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_laser",i+1), true);
305 hsb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_mjolnir",i+1), true);
306 hsb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_gren_prox",i+1), true);
307 hsb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_prox_gren",i+1), true);
308 hsb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_prox",i+1), true);
311 hsb_items[0] = Draw_CachePic ("gfx/sb_wsuit", true);
312 hsb_items[1] = Draw_CachePic ("gfx/sb_eshld", true);
314 else if (gamemode == GAME_ROGUE)
316 rsb_invbar[0] = Draw_CachePic ("gfx/r_invbar1", true);
317 rsb_invbar[1] = Draw_CachePic ("gfx/r_invbar2", true);
319 rsb_weapons[0] = Draw_CachePic ("gfx/r_lava", true);
320 rsb_weapons[1] = Draw_CachePic ("gfx/r_superlava", true);
321 rsb_weapons[2] = Draw_CachePic ("gfx/r_gren", true);
322 rsb_weapons[3] = Draw_CachePic ("gfx/r_multirock", true);
323 rsb_weapons[4] = Draw_CachePic ("gfx/r_plasma", true);
325 rsb_items[0] = Draw_CachePic ("gfx/r_shield1", true);
326 rsb_items[1] = Draw_CachePic ("gfx/r_agrav1", true);
328 // PGM 01/19/97 - team color border
329 rsb_teambord = Draw_CachePic ("gfx/r_teambord", true);
330 // PGM 01/19/97 - team color border
332 rsb_ammo[0] = Draw_CachePic ("gfx/r_ammolava", true);
333 rsb_ammo[1] = Draw_CachePic ("gfx/r_ammomulti", true);
334 rsb_ammo[2] = Draw_CachePic ("gfx/r_ammoplasma", true);
338 sb_ranking = Draw_CachePic ("gfx/ranking", true);
339 sb_complete = Draw_CachePic ("gfx/complete", true);
340 sb_inter = Draw_CachePic ("gfx/inter", true);
341 sb_finale = Draw_CachePic ("gfx/finale", true);
344 void sbar_shutdown(void)
348 void sbar_newmap(void)
352 void Sbar_Init (void)
354 Cmd_AddCommand("+showscores", Sbar_ShowScores, "show scoreboard");
355 Cmd_AddCommand("-showscores", Sbar_DontShowScores, "hide scoreboard");
356 Cvar_RegisterVariable(&showfps);
357 Cvar_RegisterVariable(&showtime);
358 Cvar_RegisterVariable(&showtime_format);
359 Cvar_RegisterVariable(&showdate);
360 Cvar_RegisterVariable(&showdate_format);
361 Cvar_RegisterVariable(&sbar_alpha_bg);
362 Cvar_RegisterVariable(&sbar_alpha_fg);
363 Cvar_RegisterVariable(&cl_deathscoreboard);
365 Cvar_RegisterVariable(&crosshair_color_red);
366 Cvar_RegisterVariable(&crosshair_color_green);
367 Cvar_RegisterVariable(&crosshair_color_blue);
368 Cvar_RegisterVariable(&crosshair_color_alpha);
369 Cvar_RegisterVariable(&crosshair_size);
371 R_RegisterModule("sbar", sbar_start, sbar_shutdown, sbar_newmap);
375 //=============================================================================
377 // drawing routines are relative to the status bar location
386 void Sbar_DrawPic (int x, int y, cachepic_t *pic)
388 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, sbar_alpha_fg.value, 0);
391 void Sbar_DrawAlphaPic (int x, int y, cachepic_t *pic, float alpha)
393 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, alpha, 0);
400 Draws one solid graphics character
403 void Sbar_DrawCharacter (int x, int y, int num)
405 DrawQ_String (sbar_x + x + 4 , sbar_y + y, va("%c", num), 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0, NULL, true);
413 void Sbar_DrawString (int x, int y, char *str)
415 DrawQ_String (sbar_x + x, sbar_y + y, str, 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0, NULL, true);
423 void Sbar_DrawNum (int x, int y, int num, int digits, int color)
428 l = sprintf(str, "%i", num);
442 Sbar_DrawPic (x, y, sb_nums[color][frame]);
455 void Sbar_DrawXNum (int x, int y, int num, int digits, int lettersize, float r, float g, float b, float a, int flags)
460 l = sprintf(str, "%i", num);
465 x += (digits-l) * lettersize;
474 DrawQ_Pic (sbar_x + x, sbar_y + y, sb_nums[0][frame],lettersize,lettersize,r,g,b,a * sbar_alpha_fg.value,flags);
481 //=============================================================================
484 int Sbar_IsTeammatch()
486 // currently only nexuiz uses the team score board
487 return ((gamemode == GAME_NEXUIZ)
488 && (teamplay.integer > 0));
496 static int fragsort[MAX_SCOREBOARD];
497 static int scoreboardlines;
499 //[515]: Sbar_GetPlayer for csqc "getplayerkey" func
500 int Sbar_GetPlayer (int index)
505 if(index >= scoreboardlines)
507 index = fragsort[index];
509 if(index >= scoreboardlines)
514 static scoreboard_t teams[MAX_SCOREBOARD];
515 static int teamsort[MAX_SCOREBOARD];
516 static int teamlines;
517 void Sbar_SortFrags (void)
523 for (i=0 ; i<cl.maxclients ; i++)
525 if (cl.scores[i].name[0])
527 fragsort[scoreboardlines] = i;
532 for (i=0 ; i<scoreboardlines ; i++)
533 for (j=0 ; j<scoreboardlines-1-i ; j++)
534 if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j+1]].frags)
537 fragsort[j] = fragsort[j+1];
542 if (Sbar_IsTeammatch ())
544 // now sort players by teams.
545 for (i=0 ; i<scoreboardlines ; i++)
547 for (j=0 ; j<scoreboardlines-1-i ; j++)
549 if (cl.scores[fragsort[j]].colors < cl.scores[fragsort[j+1]].colors)
552 fragsort[j] = fragsort[j+1];
558 // calculate team scores
560 for (i=0 ; i<scoreboardlines ; i++)
562 if (color != (cl.scores[fragsort[i]].colors & 15))
564 const char* teamname;
566 color = cl.scores[fragsort[i]].colors & 15;
572 teamname = "^1Red Team";
575 teamname = "^4Blue Team";
578 teamname = "^6Pink Team";
581 teamname = "^3Yellow Team";
584 teamname = "Total Team Score";
587 strlcpy(teams[teamlines-1].name, teamname, sizeof(teams[teamlines-1].name));
589 teams[teamlines-1].frags = 0;
590 teams[teamlines-1].colors = color + 16 * color;
593 if (cl.scores[fragsort[i]].frags != -666)
595 // do not add spedcators
596 // (ugly hack for nexuiz)
597 teams[teamlines-1].frags += cl.scores[fragsort[i]].frags;
601 // now sort teams by scores.
602 for (i=0 ; i<teamlines ; i++)
604 for (i=0 ; i<teamlines ; i++)
606 for (j=0 ; j<teamlines-1-i ; j++)
608 if (teams[teamsort[j]].frags < teams[teamsort[j+1]].frags)
611 teamsort[j] = teamsort[j+1];
624 void Sbar_SoloScoreboard (void)
627 char str[80], timestr[40];
629 int minutes, seconds;
631 minutes = (int)(cl.time / 60);
632 seconds = (int)(cl.time - 60*floor(cl.time/60));
634 // monsters and secrets are now both on the top row
635 if (gamemode != GAME_NEXUIZ)
636 Sbar_DrawString(8, 4, va("Monsters:%3i /%3i Secrets :%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS], cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]));
638 // figure out the map's filename without path or extension
639 strlcpy(str, FS_FileWithoutPath(cl.worldmodel ? cl.worldmodel->name : ""), sizeof(str));
640 if (strrchr(str, '.'))
641 *(strrchr(str, '.')) = 0;
643 // append a : separator and then the full title
644 strlcat(str, ":", sizeof(str));
645 strlcat(str, cl.levelname, sizeof(str));
647 // make the time string
648 max = 38 - sprintf(timestr, " %i:%02i", minutes, seconds);
650 // if there's a newline character, terminate the string there
651 if (strchr(str, '\n'))
652 *(strchr(str, '\n')) = 0;
654 // pad with spaces to fill the allotted space and append the time
655 i = bound(0, (int)strlen(str), max);
659 strlcat(str, timestr, sizeof(str));
661 // print the line of text
662 Sbar_DrawString(8, 12, str);
666 int minutes, seconds, tens, units;
669 if (gamemode != GAME_NEXUIZ) {
670 sprintf (str,"Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
671 Sbar_DrawString (8, 4, str);
673 sprintf (str,"Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
674 Sbar_DrawString (8, 12, str);
678 minutes = (int)(cl.time / 60);
679 seconds = (int)(cl.time - 60*minutes);
681 units = seconds - 10*tens;
682 sprintf (str,"Time :%3i:%i%i", minutes, tens, units);
683 Sbar_DrawString (184, 4, str);
686 if (gamemode == GAME_NEXUIZ) {
687 l = (int) strlen (cl.worldmodel->name);
688 Sbar_DrawString (232 - l*4, 12, cl.worldmodel->name);
690 l = (int) strlen (cl.levelname);
691 Sbar_DrawString (232 - l*4, 12, cl.levelname);
701 void Sbar_DrawScoreboard (void)
703 Sbar_SoloScoreboard ();
704 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
705 //if (cl.gametype == GAME_DEATHMATCH)
707 Sbar_DeathmatchOverlay ();
710 //=============================================================================
712 // AK to make DrawInventory smaller
713 static void Sbar_DrawWeapon(int nr, float fade, int active)
715 // width = 300, height = 100
716 const int w_width = 300, w_height = 100, w_space = 10;
717 const float w_scale = 0.4;
719 DrawQ_Pic(vid_conwidth.integer - (w_width + w_space) * w_scale, (w_height + w_space) * w_scale * nr + w_space, sb_weapons[0][nr], w_width * w_scale, w_height * w_scale, (active) ? 1 : 0.6, active ? 1 : 0.6, active ? 1 : 1, fade * sbar_alpha_fg.value, DRAWFLAG_NORMAL);
720 //DrawQ_String(vid_conwidth.integer - (w_space + font_size ), (w_height + w_space) * w_scale * nr + w_space, va("%i",nr+1), 0, font_size, font_size, 1, 0, 0, fade, 0, NULL, true);
728 void Sbar_DrawInventory (void)
735 if (gamemode == GAME_ROGUE)
737 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
738 Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], sbar_alpha_bg.value);
740 Sbar_DrawAlphaPic (0, -24, rsb_invbar[1], sbar_alpha_bg.value);
743 Sbar_DrawAlphaPic (0, -24, sb_ibar, sbar_alpha_bg.value);
746 for (i=0 ; i<7 ; i++)
748 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<i) )
750 time = cl.item_gettime[i];
751 flashon = (int)(max(0, cl.time - time)*10);
754 if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i) )
760 flashon = (flashon%5) + 2;
762 Sbar_DrawAlphaPic (i*24, -16, sb_weapons[flashon][i], sbar_alpha_bg.value);
768 if (gamemode == GAME_HIPNOTIC)
770 int grenadeflashing=0;
771 for (i=0 ; i<4 ; i++)
773 if (cl.stats[STAT_ITEMS] & (1<<hipweapons[i]) )
775 time = max(0, cl.item_gettime[hipweapons[i]]);
776 flashon = (int)((cl.time - time)*10);
779 if ( cl.stats[STAT_ACTIVEWEAPON] == (1<<hipweapons[i]) )
785 flashon = (flashon%5) + 2;
787 // check grenade launcher
790 if (cl.stats[STAT_ITEMS] & HIT_PROXIMITY_GUN)
795 Sbar_DrawPic (96, -16, hsb_weapons[flashon][2]);
801 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<4))
803 if (!grenadeflashing)
804 Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
807 Sbar_DrawPic (96, -16, hsb_weapons[flashon][4]);
810 Sbar_DrawPic (176 + (i*24), -16, hsb_weapons[flashon][i]);
815 if (gamemode == GAME_ROGUE)
817 // check for powered up weapon.
818 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
820 if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i))
821 Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]);
825 for (i=0 ; i<4 ; i++)
827 sprintf (num, "%3i",cl.stats[STAT_SHELLS+i] );
829 Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[0] - '0');
831 Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[1] - '0');
833 Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0');
837 for (i=0 ; i<6 ; i++)
838 if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
840 //MED 01/04/97 changed keys
841 if (gamemode != GAME_HIPNOTIC || (i>1))
842 Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
845 //MED 01/04/97 added hipnotic items
847 if (gamemode == GAME_HIPNOTIC)
849 for (i=0 ; i<2 ; i++)
850 if (cl.stats[STAT_ITEMS] & (1<<(24+i)))
851 Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
854 if (gamemode == GAME_ROGUE)
857 for (i=0 ; i<2 ; i++)
858 if (cl.stats[STAT_ITEMS] & (1<<(29+i)))
859 Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
864 for (i=0 ; i<4 ; i++)
865 if (cl.stats[STAT_ITEMS] & (1<<(28+i)))
866 Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
870 //=============================================================================
877 void Sbar_DrawFrags (void)
887 l = min(scoreboardlines, 4);
891 for (i = 0;i < l;i++)
897 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
898 DrawQ_Fill (sbar_x + x + 10, sbar_y - 23, 28, 4, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
899 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
900 DrawQ_Fill (sbar_x + x + 10, sbar_y + 4 - 23, 28, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
904 sprintf (num, "%3i",f);
906 if (k == cl.viewentity - 1)
908 Sbar_DrawCharacter ( x + 2, -24, 16);
909 Sbar_DrawCharacter ( x + 32 - 4, -24, 17);
911 Sbar_DrawCharacter (x + 8, -24, num[0]);
912 Sbar_DrawCharacter (x + 16, -24, num[1]);
913 Sbar_DrawCharacter (x + 24, -24, num[2]);
918 //=============================================================================
926 void Sbar_DrawFace (void)
930 // PGM 01/19/97 - team color drawing
931 // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
932 if (gamemode == GAME_ROGUE && !cl.islocalgame && (teamplay.integer > 3) && (teamplay.integer < 7))
938 s = &cl.scores[cl.viewentity - 1];
940 Sbar_DrawPic (112, 0, rsb_teambord);
941 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
942 DrawQ_Fill (sbar_x + 113, vid_conheight.integer-SBAR_HEIGHT+3, 22, 9, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
943 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
944 DrawQ_Fill (sbar_x + 113, vid_conheight.integer-SBAR_HEIGHT+12, 22, 9, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
948 sprintf (num, "%3i",f);
950 if ((s->colors & 0xf0)==0)
953 Sbar_DrawCharacter(109, 3, 18 + num[0] - '0');
955 Sbar_DrawCharacter(116, 3, 18 + num[1] - '0');
957 Sbar_DrawCharacter(123, 3, 18 + num[2] - '0');
961 Sbar_DrawCharacter ( 109, 3, num[0]);
962 Sbar_DrawCharacter ( 116, 3, num[1]);
963 Sbar_DrawCharacter ( 123, 3, num[2]);
968 // PGM 01/19/97 - team color drawing
970 if ( (cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
971 Sbar_DrawPic (112, 0, sb_face_invis_invuln);
972 else if (cl.stats[STAT_ITEMS] & IT_QUAD)
973 Sbar_DrawPic (112, 0, sb_face_quad );
974 else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
975 Sbar_DrawPic (112, 0, sb_face_invis );
976 else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
977 Sbar_DrawPic (112, 0, sb_face_invuln);
980 f = cl.stats[STAT_HEALTH] / 20;
982 Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]);
986 void Sbar_ShowFPS(void)
988 float fps_x, fps_y, fps_scalex, fps_scaley, fps_height;
992 qboolean red = false;
999 static double nexttime = 0, lasttime = 0;
1000 static double framerate = 0;
1001 static int framecount = 0;
1004 if (newtime >= nexttime)
1006 framerate = framecount / (newtime - lasttime);
1008 nexttime = max(nexttime + 1, lasttime - 1);
1014 if ((red = (calc < 1.0f)))
1015 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0f / calc + 0.5));
1017 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(calc + 0.5));
1019 if (showtime.integer)
1020 strlcpy(timestring, Sys_TimeString(showtime_format.string), sizeof(timestring));
1021 if (showdate.integer)
1022 strlcpy(datestring, Sys_TimeString(showdate_format.string), sizeof(datestring));
1023 if (fpsstring[0] || timestring[0])
1027 fps_height = fps_scaley * ((fpsstring[0] != 0) + (timestring[0] != 0) + (datestring[0] != 0));
1028 //fps_y = vid_conheight.integer - sb_lines; // yes this may draw over the sbar
1029 //fps_y = bound(0, fps_y, vid_conheight.integer - fps_height);
1030 fps_y = vid_conheight.integer - fps_height;
1033 fps_x = vid_conwidth.integer - fps_scalex * strlen(fpsstring);
1034 DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(fpsstring), fps_scaley, 0, 0, 0, 0.5, 0);
1036 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 0, 0, 1, 0, NULL, true);
1038 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true);
1039 fps_y += fps_scaley;
1043 fps_x = vid_conwidth.integer - fps_scalex * strlen(timestring);
1044 DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(timestring), fps_scaley, 0, 0, 0, 0.5, 0);
1045 DrawQ_String(fps_x, fps_y, timestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true);
1046 fps_y += fps_scaley;
1050 fps_x = vid_conwidth.integer - fps_scalex * strlen(datestring);
1051 DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(datestring), fps_scaley, 0, 0, 0, 0.5, 0);
1052 DrawQ_String(fps_x, fps_y, datestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true);
1053 fps_y += fps_scaley;
1058 void Sbar_DrawGauge(float x, float y, cachepic_t *pic, float width, float height, float rangey, float rangeheight, float c1, float c2, float c1r, float c1g, float c1b, float c1a, float c2r, float c2g, float c2b, float c2a, float c3r, float c3g, float c3b, float c3a, int drawflags)
1061 c2 = bound(0, c2, 1);
1062 c1 = bound(0, c1, 1 - c2);
1064 r[1] = rangey + rangeheight * (c2 + c1);
1065 r[2] = rangey + rangeheight * (c2);
1069 DrawQ_SuperPic(x, y + r[0], pic, width, (r[1] - r[0]), 0,(r[0] / height), c3r,c3g,c3b,c3a, 1,(r[0] / height), c3r,c3g,c3b,c3a, 0,(r[1] / height), c3r,c3g,c3b,c3a, 1,(r[1] / height), c3r,c3g,c3b,c3a, drawflags);
1071 DrawQ_SuperPic(x, y + r[1], pic, width, (r[2] - r[1]), 0,(r[1] / height), c1r,c1g,c1b,c1a, 1,(r[1] / height), c1r,c1g,c1b,c1a, 0,(r[2] / height), c1r,c1g,c1b,c1a, 1,(r[2] / height), c1r,c1g,c1b,c1a, drawflags);
1073 DrawQ_SuperPic(x, y + r[2], pic, width, (r[3] - r[2]), 0,(r[2] / height), c2r,c2g,c2b,c2a, 1,(r[2] / height), c2r,c2g,c2b,c2a, 0,(r[3] / height), c2r,c2g,c2b,c2a, 1,(r[3] / height), c2r,c2g,c2b,c2a, drawflags);
1075 DrawQ_SuperPic(x, y + r[3], pic, width, (r[4] - r[3]), 0,(r[3] / height), c3r,c3g,c3b,c3a, 1,(r[3] / height), c3r,c3g,c3b,c3a, 0,(r[4] / height), c3r,c3g,c3b,c3a, 1,(r[4] / height), c3r,c3g,c3b,c3a, drawflags);
1083 extern float v_dmg_time, v_dmg_roll, v_dmg_pitch;
1084 extern cvar_t v_kicktime;
1085 void Sbar_Draw (void)
1089 if(cl.csqc_vidvars.drawenginesbar) //[515]: csqc drawsbar
1091 if (cl.intermission == 1)
1093 Sbar_IntermissionOverlay();
1096 else if (cl.intermission == 2)
1098 Sbar_FinaleOverlay();
1102 if (gamemode == GAME_NETHERWORLD)
1105 else if (gamemode == GAME_SOM)
1107 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1108 Sbar_DrawScoreboard ();
1111 // this is the top left of the sbar area
1113 sbar_y = vid_conheight.integer - 24*3;
1116 if (cl.stats[STAT_ARMOR])
1118 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1119 Sbar_DrawPic(0, 0, somsb_armor[2]);
1120 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1121 Sbar_DrawPic(0, 0, somsb_armor[1]);
1122 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1123 Sbar_DrawPic(0, 0, somsb_armor[0]);
1124 Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1128 Sbar_DrawPic(0, 24, somsb_health);
1129 Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1132 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1133 Sbar_DrawPic(0, 48, somsb_ammo[0]);
1134 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1135 Sbar_DrawPic(0, 48, somsb_ammo[1]);
1136 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1137 Sbar_DrawPic(0, 48, somsb_ammo[2]);
1138 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1139 Sbar_DrawPic(0, 48, somsb_ammo[3]);
1140 Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
1141 if (cl.stats[STAT_SHELLS])
1142 Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
1145 else if (gamemode == GAME_NEXUIZ)
1147 sbar_y = vid_conheight.integer - 47;
1148 sbar_x = (vid_conwidth.integer - 640)/2;
1150 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1152 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1153 Sbar_DrawScoreboard ();
1159 int redflag, blueflag;
1161 // calculate intensity to draw weapons bar at
1162 fade = 3 - 2 * (cl.time - cl.weapontime);
1165 fade = min(fade, 1);
1166 for (i = 0; i < 8;i++)
1167 if (cl.stats[STAT_ITEMS] & (1 << i))
1168 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1170 if((cl.stats[STAT_ITEMS] & (1<<12)))
1171 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1174 //if (!cl.islocalgame)
1175 // Sbar_DrawFrags ();
1178 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1180 Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1183 redflag = ((cl.stats[STAT_ITEMS]>>15) & 3);
1184 blueflag = ((cl.stats[STAT_ITEMS]>>17) & 3);
1185 if (redflag == 3 && blueflag == 3)
1187 // The Impossible Combination[tm]
1188 // Can only happen in Key Hunt mode...
1189 Sbar_DrawPic (10 - sbar_x, -179, sb_items[14]);
1194 Sbar_DrawPic (10 - sbar_x, -109, sb_items[redflag+10]);
1196 Sbar_DrawPic (10 - sbar_x, -169, sb_items[blueflag+14]);
1200 Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1203 if(cl.stats[STAT_HEALTH] > 100)
1204 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1205 else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1206 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1208 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1210 // AK dont draw ammo for the laser
1211 if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1213 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1214 Sbar_DrawPic (519, 0, sb_ammo[0]);
1215 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1216 Sbar_DrawPic (519, 0, sb_ammo[1]);
1217 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1218 Sbar_DrawPic (519, 0, sb_ammo[2]);
1219 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1220 Sbar_DrawPic (519, 0, sb_ammo[3]);
1222 if(cl.stats[STAT_AMMO] <= 10)
1223 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1225 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1230 DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1233 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1234 // Sbar_MiniDeathmatchOverlay (0, 17);
1236 else if (gamemode == GAME_ZYMOTIC)
1239 float scale = 64.0f / 256.0f;
1240 float kickoffset[3];
1241 VectorClear(kickoffset);
1244 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1245 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1247 sbar_x = (int)((vid_conwidth.integer - 256 * scale)/2 + kickoffset[0]);
1248 sbar_y = (int)((vid_conheight.integer - 256 * scale)/2 + kickoffset[1]);
1249 // left1 16, 48 : 126 -66
1250 // left2 16, 128 : 196 -66
1251 // right 176, 48 : 196 -136
1252 Sbar_DrawGauge(sbar_x + 16 * scale, sbar_y + 48 * scale, zymsb_crosshair_left1, 64*scale, 80*scale, 78*scale, -66*scale, cl.stats[STAT_AMMO] * (1.0 / 200.0), cl.stats[STAT_SHELLS] * (1.0 / 200.0), 0.8f,0.8f,0.0f,1.0f, 0.8f,0.5f,0.0f,1.0f, 0.3f,0.3f,0.3f,1.0f, DRAWFLAG_NORMAL);
1253 Sbar_DrawGauge(sbar_x + 16 * scale, sbar_y + 128 * scale, zymsb_crosshair_left2, 64*scale, 80*scale, 68*scale, -66*scale, cl.stats[STAT_NAILS] * (1.0 / 200.0), cl.stats[STAT_ROCKETS] * (1.0 / 200.0), 0.8f,0.8f,0.0f,1.0f, 0.8f,0.5f,0.0f,1.0f, 0.3f,0.3f,0.3f,1.0f, DRAWFLAG_NORMAL);
1254 Sbar_DrawGauge(sbar_x + 176 * scale, sbar_y + 48 * scale, zymsb_crosshair_right, 64*scale, 160*scale, 148*scale, -136*scale, cl.stats[STAT_ARMOR] * (1.0 / 300.0), cl.stats[STAT_HEALTH] * (1.0 / 300.0), 0.0f,0.5f,1.0f,1.0f, 1.0f,0.0f,0.0f,1.0f, 0.3f,0.3f,0.3f,1.0f, DRAWFLAG_NORMAL);
1255 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1257 float scale = 128.0f / 256.0f;
1258 float healthstart, healthheight, healthstarttc, healthendtc;
1259 float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1260 float ammostart, ammoheight, ammostarttc, ammoendtc;
1261 float clipstart, clipheight, clipstarttc, clipendtc;
1262 float kickoffset[3], offset;
1263 VectorClear(kickoffset);
1266 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1267 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1269 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1270 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1271 offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1272 DrawQ_SuperPic(sbar_x + 120 * scale, sbar_y + ( 88 - offset) * scale, zymsb_crosshair_line, 16 * scale, 36 * scale, 0,0, 1,1,1,1, 1,0, 1,1,1,1, 0,1, 1,1,1,1, 1,1, 1,1,1,1, 0);
1273 DrawQ_SuperPic(sbar_x + (132 + offset) * scale, sbar_y + 120 * scale, zymsb_crosshair_line, 36 * scale, 16 * scale, 0,1, 1,1,1,1, 0,0, 1,1,1,1, 1,1, 1,1,1,1, 1,0, 1,1,1,1, 0);
1274 DrawQ_SuperPic(sbar_x + 120 * scale, sbar_y + (132 + offset) * scale, zymsb_crosshair_line, 16 * scale, 36 * scale, 1,1, 1,1,1,1, 0,1, 1,1,1,1, 1,0, 1,1,1,1, 0,0, 1,1,1,1, 0);
1275 DrawQ_SuperPic(sbar_x + ( 88 - offset) * scale, sbar_y + 120 * scale, zymsb_crosshair_line, 36 * scale, 16 * scale, 1,0, 1,1,1,1, 1,1, 1,1,1,1, 0,0, 1,1,1,1, 0,1, 1,1,1,1, 0);
1276 healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1277 shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1278 healthstart = 204 - healthheight;
1279 shieldstart = healthstart - shieldheight;
1280 healthstarttc = healthstart * (1.0f / 256.0f);
1281 healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1282 shieldstarttc = shieldstart * (1.0f / 256.0f);
1283 shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1284 ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1285 ammostart = 114 - ammoheight;
1286 ammostarttc = ammostart * (1.0f / 256.0f);
1287 ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1288 clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1289 clipstart = 190 - clipheight;
1290 clipstarttc = clipstart * (1.0f / 256.0f);
1291 clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1292 if (healthheight > 0) DrawQ_SuperPic(sbar_x + 0 * scale, sbar_y + healthstart * scale, zymsb_crosshair_health, 256 * scale, healthheight * scale, 0,healthstarttc, 1.0f,0.0f,0.0f,1.0f, 1,healthstarttc, 1.0f,0.0f,0.0f,1.0f, 0,healthendtc, 1.0f,0.0f,0.0f,1.0f, 1,healthendtc, 1.0f,0.0f,0.0f,1.0f, DRAWFLAG_NORMAL);
1293 if (shieldheight > 0) DrawQ_SuperPic(sbar_x + 0 * scale, sbar_y + shieldstart * scale, zymsb_crosshair_health, 256 * scale, shieldheight * scale, 0,shieldstarttc, 0.0f,0.5f,1.0f,1.0f, 1,shieldstarttc, 0.0f,0.5f,1.0f,1.0f, 0,shieldendtc, 0.0f,0.5f,1.0f,1.0f, 1,shieldendtc, 0.0f,0.5f,1.0f,1.0f, DRAWFLAG_NORMAL);
1294 if (ammoheight > 0) DrawQ_SuperPic(sbar_x + 0 * scale, sbar_y + ammostart * scale, zymsb_crosshair_ammo, 256 * scale, ammoheight * scale, 0,ammostarttc, 0.8f,0.8f,0.0f,1.0f, 1,ammostarttc, 0.8f,0.8f,0.0f,1.0f, 0,ammoendtc, 0.8f,0.8f,0.0f,1.0f, 1,ammoendtc, 0.8f,0.8f,0.0f,1.0f, DRAWFLAG_NORMAL);
1295 if (clipheight > 0) DrawQ_SuperPic(sbar_x + 0 * scale, sbar_y + clipstart * scale, zymsb_crosshair_clip, 256 * scale, clipheight * scale, 0,clipstarttc, 1.0f,1.0f,0.0f,1.0f, 1,clipstarttc, 1.0f,1.0f,0.0f,1.0f, 0,clipendtc, 1.0f,1.0f,0.0f,1.0f, 1,clipendtc, 1.0f,1.0f,0.0f,1.0f, DRAWFLAG_NORMAL);
1296 DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1297 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1300 else // Quake and others
1302 sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1303 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1304 //if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1305 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1308 sbar_x = (vid_conwidth.integer - 320)/2;
1312 if (gamemode != GAME_GOODVSBAD2)
1313 Sbar_DrawInventory ();
1314 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1318 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1320 if (gamemode != GAME_GOODVSBAD2)
1321 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1322 Sbar_DrawScoreboard ();
1326 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1328 // keys (hipnotic only)
1329 //MED 01/04/97 moved keys here so they would not be overwritten
1330 if (gamemode == GAME_HIPNOTIC)
1332 if (cl.stats[STAT_ITEMS] & IT_KEY1)
1333 Sbar_DrawPic (209, 3, sb_items[0]);
1334 if (cl.stats[STAT_ITEMS] & IT_KEY2)
1335 Sbar_DrawPic (209, 12, sb_items[1]);
1338 if (gamemode != GAME_GOODVSBAD2)
1340 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1342 Sbar_DrawNum (24, 0, 666, 3, 1);
1343 Sbar_DrawPic (0, 0, sb_disc);
1347 if (gamemode == GAME_ROGUE)
1349 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1350 if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1351 Sbar_DrawPic (0, 0, sb_armor[2]);
1352 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1353 Sbar_DrawPic (0, 0, sb_armor[1]);
1354 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1355 Sbar_DrawPic (0, 0, sb_armor[0]);
1359 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1360 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1361 Sbar_DrawPic (0, 0, sb_armor[2]);
1362 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1363 Sbar_DrawPic (0, 0, sb_armor[1]);
1364 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1365 Sbar_DrawPic (0, 0, sb_armor[0]);
1374 Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1377 if (gamemode == GAME_ROGUE)
1379 if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1380 Sbar_DrawPic (224, 0, sb_ammo[0]);
1381 else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1382 Sbar_DrawPic (224, 0, sb_ammo[1]);
1383 else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1384 Sbar_DrawPic (224, 0, sb_ammo[2]);
1385 else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1386 Sbar_DrawPic (224, 0, sb_ammo[3]);
1387 else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1388 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1389 else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1390 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1391 else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1392 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1396 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1397 Sbar_DrawPic (224, 0, sb_ammo[0]);
1398 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1399 Sbar_DrawPic (224, 0, sb_ammo[1]);
1400 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1401 Sbar_DrawPic (224, 0, sb_ammo[2]);
1402 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1403 Sbar_DrawPic (224, 0, sb_ammo[3]);
1406 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1410 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1411 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1412 if (!cl.islocalgame && vid_conwidth.integer > 320)
1414 if (gamemode == GAME_TRANSFUSION)
1415 Sbar_MiniDeathmatchOverlay (0, 0);
1417 Sbar_MiniDeathmatchOverlay (324, vid_conheight.integer - sb_lines);
1424 if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && crosshair.integer <= NUMCROSSHAIRS && !cl.intermission && !r_letterbox.value && (pic = r_crosshairs[crosshair.integer]))
1425 DrawQ_Pic((vid_conwidth.integer - pic->width * crosshair_size.value) * 0.5f, (vid_conheight.integer - pic->height * crosshair_size.value) * 0.5f, pic, pic->width * crosshair_size.value, pic->height * crosshair_size.value, crosshair_color_red.value, crosshair_color_green.value, crosshair_color_blue.value, crosshair_color_alpha.value, 0);
1427 if (cl_prydoncursor.integer)
1428 DrawQ_Pic((cl.cmd.cursor_screen[0] + 1) * 0.5 * vid_conwidth.integer, (cl.cmd.cursor_screen[1] + 1) * 0.5 * vid_conheight.integer, Draw_CachePic(va("gfx/prydoncursor%03i", cl_prydoncursor.integer), true), 0, 0, 1, 1, 1, 1, 0);
1431 //=============================================================================
1435 Sbar_DeathmatchOverlay
1439 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1443 minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : cl.time - s->qw_entertime) / 60.0);
1444 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1446 if (s->qw_spectator)
1448 if (s->qw_ping || s->qw_packetloss)
1449 DrawQ_String(x, y, va("%4i %3i %4i spectator %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes, (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1451 DrawQ_String(x, y, va(" %4i spectator %c%s", minutes, (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1455 // draw colors behind score
1456 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1457 DrawQ_Fill(x + 14*8, y+1, 40, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
1458 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1459 DrawQ_Fill(x + 14*8, y+4, 40, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
1461 //DrawQ_String(x, y, va("%c%4i %s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, true);
1462 if (s->qw_ping || s->qw_packetloss)
1463 DrawQ_String(x, y, va("%4i %3i %4i %5i %-4s %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1465 DrawQ_String(x, y, va(" %4i %5i %-4s %c%s", minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1470 if (s->qw_spectator)
1472 if (s->qw_ping || s->qw_packetloss)
1473 DrawQ_String(x, y, va("%4i %3i spect %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1475 DrawQ_String(x, y, va(" spect %c%s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1479 // draw colors behind score
1480 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1481 DrawQ_Fill(x + 9*8, y+1, 40, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
1482 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1483 DrawQ_Fill(x + 9*8, y+4, 40, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
1485 //DrawQ_String(x, y, va("%c%4i %s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, true);
1486 if (s->qw_ping || s->qw_packetloss)
1487 DrawQ_String(x, y, va("%4i %3i %5i %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), (int) s->frags, (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1489 DrawQ_String(x, y, va(" %5i %c%s", (int) s->frags, (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1495 void Sbar_DeathmatchOverlay (void)
1499 // request new ping times every two second
1500 if (cl.last_ping_request < realtime - 2 && cls.netcon)
1502 cl.last_ping_request = realtime;
1503 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1505 MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
1506 MSG_WriteString(&cls.netcon->message, "pings");
1508 else if (cls.protocol == PROTOCOL_QUAKE || cls.protocol == PROTOCOL_QUAKEDP || cls.protocol == PROTOCOL_NEHAHRAMOVIE || cls.protocol == PROTOCOL_DARKPLACES1 || cls.protocol == PROTOCOL_DARKPLACES2 || cls.protocol == PROTOCOL_DARKPLACES3 || cls.protocol == PROTOCOL_DARKPLACES4 || cls.protocol == PROTOCOL_DARKPLACES5 || cls.protocol == PROTOCOL_DARKPLACES6 || cls.protocol == PROTOCOL_DARKPLACES7)
1510 // these servers usually lack the pings command and so a less efficient "ping" command must be sent, which on modern DP servers will also reply with a pingplreport command after the ping listing
1511 static int ping_anyway_counter = 0;
1512 if(cl.parsingtextexpectingpingforscores == 1)
1514 Con_DPrintf("want to send ping, but still waiting for other reply\n");
1515 if(++ping_anyway_counter >= 5)
1516 cl.parsingtextexpectingpingforscores = 0;
1518 if(cl.parsingtextexpectingpingforscores != 1)
1520 ping_anyway_counter = 0;
1521 cl.parsingtextexpectingpingforscores = 1; // hide the output of the next ping report
1522 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1523 MSG_WriteString(&cls.netcon->message, "ping");
1528 // newer server definitely has pings command, so use it for more efficiency
1529 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1530 MSG_WriteString(&cls.netcon->message, "pings");
1534 DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1540 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1542 x = (vid_conwidth.integer - (26 + 15) * 8) / 2; // 26 characters until name, then we assume 15 character names (they can be longer but usually aren't)
1543 DrawQ_String(x, y, va("ping pl%% time frags team name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1547 x = (vid_conwidth.integer - (16 + 15) * 8) / 2; // 16 characters until name, then we assume 15 character names (they can be longer but usually aren't)
1548 DrawQ_String(x, y, va("ping pl%% frags name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1552 if (Sbar_IsTeammatch ())
1554 // show team scores first
1555 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1556 y += (int)Sbar_PrintScoreboardItem((teams + teamsort[i]), x, y);
1560 for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1561 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1566 Sbar_DeathmatchOverlay
1570 void Sbar_MiniDeathmatchOverlay (int x, int y)
1574 // decide where to print
1575 if (gamemode == GAME_TRANSFUSION)
1576 numlines = (vid_conwidth.integer - x + 127) / 128;
1578 numlines = (vid_conheight.integer - y + 7) / 8;
1580 // give up if there isn't room
1581 if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1588 for (i = 0; i < scoreboardlines; i++)
1589 if (fragsort[i] == cl.playerentity - 1)
1594 i = min(i, scoreboardlines - numlines);
1597 if (gamemode == GAME_TRANSFUSION)
1599 for (;i < scoreboardlines && x < vid_conwidth.integer;i++)
1600 x += 128 + (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1604 for (;i < scoreboardlines && y < vid_conheight.integer;i++)
1605 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1611 Sbar_IntermissionOverlay
1615 void Sbar_IntermissionOverlay (void)
1620 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1621 //if (cl.gametype == GAME_DEATHMATCH)
1622 if (!cl.islocalgame)
1624 Sbar_DeathmatchOverlay ();
1628 sbar_x = (vid_conwidth.integer - 320) >> 1;
1629 sbar_y = (vid_conheight.integer - 200) >> 1;
1631 DrawQ_Pic (sbar_x + 64, sbar_y + 24, sb_complete, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1632 DrawQ_Pic (sbar_x + 0, sbar_y + 56, sb_inter, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1635 dig = (int)cl.completed_time / 60;
1636 Sbar_DrawNum (160, 64, dig, 3, 0);
1637 num = (int)cl.completed_time - dig*60;
1638 if (gamemode != GAME_NEXUIZ)
1639 Sbar_DrawPic (234,64,sb_colon);
1640 Sbar_DrawPic (246,64,sb_nums[0][num/10]);
1641 Sbar_DrawPic (266,64,sb_nums[0][num%10]);
1643 Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
1644 if (gamemode != GAME_NEXUIZ)
1645 Sbar_DrawPic (232, 104, sb_slash);
1646 Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1648 Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1649 if (gamemode != GAME_NEXUIZ)
1650 Sbar_DrawPic (232, 144, sb_slash);
1651 Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1662 void Sbar_FinaleOverlay (void)
1664 DrawQ_Pic((vid_conwidth.integer - sb_finale->width)/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);