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
27 #define STAT_MINUS 10 // num frame for '-' stats digit
28 cachepic_t *sb_nums[2][11];
29 cachepic_t *sb_colon, *sb_slash;
32 cachepic_t *sb_scorebar;
33 // AK only used by NEX
34 cachepic_t *sb_sbar_minimal;
35 cachepic_t *sb_sbar_overlay;
37 // AK changed the bound to 9
38 cachepic_t *sb_weapons[7][9]; // 0 is active, 1 is owned, 2-5 are flashes
39 cachepic_t *sb_ammo[4];
40 cachepic_t *sb_sigil[4];
41 cachepic_t *sb_armor[3];
42 cachepic_t *sb_items[32];
44 // 0-4 are based on health (in 20 increments)
45 // 0 is static, 1 is temporary animation
46 cachepic_t *sb_faces[5][2];
47 cachepic_t *sb_health; // GAME_NEXUIZ
49 cachepic_t *sb_face_invis;
50 cachepic_t *sb_face_quad;
51 cachepic_t *sb_face_invuln;
52 cachepic_t *sb_face_invis_invuln;
54 qboolean sb_showscores;
56 int sb_lines; // scan lines to draw
58 cachepic_t *rsb_invbar[2];
59 cachepic_t *rsb_weapons[5];
60 cachepic_t *rsb_items[2];
61 cachepic_t *rsb_ammo[3];
62 cachepic_t *rsb_teambord; // PGM 01/19/97 - team color border
64 //MED 01/04/97 added two more weapons + 3 alternates for grenade launcher
65 cachepic_t *hsb_weapons[7][5]; // 0 is active, 1 is owned, 2-5 are flashes
66 //MED 01/04/97 added array to simplify weapon parsing
67 int hipweapons[4] = {HIT_LASER_CANNON_BIT,HIT_MJOLNIR_BIT,4,HIT_PROXIMITY_GUN_BIT};
68 //MED 01/04/97 added hipnotic items array
69 cachepic_t *hsb_items[2];
72 cachepic_t *somsb_health;
73 cachepic_t *somsb_ammo[4];
74 cachepic_t *somsb_armor[3];
76 cachepic_t *zymsb_crosshair_center;
77 cachepic_t *zymsb_crosshair_line;
78 cachepic_t *zymsb_crosshair_health;
79 cachepic_t *zymsb_crosshair_ammo;
80 cachepic_t *zymsb_crosshair_clip;
81 cachepic_t *zymsb_crosshair_background;
82 cachepic_t *zymsb_crosshair_left1;
83 cachepic_t *zymsb_crosshair_left2;
84 cachepic_t *zymsb_crosshair_right;
86 cachepic_t *sb_ranking;
87 cachepic_t *sb_complete;
89 cachepic_t *sb_finale;
91 cvar_t showfps = {CVAR_SAVE, "showfps", "0", "shows your rendered fps (frames per second)"};
92 cvar_t showsound = {CVAR_SAVE, "showsound", "0", "shows number of active sound sources, sound latency, and other statistics"};
93 cvar_t showspeed = {CVAR_SAVE, "showspeed", "0", "shows your current speed (qu per second); number selects unit: 1 = qu/s, 2 = m/s, 3 = km/h, 4 = mph, 5 = knots"};
94 cvar_t showtopspeed = {CVAR_SAVE, "showtopspeed", "0", "shows your top speed (kept on screen for max 3 seconds); value -1 takes over the unit from showspeed, otherwise it's an unit number just like in showspeed"};
95 cvar_t showtime = {CVAR_SAVE, "showtime", "0", "shows current time of day (useful on screenshots)"};
96 cvar_t showtime_format = {CVAR_SAVE, "showtime_format", "%H:%M:%S", "format string for time of day"};
97 cvar_t showdate = {CVAR_SAVE, "showdate", "0", "shows current date (useful on screenshots)"};
98 cvar_t showdate_format = {CVAR_SAVE, "showdate_format", "%Y-%m-%d", "format string for date"};
99 cvar_t sbar_alpha_bg = {CVAR_SAVE, "sbar_alpha_bg", "0.4", "opacity value of the statusbar background image"};
100 cvar_t sbar_alpha_fg = {CVAR_SAVE, "sbar_alpha_fg", "1", "opacity value of the statusbar weapon/item icons and numbers"};
101 cvar_t sbar_hudselector = {CVAR_SAVE, "sbar_hudselector", "0", "selects which of the builtin hud layouts to use (meaning is somewhat dependent on gamemode, so nexuiz has a very different set of hud layouts than quake for example)"};
102 cvar_t sbar_scorerank = {CVAR_SAVE, "sbar_scorerank", "1", "shows an overlay for your score (or team score) and rank in the scoreboard"};
103 cvar_t sbar_gametime = {CVAR_SAVE, "sbar_gametime", "1", "shows an overlay for the time left in the current match/level (or current game time if there is no timelimit set)"};
104 cvar_t sbar_miniscoreboard_size = {CVAR_SAVE, "sbar_miniscoreboard_size", "-1", "sets the size of the mini deathmatch overlay in items, or disables it when set to 0, or sets it to a sane default when set to -1"};
105 cvar_t sbar_flagstatus_right = {CVAR_SAVE, "sbar_flagstatus_right", "0", "moves Nexuiz flag status icons to the right"};
106 cvar_t sbar_flagstatus_pos = {CVAR_SAVE, "sbar_flagstatus_pos", "115", "pixel position of the Nexuiz flag status icons, from the bottom"};
107 cvar_t sbar_info_pos = {CVAR_SAVE, "sbar_info_pos", "0", "pixel position of the info strings (such as showfps), from the bottom"};
109 cvar_t cl_deathscoreboard = {0, "cl_deathscoreboard", "1", "shows scoreboard (+showscores) while dead"};
111 cvar_t crosshair_color_red = {CVAR_SAVE, "crosshair_color_red", "1", "customizable crosshair color"};
112 cvar_t crosshair_color_green = {CVAR_SAVE, "crosshair_color_green", "0", "customizable crosshair color"};
113 cvar_t crosshair_color_blue = {CVAR_SAVE, "crosshair_color_blue", "0", "customizable crosshair color"};
114 cvar_t crosshair_color_alpha = {CVAR_SAVE, "crosshair_color_alpha", "1", "how opaque the crosshair should be"};
115 cvar_t crosshair_size = {CVAR_SAVE, "crosshair_size", "1", "adjusts size of the crosshair on the screen"};
117 void Sbar_MiniDeathmatchOverlay (int x, int y);
118 void Sbar_DeathmatchOverlay (void);
119 void Sbar_IntermissionOverlay (void);
120 void Sbar_FinaleOverlay (void);
122 void CL_VM_UpdateShowingScoresState (int showingscores);
132 void Sbar_ShowScores (void)
136 sb_showscores = true;
137 CL_VM_UpdateShowingScoresState(sb_showscores);
147 void Sbar_DontShowScores (void)
149 sb_showscores = false;
150 CL_VM_UpdateShowingScoresState(sb_showscores);
153 void sbar_start(void)
157 if (gamemode == GAME_DELUXEQUAKE)
160 else if (gamemode == GAME_SOM)
162 sb_disc = Draw_CachePic ("gfx/disc");
164 for (i = 0;i < 10;i++)
165 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i));
167 somsb_health = Draw_CachePic ("gfx/hud_health");
168 somsb_ammo[0] = Draw_CachePic ("gfx/sb_shells");
169 somsb_ammo[1] = Draw_CachePic ("gfx/sb_nails");
170 somsb_ammo[2] = Draw_CachePic ("gfx/sb_rocket");
171 somsb_ammo[3] = Draw_CachePic ("gfx/sb_cells");
172 somsb_armor[0] = Draw_CachePic ("gfx/sb_armor1");
173 somsb_armor[1] = Draw_CachePic ("gfx/sb_armor2");
174 somsb_armor[2] = Draw_CachePic ("gfx/sb_armor3");
176 else if (gamemode == GAME_NEXUIZ)
178 for (i = 0;i < 10;i++)
179 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i));
180 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus");
181 sb_colon = Draw_CachePic ("gfx/num_colon");
183 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells");
184 sb_ammo[1] = Draw_CachePic ("gfx/sb_bullets");
185 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket");
186 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells");
188 sb_armor[0] = Draw_CachePic ("gfx/sb_armor");
192 sb_health = Draw_CachePic ("gfx/sb_health");
194 sb_items[2] = Draw_CachePic ("gfx/sb_slowmo");
195 sb_items[3] = Draw_CachePic ("gfx/sb_invinc");
196 sb_items[4] = Draw_CachePic ("gfx/sb_energy");
197 sb_items[5] = Draw_CachePic ("gfx/sb_str");
199 sb_items[11] = Draw_CachePic ("gfx/sb_flag_red_taken");
200 sb_items[12] = Draw_CachePic ("gfx/sb_flag_red_lost");
201 sb_items[13] = Draw_CachePic ("gfx/sb_flag_red_carrying");
202 sb_items[14] = Draw_CachePic ("gfx/sb_key_carrying");
203 sb_items[15] = Draw_CachePic ("gfx/sb_flag_blue_taken");
204 sb_items[16] = Draw_CachePic ("gfx/sb_flag_blue_lost");
205 sb_items[17] = Draw_CachePic ("gfx/sb_flag_blue_carrying");
207 sb_sbar = Draw_CachePic ("gfx/sbar");
208 sb_sbar_minimal = Draw_CachePic ("gfx/sbar_minimal");
209 sb_sbar_overlay = Draw_CachePic ("gfx/sbar_overlay");
211 for(i = 0; i < 9;i++)
212 sb_weapons[0][i] = Draw_CachePic (va("gfx/inv_weapon%i",i));
214 else if (gamemode == GAME_ZYMOTIC)
216 zymsb_crosshair_center = Draw_CachePic ("gfx/hud/crosshair_center");
217 zymsb_crosshair_line = Draw_CachePic ("gfx/hud/crosshair_line");
218 zymsb_crosshair_health = Draw_CachePic ("gfx/hud/crosshair_health");
219 zymsb_crosshair_clip = Draw_CachePic ("gfx/hud/crosshair_clip");
220 zymsb_crosshair_ammo = Draw_CachePic ("gfx/hud/crosshair_ammo");
221 zymsb_crosshair_background = Draw_CachePic ("gfx/hud/crosshair_background");
222 zymsb_crosshair_left1 = Draw_CachePic ("gfx/hud/crosshair_left1");
223 zymsb_crosshair_left2 = Draw_CachePic ("gfx/hud/crosshair_left2");
224 zymsb_crosshair_right = Draw_CachePic ("gfx/hud/crosshair_right");
228 sb_disc = Draw_CachePic ("gfx/disc");
230 for (i = 0;i < 10;i++)
232 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i));
233 sb_nums[1][i] = Draw_CachePic (va("gfx/anum_%i",i));
236 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus");
237 sb_nums[1][10] = Draw_CachePic ("gfx/anum_minus");
239 sb_colon = Draw_CachePic ("gfx/num_colon");
240 sb_slash = Draw_CachePic ("gfx/num_slash");
242 sb_weapons[0][0] = Draw_CachePic ("gfx/inv_shotgun");
243 sb_weapons[0][1] = Draw_CachePic ("gfx/inv_sshotgun");
244 sb_weapons[0][2] = Draw_CachePic ("gfx/inv_nailgun");
245 sb_weapons[0][3] = Draw_CachePic ("gfx/inv_snailgun");
246 sb_weapons[0][4] = Draw_CachePic ("gfx/inv_rlaunch");
247 sb_weapons[0][5] = Draw_CachePic ("gfx/inv_srlaunch");
248 sb_weapons[0][6] = Draw_CachePic ("gfx/inv_lightng");
250 sb_weapons[1][0] = Draw_CachePic ("gfx/inv2_shotgun");
251 sb_weapons[1][1] = Draw_CachePic ("gfx/inv2_sshotgun");
252 sb_weapons[1][2] = Draw_CachePic ("gfx/inv2_nailgun");
253 sb_weapons[1][3] = Draw_CachePic ("gfx/inv2_snailgun");
254 sb_weapons[1][4] = Draw_CachePic ("gfx/inv2_rlaunch");
255 sb_weapons[1][5] = Draw_CachePic ("gfx/inv2_srlaunch");
256 sb_weapons[1][6] = Draw_CachePic ("gfx/inv2_lightng");
258 for (i = 0;i < 5;i++)
260 sb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_shotgun",i+1));
261 sb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_sshotgun",i+1));
262 sb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_nailgun",i+1));
263 sb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_snailgun",i+1));
264 sb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_rlaunch",i+1));
265 sb_weapons[2+i][5] = Draw_CachePic (va("gfx/inva%i_srlaunch",i+1));
266 sb_weapons[2+i][6] = Draw_CachePic (va("gfx/inva%i_lightng",i+1));
269 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells");
270 sb_ammo[1] = Draw_CachePic ("gfx/sb_nails");
271 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket");
272 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells");
274 sb_armor[0] = Draw_CachePic ("gfx/sb_armor1");
275 sb_armor[1] = Draw_CachePic ("gfx/sb_armor2");
276 sb_armor[2] = Draw_CachePic ("gfx/sb_armor3");
278 sb_items[0] = Draw_CachePic ("gfx/sb_key1");
279 sb_items[1] = Draw_CachePic ("gfx/sb_key2");
280 sb_items[2] = Draw_CachePic ("gfx/sb_invis");
281 sb_items[3] = Draw_CachePic ("gfx/sb_invuln");
282 sb_items[4] = Draw_CachePic ("gfx/sb_suit");
283 sb_items[5] = Draw_CachePic ("gfx/sb_quad");
285 sb_sigil[0] = Draw_CachePic ("gfx/sb_sigil1");
286 sb_sigil[1] = Draw_CachePic ("gfx/sb_sigil2");
287 sb_sigil[2] = Draw_CachePic ("gfx/sb_sigil3");
288 sb_sigil[3] = Draw_CachePic ("gfx/sb_sigil4");
290 sb_faces[4][0] = Draw_CachePic ("gfx/face1");
291 sb_faces[4][1] = Draw_CachePic ("gfx/face_p1");
292 sb_faces[3][0] = Draw_CachePic ("gfx/face2");
293 sb_faces[3][1] = Draw_CachePic ("gfx/face_p2");
294 sb_faces[2][0] = Draw_CachePic ("gfx/face3");
295 sb_faces[2][1] = Draw_CachePic ("gfx/face_p3");
296 sb_faces[1][0] = Draw_CachePic ("gfx/face4");
297 sb_faces[1][1] = Draw_CachePic ("gfx/face_p4");
298 sb_faces[0][0] = Draw_CachePic ("gfx/face5");
299 sb_faces[0][1] = Draw_CachePic ("gfx/face_p5");
301 sb_face_invis = Draw_CachePic ("gfx/face_invis");
302 sb_face_invuln = Draw_CachePic ("gfx/face_invul2");
303 sb_face_invis_invuln = Draw_CachePic ("gfx/face_inv2");
304 sb_face_quad = Draw_CachePic ("gfx/face_quad");
306 sb_sbar = Draw_CachePic ("gfx/sbar");
307 sb_ibar = Draw_CachePic ("gfx/ibar");
308 sb_scorebar = Draw_CachePic ("gfx/scorebar");
310 //MED 01/04/97 added new hipnotic weapons
311 if (gamemode == GAME_HIPNOTIC)
313 hsb_weapons[0][0] = Draw_CachePic ("gfx/inv_laser");
314 hsb_weapons[0][1] = Draw_CachePic ("gfx/inv_mjolnir");
315 hsb_weapons[0][2] = Draw_CachePic ("gfx/inv_gren_prox");
316 hsb_weapons[0][3] = Draw_CachePic ("gfx/inv_prox_gren");
317 hsb_weapons[0][4] = Draw_CachePic ("gfx/inv_prox");
319 hsb_weapons[1][0] = Draw_CachePic ("gfx/inv2_laser");
320 hsb_weapons[1][1] = Draw_CachePic ("gfx/inv2_mjolnir");
321 hsb_weapons[1][2] = Draw_CachePic ("gfx/inv2_gren_prox");
322 hsb_weapons[1][3] = Draw_CachePic ("gfx/inv2_prox_gren");
323 hsb_weapons[1][4] = Draw_CachePic ("gfx/inv2_prox");
325 for (i = 0;i < 5;i++)
327 hsb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_laser",i+1));
328 hsb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_mjolnir",i+1));
329 hsb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_gren_prox",i+1));
330 hsb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_prox_gren",i+1));
331 hsb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_prox",i+1));
334 hsb_items[0] = Draw_CachePic ("gfx/sb_wsuit");
335 hsb_items[1] = Draw_CachePic ("gfx/sb_eshld");
337 else if (gamemode == GAME_ROGUE)
339 rsb_invbar[0] = Draw_CachePic ("gfx/r_invbar1");
340 rsb_invbar[1] = Draw_CachePic ("gfx/r_invbar2");
342 rsb_weapons[0] = Draw_CachePic ("gfx/r_lava");
343 rsb_weapons[1] = Draw_CachePic ("gfx/r_superlava");
344 rsb_weapons[2] = Draw_CachePic ("gfx/r_gren");
345 rsb_weapons[3] = Draw_CachePic ("gfx/r_multirock");
346 rsb_weapons[4] = Draw_CachePic ("gfx/r_plasma");
348 rsb_items[0] = Draw_CachePic ("gfx/r_shield1");
349 rsb_items[1] = Draw_CachePic ("gfx/r_agrav1");
351 // PGM 01/19/97 - team color border
352 rsb_teambord = Draw_CachePic ("gfx/r_teambord");
353 // PGM 01/19/97 - team color border
355 rsb_ammo[0] = Draw_CachePic ("gfx/r_ammolava");
356 rsb_ammo[1] = Draw_CachePic ("gfx/r_ammomulti");
357 rsb_ammo[2] = Draw_CachePic ("gfx/r_ammoplasma");
361 sb_ranking = Draw_CachePic ("gfx/ranking");
362 sb_complete = Draw_CachePic ("gfx/complete");
363 sb_inter = Draw_CachePic ("gfx/inter");
364 sb_finale = Draw_CachePic ("gfx/finale");
367 void sbar_shutdown(void)
371 void sbar_newmap(void)
375 void Sbar_Init (void)
377 Cmd_AddCommand("+showscores", Sbar_ShowScores, "show scoreboard");
378 Cmd_AddCommand("-showscores", Sbar_DontShowScores, "hide scoreboard");
379 Cvar_RegisterVariable(&showfps);
380 Cvar_RegisterVariable(&showsound);
381 Cvar_RegisterVariable(&showspeed);
382 Cvar_RegisterVariable(&showtopspeed);
383 Cvar_RegisterVariable(&showtime);
384 Cvar_RegisterVariable(&showtime_format);
385 Cvar_RegisterVariable(&showdate);
386 Cvar_RegisterVariable(&showdate_format);
387 Cvar_RegisterVariable(&sbar_alpha_bg);
388 Cvar_RegisterVariable(&sbar_alpha_fg);
389 Cvar_RegisterVariable(&sbar_hudselector);
390 Cvar_RegisterVariable(&sbar_scorerank);
391 Cvar_RegisterVariable(&sbar_gametime);
392 Cvar_RegisterVariable(&sbar_miniscoreboard_size);
393 Cvar_RegisterVariable(&sbar_info_pos);
394 Cvar_RegisterVariable(&cl_deathscoreboard);
396 Cvar_RegisterVariable(&crosshair_color_red);
397 Cvar_RegisterVariable(&crosshair_color_green);
398 Cvar_RegisterVariable(&crosshair_color_blue);
399 Cvar_RegisterVariable(&crosshair_color_alpha);
400 Cvar_RegisterVariable(&crosshair_size);
402 if(gamemode == GAME_NEXUIZ)
404 Cvar_RegisterVariable(&sbar_flagstatus_right); // this cvar makes no sense in other games
405 Cvar_RegisterVariable(&sbar_flagstatus_pos); // this cvar makes no sense in other games
408 R_RegisterModule("sbar", sbar_start, sbar_shutdown, sbar_newmap);
412 //=============================================================================
414 // drawing routines are relative to the status bar location
423 void Sbar_DrawStretchPic (int x, int y, cachepic_t *pic, float alpha, float overridewidth, float overrideheight)
425 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, overridewidth, overrideheight, 1, 1, 1, alpha, 0);
428 void Sbar_DrawPic (int x, int y, cachepic_t *pic)
430 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, sbar_alpha_fg.value, 0);
433 void Sbar_DrawAlphaPic (int x, int y, cachepic_t *pic, float alpha)
435 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, alpha, 0);
442 Draws one solid graphics character
445 void Sbar_DrawCharacter (int x, int y, int num)
447 DrawQ_String_Font (sbar_x + x + 4 , sbar_y + y, va("%c", num), 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0, NULL, true, FONT_SBAR);
455 void Sbar_DrawString (int x, int y, char *str)
457 DrawQ_String_Font (sbar_x + x, sbar_y + y, str, 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR);
465 void Sbar_DrawNum (int x, int y, int num, int digits, int color)
470 l = dpsnprintf(str, sizeof(str), "%i", num);
484 Sbar_DrawPic (x, y, sb_nums[color][frame]);
497 void Sbar_DrawXNum (int x, int y, int num, int digits, int lettersize, float r, float g, float b, float a, int flags)
505 l = dpsnprintf(str, sizeof(str), "%0*i", digits, num);
508 l = dpsnprintf(str, sizeof(str), "%i", num);
513 x += (digits-l) * lettersize;
522 DrawQ_Pic (sbar_x + x, sbar_y + y, sb_nums[0][frame],lettersize,lettersize,r,g,b,a * sbar_alpha_fg.value,flags);
529 //=============================================================================
532 int Sbar_IsTeammatch(void)
534 // currently only nexuiz uses the team score board
535 return ((gamemode == GAME_NEXUIZ)
536 && (teamplay.integer > 0));
544 static int fragsort[MAX_SCOREBOARD];
545 static int scoreboardlines;
547 int Sbar_GetSortedPlayerIndex (int index)
549 return index >= 0 && index < scoreboardlines ? fragsort[index] : -1;
552 static scoreboard_t teams[MAX_SCOREBOARD];
553 static int teamsort[MAX_SCOREBOARD];
554 static int teamlines;
555 void Sbar_SortFrags (void)
561 for (i=0 ; i<cl.maxclients ; i++)
563 if (cl.scores[i].name[0])
565 fragsort[scoreboardlines] = i;
570 for (i=0 ; i<scoreboardlines ; i++)
571 for (j=0 ; j<scoreboardlines-1-i ; j++)
572 if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j+1]].frags)
575 fragsort[j] = fragsort[j+1];
580 if (Sbar_IsTeammatch ())
582 // now sort players by teams.
583 for (i=0 ; i<scoreboardlines ; i++)
585 for (j=0 ; j<scoreboardlines-1-i ; j++)
587 if (cl.scores[fragsort[j]].colors < cl.scores[fragsort[j+1]].colors)
590 fragsort[j] = fragsort[j+1];
596 // calculate team scores
598 for (i=0 ; i<scoreboardlines ; i++)
600 if (color != (cl.scores[fragsort[i]].colors & 15))
602 const char* teamname;
604 color = cl.scores[fragsort[i]].colors & 15;
610 teamname = "^1Red Team";
613 teamname = "^4Blue Team";
616 teamname = "^6Pink Team";
619 teamname = "^3Yellow Team";
622 teamname = "Total Team Score";
625 strlcpy(teams[teamlines-1].name, teamname, sizeof(teams[teamlines-1].name));
627 teams[teamlines-1].frags = 0;
628 teams[teamlines-1].colors = color + 16 * color;
631 if (cl.scores[fragsort[i]].frags != -666)
633 // do not add spedcators
634 // (ugly hack for nexuiz)
635 teams[teamlines-1].frags += cl.scores[fragsort[i]].frags;
639 // now sort teams by scores.
640 for (i=0 ; i<teamlines ; i++)
642 for (i=0 ; i<teamlines ; i++)
644 for (j=0 ; j<teamlines-1-i ; j++)
646 if (teams[teamsort[j]].frags < teams[teamsort[j+1]].frags)
649 teamsort[j] = teamsort[j+1];
662 void Sbar_SoloScoreboard (void)
665 char str[80], timestr[40];
667 int minutes, seconds;
670 t = (cl.intermission ? cl.completed_time : cl.time);
671 minutes = (int)(t / 60);
672 seconds = (int)(t - 60*floor(t/60));
674 // monsters and secrets are now both on the top row
675 if (cl.stats[STAT_TOTALMONSTERS])
676 Sbar_DrawString(8, 4, va("Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]));
677 else if (cl.stats[STAT_MONSTERS]) // LA: Display something if monsters_killed is non-zero, but total_monsters is zero
678 Sbar_DrawString(8, 4, va("Monsters:%3i", cl.stats[STAT_MONSTERS]));
680 if (cl.stats[STAT_TOTALSECRETS])
681 Sbar_DrawString(8+22*8, 4, va("Secrets:%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]));
682 else if (cl.stats[STAT_SECRETS]) // LA: And similarly for secrets
683 Sbar_DrawString(8+22*8, 4, va("Secrets:%3i", cl.stats[STAT_SECRETS]));
685 // figure out the map's filename without path or extension
686 strlcpy(str, FS_FileWithoutPath(cl.worldmodel ? cl.worldmodel->name : ""), sizeof(str));
687 if (strrchr(str, '.'))
688 *(strrchr(str, '.')) = 0;
690 // append a : separator and then the full title
691 strlcat(str, ":", sizeof(str));
692 strlcat(str, cl.levelname, sizeof(str));
694 // if there's a newline character, terminate the string there
695 if (strchr(str, '\n'))
696 *(strchr(str, '\n')) = 0;
698 // make the time string
699 timelen = dpsnprintf(timestr, sizeof(timestr), " %i:%02i", minutes, seconds);
701 // truncate the level name if necessary to make room for time
703 if ((int)strlen(str) > max)
706 // print the filename and message
707 Sbar_DrawString(8, 12, str);
710 Sbar_DrawString(8 + max*8, 12, timestr);
714 int minutes, seconds, tens, units;
717 if (gamemode != GAME_NEXUIZ) {
718 dpsnprintf (str, sizeof(str), "Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
719 Sbar_DrawString (8, 4, str);
721 dpsnprintf (str, sizeof(str), "Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
722 Sbar_DrawString (8, 12, str);
726 minutes = (int)(cl.time / 60);
727 seconds = (int)(cl.time - 60*minutes);
729 units = seconds - 10*tens;
730 dpsnprintf (str, sizeof(str), "Time :%3i:%i%i", minutes, tens, units);
731 Sbar_DrawString (184, 4, str);
734 if (gamemode == GAME_NEXUIZ) {
735 l = (int) strlen (cl.worldmodel->name);
736 Sbar_DrawString (232 - l*4, 12, cl.worldmodel->name);
738 l = (int) strlen (cl.levelname);
739 Sbar_DrawString (232 - l*4, 12, cl.levelname);
749 void Sbar_DrawScoreboard (void)
751 Sbar_SoloScoreboard ();
752 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
753 //if (cl.gametype == GAME_DEATHMATCH)
755 Sbar_DeathmatchOverlay ();
758 //=============================================================================
760 // AK to make DrawInventory smaller
761 static void Sbar_DrawWeapon(int nr, float fade, int active)
763 if (sbar_hudselector.integer == 1)
765 // width = 300, height = 100
766 const int w_width = 32, w_height = 12, w_space = 2, font_size = 8;
768 DrawQ_Pic((vid_conwidth.integer - w_width * 9) * 0.5 + w_width * nr, vid_conheight.integer - w_height, sb_weapons[0][nr], w_width, w_height, (active) ? 1 : 0.6, active ? 1 : 0.6, active ? 1 : 0.6, (active ? 1 : 0.6) * fade * sbar_alpha_fg.value, DRAWFLAG_NORMAL);
770 DrawQ_String((vid_conwidth.integer - w_width * 9) * 0.5 + w_width * nr + w_space, vid_conheight.integer - w_height + w_space, va("%i",nr+1), 0, font_size, font_size, 1, 1, 0, sbar_alpha_fg.value, 0, NULL, true);
774 // width = 300, height = 100
775 const int w_width = 300, w_height = 100, w_space = 10;
776 const float w_scale = 0.4;
778 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);
779 //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);
788 void Sbar_DrawInventory (void)
795 if (gamemode == GAME_ROGUE)
797 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
798 Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], sbar_alpha_bg.value);
800 Sbar_DrawAlphaPic (0, -24, rsb_invbar[1], sbar_alpha_bg.value);
803 Sbar_DrawAlphaPic (0, -24, sb_ibar, sbar_alpha_bg.value);
806 for (i=0 ; i<7 ; i++)
808 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<i) )
810 time = cl.item_gettime[i];
811 flashon = (int)(max(0, cl.time - time)*10);
814 if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i) )
820 flashon = (flashon%5) + 2;
822 Sbar_DrawAlphaPic (i*24, -16, sb_weapons[flashon][i], sbar_alpha_bg.value);
828 if (gamemode == GAME_HIPNOTIC)
830 int grenadeflashing=0;
831 for (i=0 ; i<4 ; i++)
833 if (cl.stats[STAT_ITEMS] & (1<<hipweapons[i]) )
835 time = max(0, cl.item_gettime[hipweapons[i]]);
836 flashon = (int)((cl.time - time)*10);
839 if ( cl.stats[STAT_ACTIVEWEAPON] == (1<<hipweapons[i]) )
845 flashon = (flashon%5) + 2;
847 // check grenade launcher
850 if (cl.stats[STAT_ITEMS] & HIT_PROXIMITY_GUN)
855 Sbar_DrawPic (96, -16, hsb_weapons[flashon][2]);
861 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<4))
863 if (!grenadeflashing)
864 Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
867 Sbar_DrawPic (96, -16, hsb_weapons[flashon][4]);
870 Sbar_DrawPic (176 + (i*24), -16, hsb_weapons[flashon][i]);
875 if (gamemode == GAME_ROGUE)
877 // check for powered up weapon.
878 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
880 if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i))
881 Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]);
885 for (i=0 ; i<4 ; i++)
887 dpsnprintf (num, sizeof(num), "%4i",cl.stats[STAT_SHELLS+i] );
889 Sbar_DrawCharacter ( (6*i+0)*8 - 2, -24, 18 + num[0] - '0');
891 Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[1] - '0');
893 Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[2] - '0');
895 Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[3] - '0');
899 for (i=0 ; i<6 ; i++)
900 if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
902 //MED 01/04/97 changed keys
903 if (gamemode != GAME_HIPNOTIC || (i>1))
904 Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
907 //MED 01/04/97 added hipnotic items
909 if (gamemode == GAME_HIPNOTIC)
911 for (i=0 ; i<2 ; i++)
912 if (cl.stats[STAT_ITEMS] & (1<<(24+i)))
913 Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
916 if (gamemode == GAME_ROGUE)
919 for (i=0 ; i<2 ; i++)
920 if (cl.stats[STAT_ITEMS] & (1<<(29+i)))
921 Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
926 for (i=0 ; i<4 ; i++)
927 if (cl.stats[STAT_ITEMS] & (1<<(28+i)))
928 Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
932 //=============================================================================
939 void Sbar_DrawFrags (void)
949 l = min(scoreboardlines, 4);
953 for (i = 0;i < l;i++)
959 c = palette_rgb_pantsscoreboard[(s->colors & 0xf0) >> 4];
960 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), sbar_alpha_fg.value, 0);
961 c = palette_rgb_shirtscoreboard[s->colors & 0xf];
962 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), sbar_alpha_fg.value, 0);
966 dpsnprintf (num, sizeof(num), "%3i",f);
968 if (k == cl.viewentity - 1)
970 Sbar_DrawCharacter ( x + 2, -24, 16);
971 Sbar_DrawCharacter ( x + 32 - 4, -24, 17);
973 Sbar_DrawCharacter (x + 8, -24, num[0]);
974 Sbar_DrawCharacter (x + 16, -24, num[1]);
975 Sbar_DrawCharacter (x + 24, -24, num[2]);
980 //=============================================================================
988 void Sbar_DrawFace (void)
992 // PGM 01/19/97 - team color drawing
993 // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
994 if (gamemode == GAME_ROGUE && !cl.islocalgame && (teamplay.integer > 3) && (teamplay.integer < 7))
1000 s = &cl.scores[cl.viewentity - 1];
1002 Sbar_DrawPic (112, 0, rsb_teambord);
1003 c = palette_rgb_pantsscoreboard[(s->colors & 0xf0) >> 4];
1004 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), sbar_alpha_fg.value, 0);
1005 c = palette_rgb_shirtscoreboard[s->colors & 0xf];
1006 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), sbar_alpha_fg.value, 0);
1010 dpsnprintf (num, sizeof(num), "%3i",f);
1012 if ((s->colors & 0xf0)==0)
1015 Sbar_DrawCharacter(109, 3, 18 + num[0] - '0');
1017 Sbar_DrawCharacter(116, 3, 18 + num[1] - '0');
1019 Sbar_DrawCharacter(123, 3, 18 + num[2] - '0');
1023 Sbar_DrawCharacter ( 109, 3, num[0]);
1024 Sbar_DrawCharacter ( 116, 3, num[1]);
1025 Sbar_DrawCharacter ( 123, 3, num[2]);
1030 // PGM 01/19/97 - team color drawing
1032 if ( (cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
1033 Sbar_DrawPic (112, 0, sb_face_invis_invuln);
1034 else if (cl.stats[STAT_ITEMS] & IT_QUAD)
1035 Sbar_DrawPic (112, 0, sb_face_quad );
1036 else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
1037 Sbar_DrawPic (112, 0, sb_face_invis );
1038 else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1039 Sbar_DrawPic (112, 0, sb_face_invuln);
1042 f = cl.stats[STAT_HEALTH] / 20;
1044 Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]);
1047 double topspeed = 0;
1048 double topspeedxy = 0;
1049 time_t current_time = 3;
1050 time_t top_time = 0;
1051 time_t topxy_time = 0;
1053 static void get_showspeed_unit(int unitnumber, double *conversion_factor, const char **unit)
1056 unitnumber = showspeed.integer;
1061 if(gamemode == GAME_NEXUIZ)
1065 *conversion_factor = 1.0;
1069 *conversion_factor = 0.0254;
1070 if(gamemode != GAME_NEXUIZ) *conversion_factor *= 1.5;
1071 // 1qu=1.5in is for non-Nexuiz only - Nexuiz players are overly large, but 1qu=1in fixes that
1075 *conversion_factor = 0.0254 * 3.6;
1076 if(gamemode != GAME_NEXUIZ) *conversion_factor *= 1.5;
1080 *conversion_factor = 0.0254 * 3.6 * 0.6213711922;
1081 if(gamemode != GAME_NEXUIZ) *conversion_factor *= 1.5;
1085 *conversion_factor = 0.0254 * 1.943844492; // 1 m/s = 1.943844492 knots, because 1 knot = 1.852 km/h
1086 if(gamemode != GAME_NEXUIZ) *conversion_factor *= 1.5;
1091 void Sbar_ShowFPS(void)
1093 float fps_x, fps_y, fps_scalex, fps_scaley, fps_height;
1094 char soundstring[32];
1096 char timestring[32];
1097 char datestring[32];
1098 char speedstring[32];
1099 char topspeedstring[48];
1100 qboolean red = false;
1106 topspeedstring[0] = 0;
1107 if (showfps.integer)
1110 static double nexttime = 0, lasttime = 0;
1111 static double framerate = 0;
1112 static int framecount = 0;
1113 double interval = 1;
1115 newtime = Sys_DoubleTime();
1116 if (newtime >= nexttime)
1118 if (framecount > 1) // frames per second
1119 framerate = framecount / interval;
1120 else // seconds per frame
1121 framerate = framecount / (newtime - lasttime);
1122 if (nexttime < newtime - interval * 1.5)
1125 nexttime += interval;
1131 if ((red = (calc < 1.0f)))
1132 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0 / calc + 0.5));
1134 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(calc + 0.5));
1136 if (showtime.integer)
1137 strlcpy(timestring, Sys_TimeString(showtime_format.string), sizeof(timestring));
1138 if (showdate.integer)
1139 strlcpy(datestring, Sys_TimeString(showdate_format.string), sizeof(datestring));
1140 if (showsound.integer)
1141 dpsnprintf(soundstring, sizeof(soundstring), "%4i/4%i at %3ims", cls.soundstats.mixedsounds, cls.soundstats.totalsounds, cls.soundstats.latency_milliseconds);
1142 if (showspeed.integer || showtopspeed.integer)
1144 double speed, speedxy, f;
1146 speed = VectorLength(cl.movement_velocity);
1147 speedxy = sqrt(cl.movement_velocity[0] * cl.movement_velocity[0] + cl.movement_velocity[1] * cl.movement_velocity[1]);
1148 if (showspeed.integer)
1150 get_showspeed_unit(showspeed.integer, &f, &unit);
1151 dpsnprintf(speedstring, sizeof(speedstring), "%.0f (%.0f) %s", f*speed, f*speedxy, unit);
1153 if (showtopspeed.integer)
1155 qboolean topspeed_latched = false, topspeedxy_latched = false;
1156 get_showspeed_unit(showtopspeed.integer, &f, &unit);
1157 if (speed >= topspeed || current_time - top_time > 3)
1163 topspeed_latched = true;
1164 if (speedxy >= topspeedxy || current_time - topxy_time > 3)
1166 topspeedxy = speedxy;
1170 topspeedxy_latched = true;
1171 dpsnprintf(topspeedstring, sizeof(topspeedstring), "%s%.0f%s (%s%.0f%s) %s",
1172 topspeed_latched ? "^1" : "^xf88", f*topspeed, "^xf88",
1173 topspeedxy_latched ? "^1" : "^xf88", f*topspeedxy, "^xf88",
1175 time(¤t_time);
1178 if (fpsstring[0] || timestring[0] || datestring[0] || speedstring[0] || topspeedstring[0])
1182 fps_height = fps_scaley * ((soundstring[0] != 0) + (fpsstring[0] != 0) + (timestring[0] != 0) + (datestring[0] != 0) + (speedstring[0] != 0) + (topspeedstring[0] != 0));
1183 //fps_y = vid_conheight.integer - sb_lines; // yes this may draw over the sbar
1184 //fps_y = bound(0, fps_y, vid_conheight.integer - fps_height);
1185 fps_y = vid_conheight.integer - sbar_info_pos.integer - fps_height;
1188 fps_x = vid_conwidth.integer - DrawQ_TextWidth_Font(soundstring, 0, true, FONT_INFOBAR) * fps_scalex;
1189 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1190 DrawQ_String_Font(fps_x, fps_y, soundstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1191 fps_y += fps_scaley;
1195 fps_x = vid_conwidth.integer - DrawQ_TextWidth_Font(fpsstring, 0, true, FONT_INFOBAR) * fps_scalex;
1196 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1198 DrawQ_String_Font(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 0, 0, 1, 0, NULL, true, FONT_INFOBAR);
1200 DrawQ_String_Font(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1201 fps_y += fps_scaley;
1205 fps_x = vid_conwidth.integer - DrawQ_TextWidth_Font(timestring, 0, true, FONT_INFOBAR) * fps_scalex;
1206 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1207 DrawQ_String_Font(fps_x, fps_y, timestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1208 fps_y += fps_scaley;
1212 fps_x = vid_conwidth.integer - DrawQ_TextWidth_Font(datestring, 0, true, FONT_INFOBAR) * fps_scalex;
1213 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1214 DrawQ_String_Font(fps_x, fps_y, datestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1215 fps_y += fps_scaley;
1219 fps_x = vid_conwidth.integer - DrawQ_TextWidth_Font(speedstring, 0, true, FONT_INFOBAR) * fps_scalex;
1220 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1221 DrawQ_String_Font(fps_x, fps_y, speedstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1222 fps_y += fps_scaley;
1224 if (topspeedstring[0])
1226 fps_x = vid_conwidth.integer - DrawQ_TextWidth_Font(topspeedstring, 0, false, FONT_INFOBAR) * fps_scalex;
1227 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1228 DrawQ_String_Font(fps_x, fps_y, topspeedstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, false, FONT_INFOBAR);
1229 fps_y += fps_scaley;
1234 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)
1237 c2 = bound(0, c2, 1);
1238 c1 = bound(0, c1, 1 - c2);
1240 r[1] = rangey + rangeheight * (c2 + c1);
1241 r[2] = rangey + rangeheight * (c2);
1245 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);
1247 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);
1249 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);
1251 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);
1259 extern float v_dmg_time, v_dmg_roll, v_dmg_pitch;
1260 extern cvar_t v_kicktime;
1261 void Sbar_Score (int margin);
1262 void Sbar_Draw (void)
1266 if(cl.csqc_vidvars.drawenginesbar) //[515]: csqc drawsbar
1269 Sbar_DrawScoreboard ();
1270 else if (cl.intermission == 1)
1272 if(gamemode == GAME_NEXUIZ) // display full scoreboard (that is, show scores + map name)
1274 Sbar_DrawScoreboard();
1277 Sbar_IntermissionOverlay();
1279 else if (cl.intermission == 2)
1280 Sbar_FinaleOverlay();
1281 else if (gamemode == GAME_DELUXEQUAKE)
1284 else if (gamemode == GAME_SOM)
1286 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1287 Sbar_DrawScoreboard ();
1290 // this is the top left of the sbar area
1292 sbar_y = vid_conheight.integer - 24*3;
1295 if (cl.stats[STAT_ARMOR])
1297 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1298 Sbar_DrawPic(0, 0, somsb_armor[2]);
1299 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1300 Sbar_DrawPic(0, 0, somsb_armor[1]);
1301 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1302 Sbar_DrawPic(0, 0, somsb_armor[0]);
1303 Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1307 Sbar_DrawPic(0, 24, somsb_health);
1308 Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1311 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1312 Sbar_DrawPic(0, 48, somsb_ammo[0]);
1313 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1314 Sbar_DrawPic(0, 48, somsb_ammo[1]);
1315 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1316 Sbar_DrawPic(0, 48, somsb_ammo[2]);
1317 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1318 Sbar_DrawPic(0, 48, somsb_ammo[3]);
1319 Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
1320 if (cl.stats[STAT_SHELLS])
1321 Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
1324 else if (gamemode == GAME_NEXUIZ)
1326 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1328 sbar_x = (vid_conwidth.integer - 640)/2;
1329 sbar_y = vid_conheight.integer - 47;
1330 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1331 Sbar_DrawScoreboard ();
1333 else if (sb_lines && sbar_hudselector.integer == 1)
1337 int redflag, blueflag;
1340 sbar_x = (vid_conwidth.integer - 320)/2;
1341 sbar_y = vid_conheight.integer - 24 - 16;
1343 // calculate intensity to draw weapons bar at
1344 fade = 3.2 - 2 * (cl.time - cl.weapontime);
1345 fade = bound(0.7, fade, 1);
1346 for (i = 0; i < 8;i++)
1347 if (cl.stats[STAT_ITEMS] & (1 << i))
1348 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1349 if((cl.stats[STAT_ITEMS] & (1<<12)))
1350 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1353 redflag = ((cl.stats[STAT_ITEMS]>>15) & 3);
1354 blueflag = ((cl.stats[STAT_ITEMS]>>17) & 3);
1355 x = sbar_flagstatus_right.integer ? vid_conwidth.integer - 10 - sbar_x - 64 : 10 - sbar_x;
1356 if (redflag == 3 && blueflag == 3)
1358 // The Impossible Combination[tm]
1359 // Can only happen in Key Hunt mode...
1360 Sbar_DrawPic ((int) x, (int) ((vid_conheight.integer - sbar_y) - (sbar_flagstatus_pos.value + 128)), sb_items[14]);
1365 Sbar_DrawPic ((int) x, (int) ((vid_conheight.integer - sbar_y) - (sbar_flagstatus_pos.value + 64)), sb_items[redflag+10]);
1367 Sbar_DrawPic ((int) x, (int) ((vid_conheight.integer - sbar_y) - (sbar_flagstatus_pos.value + 128)), sb_items[blueflag+14]);
1371 if (cl.stats[STAT_ARMOR] > 0)
1373 Sbar_DrawStretchPic (72, 0, sb_armor[0], sbar_alpha_fg.value, 24, 24);
1374 if(cl.stats[STAT_ARMOR] > 200)
1375 Sbar_DrawXNum(0,0,cl.stats[STAT_ARMOR],3,24,0,1,0,1,0);
1376 else if(cl.stats[STAT_ARMOR] > 100)
1377 Sbar_DrawXNum(0,0,cl.stats[STAT_ARMOR],3,24,0.2,1,0.2,1,0);
1378 else if(cl.stats[STAT_ARMOR] > 50)
1379 Sbar_DrawXNum(0,0,cl.stats[STAT_ARMOR],3,24,0.6,0.7,0.8,1,0);
1380 else if(cl.stats[STAT_ARMOR] > 25)
1381 Sbar_DrawXNum(0,0,cl.stats[STAT_ARMOR],3,24,1,1,0.2,1,0);
1383 Sbar_DrawXNum(0,0,cl.stats[STAT_ARMOR],3,24,0.7,0,0,1,0);
1387 if (cl.stats[STAT_HEALTH] != 0)
1389 Sbar_DrawStretchPic (184, 0, sb_health, sbar_alpha_fg.value, 24, 24);
1390 if(cl.stats[STAT_HEALTH] > 200)
1391 Sbar_DrawXNum(112,0,cl.stats[STAT_HEALTH],3,24,0,1,0,1,0);
1392 else if(cl.stats[STAT_HEALTH] > 100)
1393 Sbar_DrawXNum(112,0,cl.stats[STAT_HEALTH],3,24,0.2,1,0.2,1,0);
1394 else if(cl.stats[STAT_HEALTH] > 50)
1395 Sbar_DrawXNum(112,0,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1396 else if(cl.stats[STAT_HEALTH] > 25)
1397 Sbar_DrawXNum(112,0,cl.stats[STAT_HEALTH],3,24,1,1,0.2,1,0);
1399 Sbar_DrawXNum(112,0,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1403 if ((cl.stats[STAT_ITEMS] & (NEX_IT_SHELLS | NEX_IT_BULLETS | NEX_IT_ROCKETS | NEX_IT_CELLS)) || cl.stats[STAT_AMMO] != 0)
1405 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1406 Sbar_DrawStretchPic (296, 0, sb_ammo[0], sbar_alpha_fg.value, 24, 24);
1407 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1408 Sbar_DrawStretchPic (296, 0, sb_ammo[1], sbar_alpha_fg.value, 24, 24);
1409 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1410 Sbar_DrawStretchPic (296, 0, sb_ammo[2], sbar_alpha_fg.value, 24, 24);
1411 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1412 Sbar_DrawStretchPic (296, 0, sb_ammo[3], sbar_alpha_fg.value, 24, 24);
1413 if(cl.stats[STAT_AMMO] > 10)
1414 Sbar_DrawXNum(224, 0, cl.stats[STAT_AMMO], 3, 24, 0.6,0.7,0.8,1,0);
1416 Sbar_DrawXNum(224, 0, cl.stats[STAT_AMMO], 3, 24, 0.7,0,0,1,0);
1419 if (sbar_x + 320 + 160 <= vid_conwidth.integer)
1420 Sbar_MiniDeathmatchOverlay (sbar_x + 320, sbar_y);
1423 // The margin can be at most 8 to support 640x480 console size:
1424 // 320 + 2 * (144 + 16) = 640
1430 int redflag, blueflag;
1433 sbar_x = (vid_conwidth.integer - 640)/2;
1434 sbar_y = vid_conheight.integer - 47;
1436 // calculate intensity to draw weapons bar at
1437 fade = 3 - 2 * (cl.time - cl.weapontime);
1440 fade = min(fade, 1);
1441 for (i = 0; i < 8;i++)
1442 if (cl.stats[STAT_ITEMS] & (1 << i))
1443 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1445 if((cl.stats[STAT_ITEMS] & (1<<12)))
1446 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1449 //if (!cl.islocalgame)
1450 // Sbar_DrawFrags ();
1453 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1455 Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1458 redflag = ((cl.stats[STAT_ITEMS]>>15) & 3);
1459 blueflag = ((cl.stats[STAT_ITEMS]>>17) & 3);
1460 x = sbar_flagstatus_right.integer ? vid_conwidth.integer - 10 - sbar_x - 64 : 10 - sbar_x;
1461 if (redflag == 3 && blueflag == 3)
1463 // The Impossible Combination[tm]
1464 // Can only happen in Key Hunt mode...
1465 Sbar_DrawPic ((int) x, -179, sb_items[14]);
1470 Sbar_DrawPic ((int) x, -117, sb_items[redflag+10]);
1472 Sbar_DrawPic ((int) x, -177, sb_items[blueflag+14]);
1476 Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1479 if(cl.stats[STAT_HEALTH] > 100)
1480 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1481 else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1482 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1484 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1486 // AK dont draw ammo for the laser
1487 if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1489 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1490 Sbar_DrawPic (519, 0, sb_ammo[0]);
1491 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1492 Sbar_DrawPic (519, 0, sb_ammo[1]);
1493 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1494 Sbar_DrawPic (519, 0, sb_ammo[2]);
1495 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1496 Sbar_DrawPic (519, 0, sb_ammo[3]);
1498 if(cl.stats[STAT_AMMO] <= 10)
1499 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1501 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1506 DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1508 if (sbar_x + 600 + 160 <= vid_conwidth.integer)
1509 Sbar_MiniDeathmatchOverlay (sbar_x + 600, sbar_y);
1514 // Mini scoreboard uses 12*4 per other team, that is, 144
1515 // pixels when there are four teams...
1516 // Nexuiz by default sets vid_conwidth to 800... makes
1518 // so we need to shift it by 64 pixels to the right to fit
1519 // BUT: then it overlaps with the image that gets drawn
1520 // for viewsize 100! Therefore, just account for 3 teams,
1521 // that is, 96 pixels mini scoreboard size, needing 16 pixels
1525 else if (gamemode == GAME_ZYMOTIC)
1528 float scale = 64.0f / 256.0f;
1529 float kickoffset[3];
1530 VectorClear(kickoffset);
1533 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1534 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1536 sbar_x = (int)((vid_conwidth.integer - 256 * scale)/2 + kickoffset[0]);
1537 sbar_y = (int)((vid_conheight.integer - 256 * scale)/2 + kickoffset[1]);
1538 // left1 16, 48 : 126 -66
1539 // left2 16, 128 : 196 -66
1540 // right 176, 48 : 196 -136
1541 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);
1542 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);
1543 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);
1544 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1546 float scale = 128.0f / 256.0f;
1547 float healthstart, healthheight, healthstarttc, healthendtc;
1548 float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1549 float ammostart, ammoheight, ammostarttc, ammoendtc;
1550 float clipstart, clipheight, clipstarttc, clipendtc;
1551 float kickoffset[3], offset;
1552 VectorClear(kickoffset);
1555 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1556 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1558 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1559 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1560 offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1561 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);
1562 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);
1563 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);
1564 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);
1565 healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1566 shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1567 healthstart = 204 - healthheight;
1568 shieldstart = healthstart - shieldheight;
1569 healthstarttc = healthstart * (1.0f / 256.0f);
1570 healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1571 shieldstarttc = shieldstart * (1.0f / 256.0f);
1572 shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1573 ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1574 ammostart = 114 - ammoheight;
1575 ammostarttc = ammostart * (1.0f / 256.0f);
1576 ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1577 clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1578 clipstart = 190 - clipheight;
1579 clipstarttc = clipstart * (1.0f / 256.0f);
1580 clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1581 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);
1582 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);
1583 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);
1584 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);
1585 DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1586 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1589 else // Quake and others
1591 sbar_x = (vid_conwidth.integer - 320)/2;
1592 sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1593 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1594 //if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1598 if (gamemode != GAME_GOODVSBAD2)
1599 Sbar_DrawInventory ();
1600 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1604 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1606 if (gamemode != GAME_GOODVSBAD2)
1607 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1608 Sbar_DrawScoreboard ();
1612 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1614 // keys (hipnotic only)
1615 //MED 01/04/97 moved keys here so they would not be overwritten
1616 if (gamemode == GAME_HIPNOTIC)
1618 if (cl.stats[STAT_ITEMS] & IT_KEY1)
1619 Sbar_DrawPic (209, 3, sb_items[0]);
1620 if (cl.stats[STAT_ITEMS] & IT_KEY2)
1621 Sbar_DrawPic (209, 12, sb_items[1]);
1624 if (gamemode != GAME_GOODVSBAD2)
1626 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1628 Sbar_DrawNum (24, 0, 666, 3, 1);
1629 Sbar_DrawPic (0, 0, sb_disc);
1633 if (gamemode == GAME_ROGUE)
1635 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1636 if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1637 Sbar_DrawPic (0, 0, sb_armor[2]);
1638 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1639 Sbar_DrawPic (0, 0, sb_armor[1]);
1640 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1641 Sbar_DrawPic (0, 0, sb_armor[0]);
1645 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1646 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1647 Sbar_DrawPic (0, 0, sb_armor[2]);
1648 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1649 Sbar_DrawPic (0, 0, sb_armor[1]);
1650 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1651 Sbar_DrawPic (0, 0, sb_armor[0]);
1660 Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1663 if (gamemode == GAME_ROGUE)
1665 if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1666 Sbar_DrawPic (224, 0, sb_ammo[0]);
1667 else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1668 Sbar_DrawPic (224, 0, sb_ammo[1]);
1669 else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1670 Sbar_DrawPic (224, 0, sb_ammo[2]);
1671 else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1672 Sbar_DrawPic (224, 0, sb_ammo[3]);
1673 else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1674 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1675 else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1676 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1677 else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1678 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1682 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1683 Sbar_DrawPic (224, 0, sb_ammo[0]);
1684 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1685 Sbar_DrawPic (224, 0, sb_ammo[1]);
1686 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1687 Sbar_DrawPic (224, 0, sb_ammo[2]);
1688 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1689 Sbar_DrawPic (224, 0, sb_ammo[3]);
1692 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1694 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1695 if ((!cl.islocalgame || cl.gametype != GAME_COOP))
1697 if (gamemode == GAME_TRANSFUSION)
1698 Sbar_MiniDeathmatchOverlay (0, 0);
1700 Sbar_MiniDeathmatchOverlay (sbar_x + 324, vid_conheight.integer - 8*8);
1709 if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && !cl.intermission && !r_letterbox.value)
1711 pic = Draw_CachePic (va("gfx/crosshair%i", crosshair.integer));
1712 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);
1715 if (cl_prydoncursor.integer)
1716 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)), 0, 0, 1, 1, 1, 1, 0);
1719 //=============================================================================
1723 Sbar_DeathmatchOverlay
1727 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1730 qboolean myself = false;
1732 minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : cl.time - s->qw_entertime) / 60.0);
1734 if((s - cl.scores) == cl.playerentity - 1)
1736 if((s - teams) >= 0 && (s - teams) < MAX_SCOREBOARD)
1737 if((s->colors & 15) == (cl.scores[cl.playerentity - 1].colors & 15))
1740 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1742 if (s->qw_spectator)
1744 if (s->qw_ping || s->qw_packetloss)
1745 DrawQ_String_Font(x, y, va("%4i %3i %4i spectator %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1747 DrawQ_String_Font(x, y, va(" %4i spectator %c%s", minutes, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1751 // draw colors behind score
1757 c = palette_rgb_pantsscoreboard[(s->colors & 0xf0) >> 4];
1758 DrawQ_Fill(x + 14*8*FONT_SBAR->maxwidth, y+1, 40*FONT_SBAR->maxwidth, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), sbar_alpha_fg.value, 0);
1759 c = palette_rgb_shirtscoreboard[s->colors & 0xf];
1760 DrawQ_Fill(x + 14*8*FONT_SBAR->maxwidth, y+4, 40*FONT_SBAR->maxwidth, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), sbar_alpha_fg.value, 0);
1762 //DrawQ_String(x, y, va("%c%4i %s", myself ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, true);
1763 if (s->qw_ping || s->qw_packetloss)
1764 DrawQ_String_Font(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 : "", myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1766 DrawQ_String_Font(x, y, va(" %4i %5i %-4s %c%s", minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1771 if (s->qw_spectator)
1773 if (s->qw_ping || s->qw_packetloss)
1774 DrawQ_String_Font(x, y, va("%4i %3i spect %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1776 DrawQ_String_Font(x, y, va(" spect %c%s", myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1780 // draw colors behind score
1781 c = palette_rgb_pantsscoreboard[(s->colors & 0xf0) >> 4];
1782 DrawQ_Fill(x + 9*8*FONT_SBAR->maxwidth, y+1, 40*FONT_SBAR->maxwidth, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), sbar_alpha_fg.value, 0);
1783 c = palette_rgb_shirtscoreboard[s->colors & 0xf];
1784 DrawQ_Fill(x + 9*8*FONT_SBAR->maxwidth, y+4, 40*FONT_SBAR->maxwidth, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), sbar_alpha_fg.value, 0);
1786 //DrawQ_String(x, y, va("%c%4i %s", myself ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, true);
1787 if (s->qw_ping || s->qw_packetloss)
1788 DrawQ_String_Font(x, y, va("%4i %3i %5i %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), (int) s->frags, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1790 DrawQ_String_Font(x, y, va(" %5i %c%s", (int) s->frags, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1796 void Sbar_DeathmatchOverlay (void)
1798 int i, y, xmin, xmax, ymin, ymax;
1800 // request new ping times every two second
1801 if (cl.last_ping_request < realtime - 2 && cls.netcon)
1803 cl.last_ping_request = realtime;
1804 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1806 MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
1807 MSG_WriteString(&cls.netcon->message, "pings");
1809 else if (cls.protocol == PROTOCOL_QUAKE || cls.protocol == PROTOCOL_QUAKEDP || cls.protocol == PROTOCOL_NEHAHRAMOVIE || cls.protocol == PROTOCOL_NEHAHRABJP || cls.protocol == PROTOCOL_NEHAHRABJP2 || cls.protocol == PROTOCOL_NEHAHRABJP3 || 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*/)
1811 // 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
1812 static int ping_anyway_counter = 0;
1813 if(cl.parsingtextexpectingpingforscores == 1)
1815 Con_DPrintf("want to send ping, but still waiting for other reply\n");
1816 if(++ping_anyway_counter >= 5)
1817 cl.parsingtextexpectingpingforscores = 0;
1819 if(cl.parsingtextexpectingpingforscores != 1)
1821 ping_anyway_counter = 0;
1822 cl.parsingtextexpectingpingforscores = 1; // hide the output of the next ping report
1823 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1824 MSG_WriteString(&cls.netcon->message, "ping");
1829 // newer server definitely has pings command, so use it for more efficiency, avoids ping reports spamming the console if they are misparsed, and saves a little bandwidth
1830 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1831 MSG_WriteString(&cls.netcon->message, "pings");
1839 ymax = 40 + 8 + (Sbar_IsTeammatch() ? (teamlines * 8 + 5): 0) + scoreboardlines * 8 - 1;
1841 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1842 xmin = (int) (vid_conwidth.integer - (26 + 15) * 8 * FONT_SBAR->maxwidth) / 2; // 26 characters until name, then we assume 15 character names (they can be longer but usually aren't)
1844 xmin = (int) (vid_conwidth.integer - (16 + 25) * 8 * FONT_SBAR->maxwidth) / 2; // 16 characters until name, then we assume 25 character names (they can be longer but usually aren't)
1845 xmax = vid_conwidth.integer - xmin;
1847 if(gamemode == GAME_NEXUIZ)
1848 DrawQ_Pic (xmin - 8, ymin - 8, 0, xmax-xmin+1 + 2*8, ymax-ymin+1 + 2*8, 0, 0, 0, sbar_alpha_bg.value, 0);
1850 DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1854 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1856 DrawQ_String_Font(xmin, y, va("ping pl%% time frags team name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1860 DrawQ_String_Font(xmin, y, va("ping pl%% frags name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1864 if (Sbar_IsTeammatch ())
1866 // show team scores first
1867 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1868 y += (int)Sbar_PrintScoreboardItem((teams + teamsort[i]), xmin, y);
1872 for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1873 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], xmin, y);
1878 Sbar_MiniDeathmatchOverlay
1882 void Sbar_MiniDeathmatchOverlay (int x, int y)
1884 int i, j, numlines, range_begin, range_end, myteam, teamsep;
1886 // do not draw this if sbar_miniscoreboard_size is zero
1887 if(sbar_miniscoreboard_size.value == 0)
1889 // adjust the given y if sbar_miniscoreboard_size doesn't indicate default (< 0)
1890 if(sbar_miniscoreboard_size.value > 0)
1891 y = (int) (vid_conheight.integer - sbar_miniscoreboard_size.value * 8);
1896 // decide where to print
1897 if (gamemode == GAME_TRANSFUSION)
1898 numlines = (vid_conwidth.integer - x + 127) / 128;
1900 numlines = (vid_conheight.integer - y + 7) / 8;
1902 // give up if there isn't room
1903 if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1907 for (i = 0; i < scoreboardlines; i++)
1908 if (fragsort[i] == cl.playerentity - 1)
1912 range_end = scoreboardlines;
1915 if (gamemode != GAME_TRANSFUSION)
1916 if (Sbar_IsTeammatch ())
1918 // reserve space for the team scores
1919 numlines -= teamlines;
1921 // find first and last player of my team (only draw the team totals and my own team)
1922 range_begin = range_end = i;
1923 myteam = cl.scores[fragsort[i]].colors & 15;
1924 while(range_begin > 0 && (cl.scores[fragsort[range_begin-1]].colors & 15) == myteam)
1926 while(range_end < scoreboardlines && (cl.scores[fragsort[range_end]].colors & 15) == myteam)
1929 // looks better than two players
1939 i = min(i, range_end - numlines);
1940 i = max(i, range_begin);
1942 if (gamemode == GAME_TRANSFUSION)
1944 for (;i < range_end && x < vid_conwidth.integer;i++)
1945 x += 128 + (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1949 if(range_end - i < numlines) // won't draw to bottom?
1950 y += 8 * (numlines - (range_end - i)); // bottom align
1951 // show team scores first
1952 for (j = 0;j < teamlines && y < vid_conheight.integer;j++)
1953 y += (int)Sbar_PrintScoreboardItem((teams + teamsort[j]), x, y);
1955 for (;i < range_end && y < vid_conheight.integer;i++)
1956 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1960 int Sbar_TeamColorCompare(const void *t1_, const void *t2_)
1962 static int const sortorder[16] =
1981 const scoreboard_t *t1 = *(scoreboard_t **) t1_;
1982 const scoreboard_t *t2 = *(scoreboard_t **) t2_;
1983 int tc1 = sortorder[t1->colors & 15];
1984 int tc2 = sortorder[t2->colors & 15];
1988 void Sbar_Score (int margin)
1990 int i, me, score, otherleader, place, distribution, minutes, seconds;
1992 int sbar_x_save = sbar_x;
1993 int sbar_y_save = sbar_y;
1996 sbar_y = (int) (vid_conheight.value - (32+12));
1999 me = cl.playerentity - 1;
2000 if (sbar_scorerank.integer && me >= 0 && me < cl.maxclients)
2002 if(Sbar_IsTeammatch())
2006 // team1 team3 team4
2010 scoreboard_t *teamcolorsort[16];
2013 for(i = 0; i < teamlines; ++i)
2014 teamcolorsort[i] = &(teams[i]);
2016 // Now sort them by color
2017 qsort(teamcolorsort, teamlines, sizeof(*teamcolorsort), Sbar_TeamColorCompare);
2020 // -12*4: four digits space
2021 place = (teamlines - 1) * (-12 * 4);
2023 for(i = 0; i < teamlines; ++i)
2025 int cindex = teamcolorsort[i]->colors & 15;
2026 unsigned char *c = palette_rgb_shirtscoreboard[cindex];
2027 float cm = max(max(c[0], c[1]), c[2]);
2028 float cr = c[0] / cm;
2029 float cg = c[1] / cm;
2030 float cb = c[2] / cm;
2031 if(cindex == (cl.scores[cl.playerentity - 1].colors & 15)) // my team
2033 Sbar_DrawXNum(-32*4, 0, teamcolorsort[i]->frags, 4, 32, cr, cg, cb, 1, 0);
2037 Sbar_DrawXNum(place, -12, teamcolorsort[i]->frags, 4, 12, cr, cg, cb, 1, 0);
2050 // find leading score other than ourselves, to calculate distribution
2051 // find our place in the scoreboard
2052 score = cl.scores[me].frags;
2053 for (i = 0, otherleader = -1, place = 1;i < cl.maxclients;i++)
2055 if (cl.scores[i].name[0] && i != me)
2057 if (otherleader == -1 || cl.scores[i].frags > cl.scores[otherleader].frags)
2059 if (score < cl.scores[i].frags || (score == cl.scores[i].frags && i < me))
2063 distribution = otherleader >= 0 ? score - cl.scores[otherleader].frags : 0;
2065 Sbar_DrawXNum(-3*12, -12, place, 3, 12, 1, 1, 1, 1, 0);
2066 else if (place == 2)
2067 Sbar_DrawXNum(-3*12, -12, place, 3, 12, 1, 1, 0, 1, 0);
2069 Sbar_DrawXNum(-3*12, -12, place, 3, 12, 1, 0, 0, 1, 0);
2070 if (otherleader < 0)
2071 Sbar_DrawXNum(-32*4, 0, score, 4, 32, 1, 1, 1, 1, 0);
2072 if (distribution >= 0)
2074 Sbar_DrawXNum(-7*12, -12, distribution, 4, 12, 1, 1, 1, 1, 0);
2075 Sbar_DrawXNum(-32*4, 0, score, 4, 32, 1, 1, 1, 1, 0);
2077 else if (distribution >= -5)
2079 Sbar_DrawXNum(-7*12, -12, distribution, 4, 12, 1, 1, 0, 1, 0);
2080 Sbar_DrawXNum(-32*4, 0, score, 4, 32, 1, 1, 0, 1, 0);
2084 Sbar_DrawXNum(-7*12, -12, distribution, 4, 12, 1, 0, 0, 1, 0);
2085 Sbar_DrawXNum(-32*4, 0, score, 4, 32, 1, 0, 0, 1, 0);
2090 if (sbar_gametime.integer && cl.statsf[STAT_TIMELIMIT])
2092 timeleft = max(0, cl.statsf[STAT_TIMELIMIT] * 60 - cl.time);
2093 minutes = (int)floor(timeleft / 60);
2094 seconds = (int)(floor(timeleft) - minutes * 60);
2097 Sbar_DrawXNum(-12*6, 32, minutes, 3, 12, 1, 1, 1, 1, 0);
2098 if(sb_colon && sb_colon->tex != r_texture_notexture)
2099 DrawQ_Pic(sbar_x + -12*3, sbar_y + 32, sb_colon, 12, 12, 1, 1, 1, sbar_alpha_fg.value, 0);
2100 Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
2102 else if (minutes >= 1)
2104 Sbar_DrawXNum(-12*6, 32, minutes, 3, 12, 1, 1, 0, 1, 0);
2105 if(sb_colon && sb_colon->tex != r_texture_notexture)
2106 DrawQ_Pic(sbar_x + -12*3, sbar_y + 32, sb_colon, 12, 12, 1, 1, 0, sbar_alpha_fg.value, 0);
2107 Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 0, 1, 0);
2109 else if ((int)(timeleft * 4) & 1)
2110 Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
2112 Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 0, 0, 1, 0);
2114 else if (sbar_gametime.integer)
2116 minutes = (int)floor(cl.time / 60);
2117 seconds = (int)(floor(cl.time) - minutes * 60);
2118 Sbar_DrawXNum(-12*6, 32, minutes, 3, 12, 1, 1, 1, 1, 0);
2119 if(sb_colon && sb_colon->tex != r_texture_notexture)
2120 DrawQ_Pic(sbar_x + -12*3, sbar_y + 32, sb_colon, 12, 12, 1, 1, 1, sbar_alpha_fg.value, 0);
2121 Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
2124 sbar_x = sbar_x_save;
2125 sbar_y = sbar_y_save;
2130 Sbar_IntermissionOverlay
2134 void Sbar_IntermissionOverlay (void)
2139 if (cl.gametype == GAME_DEATHMATCH)
2141 Sbar_DeathmatchOverlay ();
2145 sbar_x = (vid_conwidth.integer - 320) >> 1;
2146 sbar_y = (vid_conheight.integer - 200) >> 1;
2148 DrawQ_Pic (sbar_x + 64, sbar_y + 24, sb_complete, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
2149 DrawQ_Pic (sbar_x + 0, sbar_y + 56, sb_inter, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
2152 dig = (int)cl.completed_time / 60;
2153 Sbar_DrawNum (160, 64, dig, 3, 0);
2154 num = (int)cl.completed_time - dig*60;
2155 Sbar_DrawPic (234,64,sb_colon);
2156 Sbar_DrawPic (246,64,sb_nums[0][num/10]);
2157 Sbar_DrawPic (266,64,sb_nums[0][num%10]);
2159 // LA: Display as "a" instead of "a/b" if b is 0
2160 if(cl.stats[STAT_TOTALSECRETS])
2162 Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
2163 if (gamemode != GAME_NEXUIZ)
2164 Sbar_DrawPic (232, 104, sb_slash);
2165 Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
2169 Sbar_DrawNum (240, 104, cl.stats[STAT_SECRETS], 3, 0);
2172 if(cl.stats[STAT_TOTALMONSTERS])
2174 Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
2175 if (gamemode != GAME_NEXUIZ)
2176 Sbar_DrawPic (232, 144, sb_slash);
2177 Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
2181 Sbar_DrawNum (240, 144, cl.stats[STAT_MONSTERS], 3, 0);
2192 void Sbar_FinaleOverlay (void)
2194 DrawQ_Pic((vid_conwidth.integer - sb_finale->width)/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);