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 showblur = {CVAR_SAVE, "showblur", "0", "shows the current alpha level of motionblur"};
94 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"};
95 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"};
96 cvar_t showtime = {CVAR_SAVE, "showtime", "0", "shows current time of day (useful on screenshots)"};
97 cvar_t showtime_format = {CVAR_SAVE, "showtime_format", "%H:%M:%S", "format string for time of day"};
98 cvar_t showdate = {CVAR_SAVE, "showdate", "0", "shows current date (useful on screenshots)"};
99 cvar_t showdate_format = {CVAR_SAVE, "showdate_format", "%Y-%m-%d", "format string for date"};
100 cvar_t sbar_alpha_bg = {CVAR_SAVE, "sbar_alpha_bg", "0.4", "opacity value of the statusbar background image"};
101 cvar_t sbar_alpha_fg = {CVAR_SAVE, "sbar_alpha_fg", "1", "opacity value of the statusbar weapon/item icons and numbers"};
102 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)"};
103 cvar_t sbar_scorerank = {CVAR_SAVE, "sbar_scorerank", "1", "shows an overlay for your score (or team score) and rank in the scoreboard"};
104 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)"};
105 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"};
106 cvar_t sbar_flagstatus_right = {CVAR_SAVE, "sbar_flagstatus_right", "0", "moves Nexuiz flag status icons to the right"};
107 cvar_t sbar_flagstatus_pos = {CVAR_SAVE, "sbar_flagstatus_pos", "115", "pixel position of the Nexuiz flag status icons, from the bottom"};
108 cvar_t sbar_info_pos = {CVAR_SAVE, "sbar_info_pos", "0", "pixel position of the info strings (such as showfps), from the bottom"};
110 cvar_t cl_deathscoreboard = {0, "cl_deathscoreboard", "1", "shows scoreboard (+showscores) while dead"};
112 cvar_t crosshair_color_red = {CVAR_SAVE, "crosshair_color_red", "1", "customizable crosshair color"};
113 cvar_t crosshair_color_green = {CVAR_SAVE, "crosshair_color_green", "0", "customizable crosshair color"};
114 cvar_t crosshair_color_blue = {CVAR_SAVE, "crosshair_color_blue", "0", "customizable crosshair color"};
115 cvar_t crosshair_color_alpha = {CVAR_SAVE, "crosshair_color_alpha", "1", "how opaque the crosshair should be"};
116 cvar_t crosshair_size = {CVAR_SAVE, "crosshair_size", "1", "adjusts size of the crosshair on the screen"};
118 void Sbar_MiniDeathmatchOverlay (int x, int y);
119 void Sbar_DeathmatchOverlay (void);
120 void Sbar_IntermissionOverlay (void);
121 void Sbar_FinaleOverlay (void);
123 void CL_VM_UpdateShowingScoresState (int showingscores);
133 void Sbar_ShowScores (void)
137 sb_showscores = true;
138 CL_VM_UpdateShowingScoresState(sb_showscores);
148 void Sbar_DontShowScores (void)
150 sb_showscores = false;
151 CL_VM_UpdateShowingScoresState(sb_showscores);
154 void sbar_start(void)
158 if (gamemode == GAME_DELUXEQUAKE)
161 else if (gamemode == GAME_SOM)
163 sb_disc = Draw_CachePic ("gfx/disc");
165 for (i = 0;i < 10;i++)
166 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i));
168 somsb_health = Draw_CachePic ("gfx/hud_health");
169 somsb_ammo[0] = Draw_CachePic ("gfx/sb_shells");
170 somsb_ammo[1] = Draw_CachePic ("gfx/sb_nails");
171 somsb_ammo[2] = Draw_CachePic ("gfx/sb_rocket");
172 somsb_ammo[3] = Draw_CachePic ("gfx/sb_cells");
173 somsb_armor[0] = Draw_CachePic ("gfx/sb_armor1");
174 somsb_armor[1] = Draw_CachePic ("gfx/sb_armor2");
175 somsb_armor[2] = Draw_CachePic ("gfx/sb_armor3");
177 else if (gamemode == GAME_NEXUIZ)
179 for (i = 0;i < 10;i++)
180 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i));
181 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus");
182 sb_colon = Draw_CachePic ("gfx/num_colon");
184 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells");
185 sb_ammo[1] = Draw_CachePic ("gfx/sb_bullets");
186 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket");
187 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells");
189 sb_armor[0] = Draw_CachePic ("gfx/sb_armor");
193 sb_health = Draw_CachePic ("gfx/sb_health");
195 sb_items[2] = Draw_CachePic ("gfx/sb_slowmo");
196 sb_items[3] = Draw_CachePic ("gfx/sb_invinc");
197 sb_items[4] = Draw_CachePic ("gfx/sb_energy");
198 sb_items[5] = Draw_CachePic ("gfx/sb_str");
200 sb_items[11] = Draw_CachePic ("gfx/sb_flag_red_taken");
201 sb_items[12] = Draw_CachePic ("gfx/sb_flag_red_lost");
202 sb_items[13] = Draw_CachePic ("gfx/sb_flag_red_carrying");
203 sb_items[14] = Draw_CachePic ("gfx/sb_key_carrying");
204 sb_items[15] = Draw_CachePic ("gfx/sb_flag_blue_taken");
205 sb_items[16] = Draw_CachePic ("gfx/sb_flag_blue_lost");
206 sb_items[17] = Draw_CachePic ("gfx/sb_flag_blue_carrying");
208 sb_sbar = Draw_CachePic ("gfx/sbar");
209 sb_sbar_minimal = Draw_CachePic ("gfx/sbar_minimal");
210 sb_sbar_overlay = Draw_CachePic ("gfx/sbar_overlay");
212 for(i = 0; i < 9;i++)
213 sb_weapons[0][i] = Draw_CachePic (va("gfx/inv_weapon%i",i));
215 else if (gamemode == GAME_ZYMOTIC)
217 zymsb_crosshair_center = Draw_CachePic ("gfx/hud/crosshair_center");
218 zymsb_crosshair_line = Draw_CachePic ("gfx/hud/crosshair_line");
219 zymsb_crosshair_health = Draw_CachePic ("gfx/hud/crosshair_health");
220 zymsb_crosshair_clip = Draw_CachePic ("gfx/hud/crosshair_clip");
221 zymsb_crosshair_ammo = Draw_CachePic ("gfx/hud/crosshair_ammo");
222 zymsb_crosshair_background = Draw_CachePic ("gfx/hud/crosshair_background");
223 zymsb_crosshair_left1 = Draw_CachePic ("gfx/hud/crosshair_left1");
224 zymsb_crosshair_left2 = Draw_CachePic ("gfx/hud/crosshair_left2");
225 zymsb_crosshair_right = Draw_CachePic ("gfx/hud/crosshair_right");
229 sb_disc = Draw_CachePic ("gfx/disc");
231 for (i = 0;i < 10;i++)
233 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i));
234 sb_nums[1][i] = Draw_CachePic (va("gfx/anum_%i",i));
237 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus");
238 sb_nums[1][10] = Draw_CachePic ("gfx/anum_minus");
240 sb_colon = Draw_CachePic ("gfx/num_colon");
241 sb_slash = Draw_CachePic ("gfx/num_slash");
243 sb_weapons[0][0] = Draw_CachePic ("gfx/inv_shotgun");
244 sb_weapons[0][1] = Draw_CachePic ("gfx/inv_sshotgun");
245 sb_weapons[0][2] = Draw_CachePic ("gfx/inv_nailgun");
246 sb_weapons[0][3] = Draw_CachePic ("gfx/inv_snailgun");
247 sb_weapons[0][4] = Draw_CachePic ("gfx/inv_rlaunch");
248 sb_weapons[0][5] = Draw_CachePic ("gfx/inv_srlaunch");
249 sb_weapons[0][6] = Draw_CachePic ("gfx/inv_lightng");
251 sb_weapons[1][0] = Draw_CachePic ("gfx/inv2_shotgun");
252 sb_weapons[1][1] = Draw_CachePic ("gfx/inv2_sshotgun");
253 sb_weapons[1][2] = Draw_CachePic ("gfx/inv2_nailgun");
254 sb_weapons[1][3] = Draw_CachePic ("gfx/inv2_snailgun");
255 sb_weapons[1][4] = Draw_CachePic ("gfx/inv2_rlaunch");
256 sb_weapons[1][5] = Draw_CachePic ("gfx/inv2_srlaunch");
257 sb_weapons[1][6] = Draw_CachePic ("gfx/inv2_lightng");
259 for (i = 0;i < 5;i++)
261 sb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_shotgun",i+1));
262 sb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_sshotgun",i+1));
263 sb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_nailgun",i+1));
264 sb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_snailgun",i+1));
265 sb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_rlaunch",i+1));
266 sb_weapons[2+i][5] = Draw_CachePic (va("gfx/inva%i_srlaunch",i+1));
267 sb_weapons[2+i][6] = Draw_CachePic (va("gfx/inva%i_lightng",i+1));
270 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells");
271 sb_ammo[1] = Draw_CachePic ("gfx/sb_nails");
272 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket");
273 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells");
275 sb_armor[0] = Draw_CachePic ("gfx/sb_armor1");
276 sb_armor[1] = Draw_CachePic ("gfx/sb_armor2");
277 sb_armor[2] = Draw_CachePic ("gfx/sb_armor3");
279 sb_items[0] = Draw_CachePic ("gfx/sb_key1");
280 sb_items[1] = Draw_CachePic ("gfx/sb_key2");
281 sb_items[2] = Draw_CachePic ("gfx/sb_invis");
282 sb_items[3] = Draw_CachePic ("gfx/sb_invuln");
283 sb_items[4] = Draw_CachePic ("gfx/sb_suit");
284 sb_items[5] = Draw_CachePic ("gfx/sb_quad");
286 sb_sigil[0] = Draw_CachePic ("gfx/sb_sigil1");
287 sb_sigil[1] = Draw_CachePic ("gfx/sb_sigil2");
288 sb_sigil[2] = Draw_CachePic ("gfx/sb_sigil3");
289 sb_sigil[3] = Draw_CachePic ("gfx/sb_sigil4");
291 sb_faces[4][0] = Draw_CachePic ("gfx/face1");
292 sb_faces[4][1] = Draw_CachePic ("gfx/face_p1");
293 sb_faces[3][0] = Draw_CachePic ("gfx/face2");
294 sb_faces[3][1] = Draw_CachePic ("gfx/face_p2");
295 sb_faces[2][0] = Draw_CachePic ("gfx/face3");
296 sb_faces[2][1] = Draw_CachePic ("gfx/face_p3");
297 sb_faces[1][0] = Draw_CachePic ("gfx/face4");
298 sb_faces[1][1] = Draw_CachePic ("gfx/face_p4");
299 sb_faces[0][0] = Draw_CachePic ("gfx/face5");
300 sb_faces[0][1] = Draw_CachePic ("gfx/face_p5");
302 sb_face_invis = Draw_CachePic ("gfx/face_invis");
303 sb_face_invuln = Draw_CachePic ("gfx/face_invul2");
304 sb_face_invis_invuln = Draw_CachePic ("gfx/face_inv2");
305 sb_face_quad = Draw_CachePic ("gfx/face_quad");
307 sb_sbar = Draw_CachePic ("gfx/sbar");
308 sb_ibar = Draw_CachePic ("gfx/ibar");
309 sb_scorebar = Draw_CachePic ("gfx/scorebar");
311 //MED 01/04/97 added new hipnotic weapons
312 if (gamemode == GAME_HIPNOTIC)
314 hsb_weapons[0][0] = Draw_CachePic ("gfx/inv_laser");
315 hsb_weapons[0][1] = Draw_CachePic ("gfx/inv_mjolnir");
316 hsb_weapons[0][2] = Draw_CachePic ("gfx/inv_gren_prox");
317 hsb_weapons[0][3] = Draw_CachePic ("gfx/inv_prox_gren");
318 hsb_weapons[0][4] = Draw_CachePic ("gfx/inv_prox");
320 hsb_weapons[1][0] = Draw_CachePic ("gfx/inv2_laser");
321 hsb_weapons[1][1] = Draw_CachePic ("gfx/inv2_mjolnir");
322 hsb_weapons[1][2] = Draw_CachePic ("gfx/inv2_gren_prox");
323 hsb_weapons[1][3] = Draw_CachePic ("gfx/inv2_prox_gren");
324 hsb_weapons[1][4] = Draw_CachePic ("gfx/inv2_prox");
326 for (i = 0;i < 5;i++)
328 hsb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_laser",i+1));
329 hsb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_mjolnir",i+1));
330 hsb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_gren_prox",i+1));
331 hsb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_prox_gren",i+1));
332 hsb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_prox",i+1));
335 hsb_items[0] = Draw_CachePic ("gfx/sb_wsuit");
336 hsb_items[1] = Draw_CachePic ("gfx/sb_eshld");
338 else if (gamemode == GAME_ROGUE)
340 rsb_invbar[0] = Draw_CachePic ("gfx/r_invbar1");
341 rsb_invbar[1] = Draw_CachePic ("gfx/r_invbar2");
343 rsb_weapons[0] = Draw_CachePic ("gfx/r_lava");
344 rsb_weapons[1] = Draw_CachePic ("gfx/r_superlava");
345 rsb_weapons[2] = Draw_CachePic ("gfx/r_gren");
346 rsb_weapons[3] = Draw_CachePic ("gfx/r_multirock");
347 rsb_weapons[4] = Draw_CachePic ("gfx/r_plasma");
349 rsb_items[0] = Draw_CachePic ("gfx/r_shield1");
350 rsb_items[1] = Draw_CachePic ("gfx/r_agrav1");
352 // PGM 01/19/97 - team color border
353 rsb_teambord = Draw_CachePic ("gfx/r_teambord");
354 // PGM 01/19/97 - team color border
356 rsb_ammo[0] = Draw_CachePic ("gfx/r_ammolava");
357 rsb_ammo[1] = Draw_CachePic ("gfx/r_ammomulti");
358 rsb_ammo[2] = Draw_CachePic ("gfx/r_ammoplasma");
362 sb_ranking = Draw_CachePic ("gfx/ranking");
363 sb_complete = Draw_CachePic ("gfx/complete");
364 sb_inter = Draw_CachePic ("gfx/inter");
365 sb_finale = Draw_CachePic ("gfx/finale");
368 void sbar_shutdown(void)
372 void sbar_newmap(void)
376 void Sbar_Init (void)
378 Cmd_AddCommand("+showscores", Sbar_ShowScores, "show scoreboard");
379 Cmd_AddCommand("-showscores", Sbar_DontShowScores, "hide scoreboard");
380 Cvar_RegisterVariable(&showfps);
381 Cvar_RegisterVariable(&showsound);
382 Cvar_RegisterVariable(&showblur);
383 Cvar_RegisterVariable(&showspeed);
384 Cvar_RegisterVariable(&showtopspeed);
385 Cvar_RegisterVariable(&showtime);
386 Cvar_RegisterVariable(&showtime_format);
387 Cvar_RegisterVariable(&showdate);
388 Cvar_RegisterVariable(&showdate_format);
389 Cvar_RegisterVariable(&sbar_alpha_bg);
390 Cvar_RegisterVariable(&sbar_alpha_fg);
391 Cvar_RegisterVariable(&sbar_hudselector);
392 Cvar_RegisterVariable(&sbar_scorerank);
393 Cvar_RegisterVariable(&sbar_gametime);
394 Cvar_RegisterVariable(&sbar_miniscoreboard_size);
395 Cvar_RegisterVariable(&sbar_info_pos);
396 Cvar_RegisterVariable(&cl_deathscoreboard);
398 Cvar_RegisterVariable(&crosshair_color_red);
399 Cvar_RegisterVariable(&crosshair_color_green);
400 Cvar_RegisterVariable(&crosshair_color_blue);
401 Cvar_RegisterVariable(&crosshair_color_alpha);
402 Cvar_RegisterVariable(&crosshair_size);
404 if(gamemode == GAME_NEXUIZ)
406 Cvar_RegisterVariable(&sbar_flagstatus_right); // this cvar makes no sense in other games
407 Cvar_RegisterVariable(&sbar_flagstatus_pos); // this cvar makes no sense in other games
410 R_RegisterModule("sbar", sbar_start, sbar_shutdown, sbar_newmap);
414 //=============================================================================
416 // drawing routines are relative to the status bar location
425 void Sbar_DrawStretchPic (int x, int y, cachepic_t *pic, float alpha, float overridewidth, float overrideheight)
427 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, overridewidth, overrideheight, 1, 1, 1, alpha, 0);
430 void Sbar_DrawPic (int x, int y, cachepic_t *pic)
432 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, sbar_alpha_fg.value, 0);
435 void Sbar_DrawAlphaPic (int x, int y, cachepic_t *pic, float alpha)
437 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, alpha, 0);
444 Draws one solid graphics character
447 void Sbar_DrawCharacter (int x, int y, int num)
449 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);
457 void Sbar_DrawString (int x, int y, char *str)
459 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);
467 void Sbar_DrawNum (int x, int y, int num, int digits, int color)
472 l = dpsnprintf(str, sizeof(str), "%i", num);
486 Sbar_DrawPic (x, y, sb_nums[color][frame]);
499 void Sbar_DrawXNum (int x, int y, int num, int digits, int lettersize, float r, float g, float b, float a, int flags)
507 l = dpsnprintf(str, sizeof(str), "%0*i", digits, num);
510 l = dpsnprintf(str, sizeof(str), "%i", num);
515 x += (digits-l) * lettersize;
524 DrawQ_Pic (sbar_x + x, sbar_y + y, sb_nums[0][frame],lettersize,lettersize,r,g,b,a * sbar_alpha_fg.value,flags);
531 //=============================================================================
534 int Sbar_IsTeammatch(void)
536 // currently only nexuiz uses the team score board
537 return ((gamemode == GAME_NEXUIZ)
538 && (teamplay.integer > 0));
546 static int fragsort[MAX_SCOREBOARD];
547 static int scoreboardlines;
549 int Sbar_GetSortedPlayerIndex (int index)
551 return index >= 0 && index < scoreboardlines ? fragsort[index] : -1;
554 static scoreboard_t teams[MAX_SCOREBOARD];
555 static int teamsort[MAX_SCOREBOARD];
556 static int teamlines;
557 void Sbar_SortFrags (void)
563 for (i=0 ; i<cl.maxclients ; i++)
565 if (cl.scores[i].name[0])
567 fragsort[scoreboardlines] = i;
572 for (i=0 ; i<scoreboardlines ; i++)
573 for (j=0 ; j<scoreboardlines-1-i ; j++)
574 if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j+1]].frags)
577 fragsort[j] = fragsort[j+1];
582 if (Sbar_IsTeammatch ())
584 // now sort players by teams.
585 for (i=0 ; i<scoreboardlines ; i++)
587 for (j=0 ; j<scoreboardlines-1-i ; j++)
589 if (cl.scores[fragsort[j]].colors < cl.scores[fragsort[j+1]].colors)
592 fragsort[j] = fragsort[j+1];
598 // calculate team scores
600 for (i=0 ; i<scoreboardlines ; i++)
602 if (color != (cl.scores[fragsort[i]].colors & 15))
604 const char* teamname;
606 color = cl.scores[fragsort[i]].colors & 15;
612 teamname = "^1Red Team";
615 teamname = "^4Blue Team";
618 teamname = "^6Pink Team";
621 teamname = "^3Yellow Team";
624 teamname = "Total Team Score";
627 strlcpy(teams[teamlines-1].name, teamname, sizeof(teams[teamlines-1].name));
629 teams[teamlines-1].frags = 0;
630 teams[teamlines-1].colors = color + 16 * color;
633 if (cl.scores[fragsort[i]].frags != -666)
635 // do not add spedcators
636 // (ugly hack for nexuiz)
637 teams[teamlines-1].frags += cl.scores[fragsort[i]].frags;
641 // now sort teams by scores.
642 for (i=0 ; i<teamlines ; i++)
644 for (i=0 ; i<teamlines ; i++)
646 for (j=0 ; j<teamlines-1-i ; j++)
648 if (teams[teamsort[j]].frags < teams[teamsort[j+1]].frags)
651 teamsort[j] = teamsort[j+1];
664 void Sbar_SoloScoreboard (void)
667 char str[80], timestr[40];
669 int minutes, seconds;
672 t = (cl.intermission ? cl.completed_time : cl.time);
673 minutes = (int)(t / 60);
674 seconds = (int)(t - 60*floor(t/60));
676 // monsters and secrets are now both on the top row
677 if (cl.stats[STAT_TOTALMONSTERS])
678 Sbar_DrawString(8, 4, va("Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]));
679 else if (cl.stats[STAT_MONSTERS]) // LA: Display something if monsters_killed is non-zero, but total_monsters is zero
680 Sbar_DrawString(8, 4, va("Monsters:%3i", cl.stats[STAT_MONSTERS]));
682 if (cl.stats[STAT_TOTALSECRETS])
683 Sbar_DrawString(8+22*8, 4, va("Secrets:%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]));
684 else if (cl.stats[STAT_SECRETS]) // LA: And similarly for secrets
685 Sbar_DrawString(8+22*8, 4, va("Secrets:%3i", cl.stats[STAT_SECRETS]));
687 // figure out the map's filename without path or extension
688 strlcpy(str, FS_FileWithoutPath(cl.worldmodel ? cl.worldmodel->name : ""), sizeof(str));
689 if (strrchr(str, '.'))
690 *(strrchr(str, '.')) = 0;
692 // append a : separator and then the full title
693 strlcat(str, ":", sizeof(str));
694 strlcat(str, cl.levelname, sizeof(str));
696 // if there's a newline character, terminate the string there
697 if (strchr(str, '\n'))
698 *(strchr(str, '\n')) = 0;
700 // make the time string
701 timelen = dpsnprintf(timestr, sizeof(timestr), " %i:%02i", minutes, seconds);
703 // truncate the level name if necessary to make room for time
705 if ((int)strlen(str) > max)
708 // print the filename and message
709 Sbar_DrawString(8, 12, str);
712 Sbar_DrawString(8 + max*8, 12, timestr);
716 int minutes, seconds, tens, units;
719 if (gamemode != GAME_NEXUIZ) {
720 dpsnprintf (str, sizeof(str), "Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
721 Sbar_DrawString (8, 4, str);
723 dpsnprintf (str, sizeof(str), "Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
724 Sbar_DrawString (8, 12, str);
728 minutes = (int)(cl.time / 60);
729 seconds = (int)(cl.time - 60*minutes);
731 units = seconds - 10*tens;
732 dpsnprintf (str, sizeof(str), "Time :%3i:%i%i", minutes, tens, units);
733 Sbar_DrawString (184, 4, str);
736 if (gamemode == GAME_NEXUIZ) {
737 l = (int) strlen (cl.worldmodel->name);
738 Sbar_DrawString (232 - l*4, 12, cl.worldmodel->name);
740 l = (int) strlen (cl.levelname);
741 Sbar_DrawString (232 - l*4, 12, cl.levelname);
751 void Sbar_DrawScoreboard (void)
753 Sbar_SoloScoreboard ();
754 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
755 //if (cl.gametype == GAME_DEATHMATCH)
757 Sbar_DeathmatchOverlay ();
760 //=============================================================================
762 // AK to make DrawInventory smaller
763 static void Sbar_DrawWeapon(int nr, float fade, int active)
765 if (sbar_hudselector.integer == 1)
767 // width = 300, height = 100
768 const int w_width = 32, w_height = 12, w_space = 2, font_size = 8;
770 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);
772 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);
776 // width = 300, height = 100
777 const int w_width = 300, w_height = 100, w_space = 10;
778 const float w_scale = 0.4;
780 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);
781 //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);
790 void Sbar_DrawInventory (void)
797 if (gamemode == GAME_ROGUE)
799 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
800 Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], sbar_alpha_bg.value);
802 Sbar_DrawAlphaPic (0, -24, rsb_invbar[1], sbar_alpha_bg.value);
805 Sbar_DrawAlphaPic (0, -24, sb_ibar, sbar_alpha_bg.value);
808 for (i=0 ; i<7 ; i++)
810 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<i) )
812 time = cl.item_gettime[i];
813 flashon = (int)(max(0, cl.time - time)*10);
816 if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i) )
822 flashon = (flashon%5) + 2;
824 Sbar_DrawAlphaPic (i*24, -16, sb_weapons[flashon][i], sbar_alpha_bg.value);
830 if (gamemode == GAME_HIPNOTIC)
832 int grenadeflashing=0;
833 for (i=0 ; i<4 ; i++)
835 if (cl.stats[STAT_ITEMS] & (1<<hipweapons[i]) )
837 time = max(0, cl.item_gettime[hipweapons[i]]);
838 flashon = (int)((cl.time - time)*10);
841 if ( cl.stats[STAT_ACTIVEWEAPON] == (1<<hipweapons[i]) )
847 flashon = (flashon%5) + 2;
849 // check grenade launcher
852 if (cl.stats[STAT_ITEMS] & HIT_PROXIMITY_GUN)
857 Sbar_DrawPic (96, -16, hsb_weapons[flashon][2]);
863 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<4))
865 if (!grenadeflashing)
866 Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
869 Sbar_DrawPic (96, -16, hsb_weapons[flashon][4]);
872 Sbar_DrawPic (176 + (i*24), -16, hsb_weapons[flashon][i]);
877 if (gamemode == GAME_ROGUE)
879 // check for powered up weapon.
880 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
882 if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i))
883 Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]);
887 for (i=0 ; i<4 ; i++)
889 dpsnprintf (num, sizeof(num), "%4i",cl.stats[STAT_SHELLS+i] );
891 Sbar_DrawCharacter ( (6*i+0)*8 - 2, -24, 18 + num[0] - '0');
893 Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[1] - '0');
895 Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[2] - '0');
897 Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[3] - '0');
901 for (i=0 ; i<6 ; i++)
902 if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
904 //MED 01/04/97 changed keys
905 if (gamemode != GAME_HIPNOTIC || (i>1))
906 Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
909 //MED 01/04/97 added hipnotic items
911 if (gamemode == GAME_HIPNOTIC)
913 for (i=0 ; i<2 ; i++)
914 if (cl.stats[STAT_ITEMS] & (1<<(24+i)))
915 Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
918 if (gamemode == GAME_ROGUE)
921 for (i=0 ; i<2 ; i++)
922 if (cl.stats[STAT_ITEMS] & (1<<(29+i)))
923 Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
928 for (i=0 ; i<4 ; i++)
929 if (cl.stats[STAT_ITEMS] & (1<<(28+i)))
930 Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
934 //=============================================================================
941 void Sbar_DrawFrags (void)
951 l = min(scoreboardlines, 4);
955 for (i = 0;i < l;i++)
961 c = palette_rgb_pantsscoreboard[(s->colors & 0xf0) >> 4];
962 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);
963 c = palette_rgb_shirtscoreboard[s->colors & 0xf];
964 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);
968 dpsnprintf (num, sizeof(num), "%3i",f);
970 if (k == cl.viewentity - 1)
972 Sbar_DrawCharacter ( x + 2, -24, 16);
973 Sbar_DrawCharacter ( x + 32 - 4, -24, 17);
975 Sbar_DrawCharacter (x + 8, -24, num[0]);
976 Sbar_DrawCharacter (x + 16, -24, num[1]);
977 Sbar_DrawCharacter (x + 24, -24, num[2]);
982 //=============================================================================
990 void Sbar_DrawFace (void)
994 // PGM 01/19/97 - team color drawing
995 // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
996 if (gamemode == GAME_ROGUE && !cl.islocalgame && (teamplay.integer > 3) && (teamplay.integer < 7))
1002 s = &cl.scores[cl.viewentity - 1];
1004 Sbar_DrawPic (112, 0, rsb_teambord);
1005 c = palette_rgb_pantsscoreboard[(s->colors & 0xf0) >> 4];
1006 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);
1007 c = palette_rgb_shirtscoreboard[s->colors & 0xf];
1008 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);
1012 dpsnprintf (num, sizeof(num), "%3i",f);
1014 if ((s->colors & 0xf0)==0)
1017 Sbar_DrawCharacter(109, 3, 18 + num[0] - '0');
1019 Sbar_DrawCharacter(116, 3, 18 + num[1] - '0');
1021 Sbar_DrawCharacter(123, 3, 18 + num[2] - '0');
1025 Sbar_DrawCharacter ( 109, 3, num[0]);
1026 Sbar_DrawCharacter ( 116, 3, num[1]);
1027 Sbar_DrawCharacter ( 123, 3, num[2]);
1032 // PGM 01/19/97 - team color drawing
1034 if ( (cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
1035 Sbar_DrawPic (112, 0, sb_face_invis_invuln);
1036 else if (cl.stats[STAT_ITEMS] & IT_QUAD)
1037 Sbar_DrawPic (112, 0, sb_face_quad );
1038 else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
1039 Sbar_DrawPic (112, 0, sb_face_invis );
1040 else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1041 Sbar_DrawPic (112, 0, sb_face_invuln);
1044 f = cl.stats[STAT_HEALTH] / 20;
1046 Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]);
1049 double topspeed = 0;
1050 double topspeedxy = 0;
1051 time_t current_time = 3;
1052 time_t top_time = 0;
1053 time_t topxy_time = 0;
1055 static void get_showspeed_unit(int unitnumber, double *conversion_factor, const char **unit)
1058 unitnumber = showspeed.integer;
1063 if(gamemode == GAME_NEXUIZ)
1067 *conversion_factor = 1.0;
1071 *conversion_factor = 0.0254;
1072 if(gamemode != GAME_NEXUIZ) *conversion_factor *= 1.5;
1073 // 1qu=1.5in is for non-Nexuiz only - Nexuiz players are overly large, but 1qu=1in fixes that
1077 *conversion_factor = 0.0254 * 3.6;
1078 if(gamemode != GAME_NEXUIZ) *conversion_factor *= 1.5;
1082 *conversion_factor = 0.0254 * 3.6 * 0.6213711922;
1083 if(gamemode != GAME_NEXUIZ) *conversion_factor *= 1.5;
1087 *conversion_factor = 0.0254 * 1.943844492; // 1 m/s = 1.943844492 knots, because 1 knot = 1.852 km/h
1088 if(gamemode != GAME_NEXUIZ) *conversion_factor *= 1.5;
1093 static double showfps_nexttime = 0, showfps_lasttime = -1;
1094 static double showfps_framerate = 0;
1095 static int showfps_framecount = 0;
1097 void Sbar_ShowFPS_Update(void)
1099 double interval = 1;
1102 if (newtime >= showfps_nexttime)
1104 showfps_framerate = showfps_framecount / (newtime - showfps_lasttime);
1105 if (showfps_nexttime < newtime - interval * 1.5)
1106 showfps_nexttime = newtime;
1107 showfps_lasttime = newtime;
1108 showfps_nexttime += interval;
1109 showfps_framecount = 0;
1111 showfps_framecount++;
1114 void Sbar_ShowFPS(void)
1116 float fps_x, fps_y, fps_scalex, fps_scaley, fps_height;
1117 char soundstring[32];
1119 char timestring[32];
1120 char datestring[32];
1121 char timedemostring1[32];
1122 char timedemostring2[32];
1123 char speedstring[32];
1124 char blurstring[32];
1125 char topspeedstring[48];
1126 qboolean red = false;
1129 timedemostring1[0] = 0;
1130 timedemostring2[0] = 0;
1135 topspeedstring[0] = 0;
1136 if (showfps.integer)
1138 red = (showfps_framerate < 1.0f);
1139 if(showfps.integer == 2)
1140 dpsnprintf(fpsstring, sizeof(fpsstring), "%7.3f mspf", (1000.0 / showfps_framerate));
1142 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0 / showfps_framerate + 0.5));
1144 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(showfps_framerate + 0.5));
1147 dpsnprintf(timedemostring1, sizeof(timedemostring1), "frame%4i %f", cls.td_frames, realtime - cls.td_starttime);
1148 dpsnprintf(timedemostring2, sizeof(timedemostring2), "%i seconds %3.0f/%3.0f/%3.0f fps", cls.td_onesecondavgcount, cls.td_onesecondminfps, cls.td_onesecondavgfps / max(1, cls.td_onesecondavgcount), cls.td_onesecondmaxfps);
1151 if (showtime.integer)
1152 strlcpy(timestring, Sys_TimeString(showtime_format.string), sizeof(timestring));
1153 if (showdate.integer)
1154 strlcpy(datestring, Sys_TimeString(showdate_format.string), sizeof(datestring));
1155 if (showblur.integer)
1156 dpsnprintf(blurstring, sizeof(blurstring), "%3i%% blur", (int)(cl.motionbluralpha * 100));
1157 if (showsound.integer)
1158 dpsnprintf(soundstring, sizeof(soundstring), "%4i/4%i at %3ims", cls.soundstats.mixedsounds, cls.soundstats.totalsounds, cls.soundstats.latency_milliseconds);
1159 if (showspeed.integer || showtopspeed.integer)
1161 double speed, speedxy, f;
1163 speed = VectorLength(cl.movement_velocity);
1164 speedxy = sqrt(cl.movement_velocity[0] * cl.movement_velocity[0] + cl.movement_velocity[1] * cl.movement_velocity[1]);
1165 if (showspeed.integer)
1167 get_showspeed_unit(showspeed.integer, &f, &unit);
1168 dpsnprintf(speedstring, sizeof(speedstring), "%.0f (%.0f) %s", f*speed, f*speedxy, unit);
1170 if (showtopspeed.integer)
1172 qboolean topspeed_latched = false, topspeedxy_latched = false;
1173 get_showspeed_unit(showtopspeed.integer, &f, &unit);
1174 if (speed >= topspeed || current_time - top_time > 3)
1180 topspeed_latched = true;
1181 if (speedxy >= topspeedxy || current_time - topxy_time > 3)
1183 topspeedxy = speedxy;
1187 topspeedxy_latched = true;
1188 dpsnprintf(topspeedstring, sizeof(topspeedstring), "%s%.0f%s (%s%.0f%s) %s",
1189 topspeed_latched ? "^1" : "^xf88", f*topspeed, "^xf88",
1190 topspeedxy_latched ? "^1" : "^xf88", f*topspeedxy, "^xf88",
1192 time(¤t_time);
1195 if (fpsstring[0] || timedemostring1[0] || timedemostring2[0] || timestring[0] || datestring[0] || speedstring[0] || blurstring[0] || topspeedstring[0])
1199 fps_height = fps_scaley * ((soundstring[0] != 0) + (blurstring[0] != 0) + (fpsstring[0] != 0) + (timedemostring1[0] != 0) + (timedemostring2[0] != 0) + (timestring[0] != 0) + (datestring[0] != 0) + (speedstring[0] != 0) + (topspeedstring[0] != 0));
1200 //fps_y = vid_conheight.integer - sb_lines; // yes this may draw over the sbar
1201 //fps_y = bound(0, fps_y, vid_conheight.integer - fps_height);
1202 fps_y = vid_conheight.integer - sbar_info_pos.integer - fps_height;
1205 fps_x = vid_conwidth.integer - DrawQ_TextWidth_Font(soundstring, 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, soundstring, 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(fpsstring, 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);
1215 DrawQ_String_Font(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 0, 0, 1, 0, NULL, true, FONT_INFOBAR);
1217 DrawQ_String_Font(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1218 fps_y += fps_scaley;
1220 if (timedemostring1[0])
1222 fps_x = vid_conwidth.integer - DrawQ_TextWidth_Font(timedemostring1, 0, true, FONT_INFOBAR) * fps_scalex;
1223 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1224 DrawQ_String_Font(fps_x, fps_y, timedemostring1, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1225 fps_y += fps_scaley;
1227 if (timedemostring2[0])
1229 fps_x = vid_conwidth.integer - DrawQ_TextWidth_Font(timedemostring2, 0, true, FONT_INFOBAR) * fps_scalex;
1230 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1231 DrawQ_String_Font(fps_x, fps_y, timedemostring2, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1232 fps_y += fps_scaley;
1236 fps_x = vid_conwidth.integer - DrawQ_TextWidth_Font(timestring, 0, true, FONT_INFOBAR) * fps_scalex;
1237 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1238 DrawQ_String_Font(fps_x, fps_y, timestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1239 fps_y += fps_scaley;
1243 fps_x = vid_conwidth.integer - DrawQ_TextWidth_Font(datestring, 0, true, FONT_INFOBAR) * fps_scalex;
1244 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1245 DrawQ_String_Font(fps_x, fps_y, datestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1246 fps_y += fps_scaley;
1250 fps_x = vid_conwidth.integer - DrawQ_TextWidth_Font(speedstring, 0, true, FONT_INFOBAR) * fps_scalex;
1251 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1252 DrawQ_String_Font(fps_x, fps_y, speedstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1253 fps_y += fps_scaley;
1255 if (topspeedstring[0])
1257 fps_x = vid_conwidth.integer - DrawQ_TextWidth_Font(topspeedstring, 0, false, FONT_INFOBAR) * fps_scalex;
1258 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1259 DrawQ_String_Font(fps_x, fps_y, topspeedstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, false, FONT_INFOBAR);
1260 fps_y += fps_scaley;
1264 fps_x = vid_conwidth.integer - DrawQ_TextWidth_Font(blurstring, 0, true, FONT_INFOBAR) * fps_scalex;
1265 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1266 DrawQ_String_Font(fps_x, fps_y, blurstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1267 fps_y += fps_scaley;
1272 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)
1275 c2 = bound(0, c2, 1);
1276 c1 = bound(0, c1, 1 - c2);
1278 r[1] = rangey + rangeheight * (c2 + c1);
1279 r[2] = rangey + rangeheight * (c2);
1283 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);
1285 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);
1287 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);
1289 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);
1297 extern float v_dmg_time, v_dmg_roll, v_dmg_pitch;
1298 extern cvar_t v_kicktime;
1299 void Sbar_Score (int margin);
1300 void Sbar_Draw (void)
1304 if(cl.csqc_vidvars.drawenginesbar) //[515]: csqc drawsbar
1307 Sbar_DrawScoreboard ();
1308 else if (cl.intermission == 1)
1310 if(gamemode == GAME_NEXUIZ) // display full scoreboard (that is, show scores + map name)
1312 Sbar_DrawScoreboard();
1315 Sbar_IntermissionOverlay();
1317 else if (cl.intermission == 2)
1318 Sbar_FinaleOverlay();
1319 else if (gamemode == GAME_DELUXEQUAKE)
1322 else if (gamemode == GAME_SOM)
1324 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1325 Sbar_DrawScoreboard ();
1328 // this is the top left of the sbar area
1330 sbar_y = vid_conheight.integer - 24*3;
1333 if (cl.stats[STAT_ARMOR])
1335 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1336 Sbar_DrawPic(0, 0, somsb_armor[2]);
1337 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1338 Sbar_DrawPic(0, 0, somsb_armor[1]);
1339 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1340 Sbar_DrawPic(0, 0, somsb_armor[0]);
1341 Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1345 Sbar_DrawPic(0, 24, somsb_health);
1346 Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1349 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1350 Sbar_DrawPic(0, 48, somsb_ammo[0]);
1351 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1352 Sbar_DrawPic(0, 48, somsb_ammo[1]);
1353 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1354 Sbar_DrawPic(0, 48, somsb_ammo[2]);
1355 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1356 Sbar_DrawPic(0, 48, somsb_ammo[3]);
1357 Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
1358 if (cl.stats[STAT_SHELLS])
1359 Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
1362 else if (gamemode == GAME_NEXUIZ)
1364 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1366 sbar_x = (vid_conwidth.integer - 640)/2;
1367 sbar_y = vid_conheight.integer - 47;
1368 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1369 Sbar_DrawScoreboard ();
1371 else if (sb_lines && sbar_hudselector.integer == 1)
1375 int redflag, blueflag;
1378 sbar_x = (vid_conwidth.integer - 320)/2;
1379 sbar_y = vid_conheight.integer - 24 - 16;
1381 // calculate intensity to draw weapons bar at
1382 fade = 3.2 - 2 * (cl.time - cl.weapontime);
1383 fade = bound(0.7, fade, 1);
1384 for (i = 0; i < 8;i++)
1385 if (cl.stats[STAT_ITEMS] & (1 << i))
1386 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1387 if((cl.stats[STAT_ITEMS] & (1<<12)))
1388 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1391 redflag = ((cl.stats[STAT_ITEMS]>>15) & 3);
1392 blueflag = ((cl.stats[STAT_ITEMS]>>17) & 3);
1393 x = sbar_flagstatus_right.integer ? vid_conwidth.integer - 10 - sbar_x - 64 : 10 - sbar_x;
1394 if (redflag == 3 && blueflag == 3)
1396 // The Impossible Combination[tm]
1397 // Can only happen in Key Hunt mode...
1398 Sbar_DrawPic ((int) x, (int) ((vid_conheight.integer - sbar_y) - (sbar_flagstatus_pos.value + 128)), sb_items[14]);
1403 Sbar_DrawPic ((int) x, (int) ((vid_conheight.integer - sbar_y) - (sbar_flagstatus_pos.value + 64)), sb_items[redflag+10]);
1405 Sbar_DrawPic ((int) x, (int) ((vid_conheight.integer - sbar_y) - (sbar_flagstatus_pos.value + 128)), sb_items[blueflag+14]);
1409 if (cl.stats[STAT_ARMOR] > 0)
1411 Sbar_DrawStretchPic (72, 0, sb_armor[0], sbar_alpha_fg.value, 24, 24);
1412 if(cl.stats[STAT_ARMOR] > 200)
1413 Sbar_DrawXNum(0,0,cl.stats[STAT_ARMOR],3,24,0,1,0,1,0);
1414 else if(cl.stats[STAT_ARMOR] > 100)
1415 Sbar_DrawXNum(0,0,cl.stats[STAT_ARMOR],3,24,0.2,1,0.2,1,0);
1416 else if(cl.stats[STAT_ARMOR] > 50)
1417 Sbar_DrawXNum(0,0,cl.stats[STAT_ARMOR],3,24,0.6,0.7,0.8,1,0);
1418 else if(cl.stats[STAT_ARMOR] > 25)
1419 Sbar_DrawXNum(0,0,cl.stats[STAT_ARMOR],3,24,1,1,0.2,1,0);
1421 Sbar_DrawXNum(0,0,cl.stats[STAT_ARMOR],3,24,0.7,0,0,1,0);
1425 if (cl.stats[STAT_HEALTH] != 0)
1427 Sbar_DrawStretchPic (184, 0, sb_health, sbar_alpha_fg.value, 24, 24);
1428 if(cl.stats[STAT_HEALTH] > 200)
1429 Sbar_DrawXNum(112,0,cl.stats[STAT_HEALTH],3,24,0,1,0,1,0);
1430 else if(cl.stats[STAT_HEALTH] > 100)
1431 Sbar_DrawXNum(112,0,cl.stats[STAT_HEALTH],3,24,0.2,1,0.2,1,0);
1432 else if(cl.stats[STAT_HEALTH] > 50)
1433 Sbar_DrawXNum(112,0,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1434 else if(cl.stats[STAT_HEALTH] > 25)
1435 Sbar_DrawXNum(112,0,cl.stats[STAT_HEALTH],3,24,1,1,0.2,1,0);
1437 Sbar_DrawXNum(112,0,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1441 if ((cl.stats[STAT_ITEMS] & (NEX_IT_SHELLS | NEX_IT_BULLETS | NEX_IT_ROCKETS | NEX_IT_CELLS)) || cl.stats[STAT_AMMO] != 0)
1443 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1444 Sbar_DrawStretchPic (296, 0, sb_ammo[0], sbar_alpha_fg.value, 24, 24);
1445 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1446 Sbar_DrawStretchPic (296, 0, sb_ammo[1], sbar_alpha_fg.value, 24, 24);
1447 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1448 Sbar_DrawStretchPic (296, 0, sb_ammo[2], sbar_alpha_fg.value, 24, 24);
1449 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1450 Sbar_DrawStretchPic (296, 0, sb_ammo[3], sbar_alpha_fg.value, 24, 24);
1451 if(cl.stats[STAT_AMMO] > 10)
1452 Sbar_DrawXNum(224, 0, cl.stats[STAT_AMMO], 3, 24, 0.6,0.7,0.8,1,0);
1454 Sbar_DrawXNum(224, 0, cl.stats[STAT_AMMO], 3, 24, 0.7,0,0,1,0);
1457 if (sbar_x + 320 + 160 <= vid_conwidth.integer)
1458 Sbar_MiniDeathmatchOverlay (sbar_x + 320, sbar_y);
1461 // The margin can be at most 8 to support 640x480 console size:
1462 // 320 + 2 * (144 + 16) = 640
1468 int redflag, blueflag;
1471 sbar_x = (vid_conwidth.integer - 640)/2;
1472 sbar_y = vid_conheight.integer - 47;
1474 // calculate intensity to draw weapons bar at
1475 fade = 3 - 2 * (cl.time - cl.weapontime);
1478 fade = min(fade, 1);
1479 for (i = 0; i < 8;i++)
1480 if (cl.stats[STAT_ITEMS] & (1 << i))
1481 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1483 if((cl.stats[STAT_ITEMS] & (1<<12)))
1484 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1487 //if (!cl.islocalgame)
1488 // Sbar_DrawFrags ();
1491 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1493 Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1496 redflag = ((cl.stats[STAT_ITEMS]>>15) & 3);
1497 blueflag = ((cl.stats[STAT_ITEMS]>>17) & 3);
1498 x = sbar_flagstatus_right.integer ? vid_conwidth.integer - 10 - sbar_x - 64 : 10 - sbar_x;
1499 if (redflag == 3 && blueflag == 3)
1501 // The Impossible Combination[tm]
1502 // Can only happen in Key Hunt mode...
1503 Sbar_DrawPic ((int) x, -179, sb_items[14]);
1508 Sbar_DrawPic ((int) x, -117, sb_items[redflag+10]);
1510 Sbar_DrawPic ((int) x, -177, sb_items[blueflag+14]);
1514 Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1517 if(cl.stats[STAT_HEALTH] > 100)
1518 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1519 else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1520 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1522 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1524 // AK dont draw ammo for the laser
1525 if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1527 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1528 Sbar_DrawPic (519, 0, sb_ammo[0]);
1529 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1530 Sbar_DrawPic (519, 0, sb_ammo[1]);
1531 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1532 Sbar_DrawPic (519, 0, sb_ammo[2]);
1533 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1534 Sbar_DrawPic (519, 0, sb_ammo[3]);
1536 if(cl.stats[STAT_AMMO] <= 10)
1537 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1539 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1544 DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1546 if (sbar_x + 600 + 160 <= vid_conwidth.integer)
1547 Sbar_MiniDeathmatchOverlay (sbar_x + 600, sbar_y);
1552 // Mini scoreboard uses 12*4 per other team, that is, 144
1553 // pixels when there are four teams...
1554 // Nexuiz by default sets vid_conwidth to 800... makes
1556 // so we need to shift it by 64 pixels to the right to fit
1557 // BUT: then it overlaps with the image that gets drawn
1558 // for viewsize 100! Therefore, just account for 3 teams,
1559 // that is, 96 pixels mini scoreboard size, needing 16 pixels
1563 else if (gamemode == GAME_ZYMOTIC)
1566 float scale = 64.0f / 256.0f;
1567 float kickoffset[3];
1568 VectorClear(kickoffset);
1571 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1572 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1574 sbar_x = (int)((vid_conwidth.integer - 256 * scale)/2 + kickoffset[0]);
1575 sbar_y = (int)((vid_conheight.integer - 256 * scale)/2 + kickoffset[1]);
1576 // left1 16, 48 : 126 -66
1577 // left2 16, 128 : 196 -66
1578 // right 176, 48 : 196 -136
1579 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);
1580 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);
1581 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);
1582 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1584 float scale = 128.0f / 256.0f;
1585 float healthstart, healthheight, healthstarttc, healthendtc;
1586 float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1587 float ammostart, ammoheight, ammostarttc, ammoendtc;
1588 float clipstart, clipheight, clipstarttc, clipendtc;
1589 float kickoffset[3], offset;
1590 VectorClear(kickoffset);
1593 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1594 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1596 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1597 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1598 offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1599 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);
1600 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);
1601 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);
1602 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);
1603 healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1604 shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1605 healthstart = 204 - healthheight;
1606 shieldstart = healthstart - shieldheight;
1607 healthstarttc = healthstart * (1.0f / 256.0f);
1608 healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1609 shieldstarttc = shieldstart * (1.0f / 256.0f);
1610 shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1611 ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1612 ammostart = 114 - ammoheight;
1613 ammostarttc = ammostart * (1.0f / 256.0f);
1614 ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1615 clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1616 clipstart = 190 - clipheight;
1617 clipstarttc = clipstart * (1.0f / 256.0f);
1618 clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1619 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);
1620 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);
1621 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);
1622 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);
1623 DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1624 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1627 else // Quake and others
1629 sbar_x = (vid_conwidth.integer - 320)/2;
1630 sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1631 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1632 //if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1636 if (gamemode != GAME_GOODVSBAD2)
1637 Sbar_DrawInventory ();
1638 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1642 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1644 if (gamemode != GAME_GOODVSBAD2)
1645 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1646 Sbar_DrawScoreboard ();
1650 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1652 // keys (hipnotic only)
1653 //MED 01/04/97 moved keys here so they would not be overwritten
1654 if (gamemode == GAME_HIPNOTIC)
1656 if (cl.stats[STAT_ITEMS] & IT_KEY1)
1657 Sbar_DrawPic (209, 3, sb_items[0]);
1658 if (cl.stats[STAT_ITEMS] & IT_KEY2)
1659 Sbar_DrawPic (209, 12, sb_items[1]);
1662 if (gamemode != GAME_GOODVSBAD2)
1664 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1666 Sbar_DrawNum (24, 0, 666, 3, 1);
1667 Sbar_DrawPic (0, 0, sb_disc);
1671 if (gamemode == GAME_ROGUE)
1673 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1674 if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1675 Sbar_DrawPic (0, 0, sb_armor[2]);
1676 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1677 Sbar_DrawPic (0, 0, sb_armor[1]);
1678 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1679 Sbar_DrawPic (0, 0, sb_armor[0]);
1683 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1684 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1685 Sbar_DrawPic (0, 0, sb_armor[2]);
1686 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1687 Sbar_DrawPic (0, 0, sb_armor[1]);
1688 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1689 Sbar_DrawPic (0, 0, sb_armor[0]);
1698 Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1701 if (gamemode == GAME_ROGUE)
1703 if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1704 Sbar_DrawPic (224, 0, sb_ammo[0]);
1705 else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1706 Sbar_DrawPic (224, 0, sb_ammo[1]);
1707 else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1708 Sbar_DrawPic (224, 0, sb_ammo[2]);
1709 else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1710 Sbar_DrawPic (224, 0, sb_ammo[3]);
1711 else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1712 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1713 else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1714 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1715 else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1716 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1720 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1721 Sbar_DrawPic (224, 0, sb_ammo[0]);
1722 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1723 Sbar_DrawPic (224, 0, sb_ammo[1]);
1724 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1725 Sbar_DrawPic (224, 0, sb_ammo[2]);
1726 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1727 Sbar_DrawPic (224, 0, sb_ammo[3]);
1730 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1732 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1733 if ((!cl.islocalgame || cl.gametype != GAME_COOP))
1735 if (gamemode == GAME_TRANSFUSION)
1736 Sbar_MiniDeathmatchOverlay (0, 0);
1738 Sbar_MiniDeathmatchOverlay (sbar_x + 324, vid_conheight.integer - 8*8);
1745 if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && !cl.intermission && !r_letterbox.value)
1747 pic = Draw_CachePic (va("gfx/crosshair%i", crosshair.integer));
1748 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);
1751 if (cl_prydoncursor.integer)
1752 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);
1755 //=============================================================================
1759 Sbar_DeathmatchOverlay
1763 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1766 qboolean myself = false;
1768 minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : cl.time - s->qw_entertime) / 60.0);
1770 if((s - cl.scores) == cl.playerentity - 1)
1772 if((s - teams) >= 0 && (s - teams) < MAX_SCOREBOARD)
1773 if((s->colors & 15) == (cl.scores[cl.playerentity - 1].colors & 15))
1776 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1778 if (s->qw_spectator)
1780 if (s->qw_ping || s->qw_packetloss)
1781 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 );
1783 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 );
1787 // draw colors behind score
1793 c = palette_rgb_pantsscoreboard[(s->colors & 0xf0) >> 4];
1794 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);
1795 c = palette_rgb_shirtscoreboard[s->colors & 0xf];
1796 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);
1798 //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);
1799 if (s->qw_ping || s->qw_packetloss)
1800 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 );
1802 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 );
1807 if (s->qw_spectator)
1809 if (s->qw_ping || s->qw_packetloss)
1810 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 );
1812 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 );
1816 // draw colors behind score
1817 c = palette_rgb_pantsscoreboard[(s->colors & 0xf0) >> 4];
1818 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);
1819 c = palette_rgb_shirtscoreboard[s->colors & 0xf];
1820 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);
1822 //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);
1823 if (s->qw_ping || s->qw_packetloss)
1824 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 );
1826 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 );
1832 void Sbar_DeathmatchOverlay (void)
1834 int i, y, xmin, xmax, ymin, ymax;
1836 // request new ping times every two second
1837 if (cl.last_ping_request < realtime - 2 && cls.netcon)
1839 cl.last_ping_request = realtime;
1840 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1842 MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
1843 MSG_WriteString(&cls.netcon->message, "pings");
1845 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*/)
1847 // 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
1848 static int ping_anyway_counter = 0;
1849 if(cl.parsingtextexpectingpingforscores == 1)
1851 Con_DPrintf("want to send ping, but still waiting for other reply\n");
1852 if(++ping_anyway_counter >= 5)
1853 cl.parsingtextexpectingpingforscores = 0;
1855 if(cl.parsingtextexpectingpingforscores != 1)
1857 ping_anyway_counter = 0;
1858 cl.parsingtextexpectingpingforscores = 1; // hide the output of the next ping report
1859 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1860 MSG_WriteString(&cls.netcon->message, "ping");
1865 // 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
1866 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1867 MSG_WriteString(&cls.netcon->message, "pings");
1875 ymax = 40 + 8 + (Sbar_IsTeammatch() ? (teamlines * 8 + 5): 0) + scoreboardlines * 8 - 1;
1877 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1878 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)
1880 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)
1881 xmax = vid_conwidth.integer - xmin;
1883 if(gamemode == GAME_NEXUIZ)
1884 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);
1886 DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1890 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1892 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 );
1896 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 );
1900 if (Sbar_IsTeammatch ())
1902 // show team scores first
1903 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1904 y += (int)Sbar_PrintScoreboardItem((teams + teamsort[i]), xmin, y);
1908 for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1909 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], xmin, y);
1914 Sbar_MiniDeathmatchOverlay
1918 void Sbar_MiniDeathmatchOverlay (int x, int y)
1920 int i, j, numlines, range_begin, range_end, myteam, teamsep;
1922 // do not draw this if sbar_miniscoreboard_size is zero
1923 if(sbar_miniscoreboard_size.value == 0)
1925 // adjust the given y if sbar_miniscoreboard_size doesn't indicate default (< 0)
1926 if(sbar_miniscoreboard_size.value > 0)
1927 y = (int) (vid_conheight.integer - sbar_miniscoreboard_size.value * 8);
1932 // decide where to print
1933 if (gamemode == GAME_TRANSFUSION)
1934 numlines = (vid_conwidth.integer - x + 127) / 128;
1936 numlines = (vid_conheight.integer - y + 7) / 8;
1938 // give up if there isn't room
1939 if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1943 for (i = 0; i < scoreboardlines; i++)
1944 if (fragsort[i] == cl.playerentity - 1)
1948 range_end = scoreboardlines;
1951 if (gamemode != GAME_TRANSFUSION)
1952 if (Sbar_IsTeammatch ())
1954 // reserve space for the team scores
1955 numlines -= teamlines;
1957 // find first and last player of my team (only draw the team totals and my own team)
1958 range_begin = range_end = i;
1959 myteam = cl.scores[fragsort[i]].colors & 15;
1960 while(range_begin > 0 && (cl.scores[fragsort[range_begin-1]].colors & 15) == myteam)
1962 while(range_end < scoreboardlines && (cl.scores[fragsort[range_end]].colors & 15) == myteam)
1965 // looks better than two players
1975 i = min(i, range_end - numlines);
1976 i = max(i, range_begin);
1978 if (gamemode == GAME_TRANSFUSION)
1980 for (;i < range_end && x < vid_conwidth.integer;i++)
1981 x += 128 + (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1985 if(range_end - i < numlines) // won't draw to bottom?
1986 y += 8 * (numlines - (range_end - i)); // bottom align
1987 // show team scores first
1988 for (j = 0;j < teamlines && y < vid_conheight.integer;j++)
1989 y += (int)Sbar_PrintScoreboardItem((teams + teamsort[j]), x, y);
1991 for (;i < range_end && y < vid_conheight.integer;i++)
1992 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1996 int Sbar_TeamColorCompare(const void *t1_, const void *t2_)
1998 static int const sortorder[16] =
2017 const scoreboard_t *t1 = *(scoreboard_t **) t1_;
2018 const scoreboard_t *t2 = *(scoreboard_t **) t2_;
2019 int tc1 = sortorder[t1->colors & 15];
2020 int tc2 = sortorder[t2->colors & 15];
2024 void Sbar_Score (int margin)
2026 int i, me, score, otherleader, place, distribution, minutes, seconds;
2028 int sbar_x_save = sbar_x;
2029 int sbar_y_save = sbar_y;
2032 sbar_y = (int) (vid_conheight.value - (32+12));
2035 me = cl.playerentity - 1;
2036 if (sbar_scorerank.integer && me >= 0 && me < cl.maxclients)
2038 if(Sbar_IsTeammatch())
2042 // team1 team3 team4
2046 scoreboard_t *teamcolorsort[16];
2049 for(i = 0; i < teamlines; ++i)
2050 teamcolorsort[i] = &(teams[i]);
2052 // Now sort them by color
2053 qsort(teamcolorsort, teamlines, sizeof(*teamcolorsort), Sbar_TeamColorCompare);
2056 // -12*4: four digits space
2057 place = (teamlines - 1) * (-12 * 4);
2059 for(i = 0; i < teamlines; ++i)
2061 int cindex = teamcolorsort[i]->colors & 15;
2062 unsigned char *c = palette_rgb_shirtscoreboard[cindex];
2063 float cm = max(max(c[0], c[1]), c[2]);
2064 float cr = c[0] / cm;
2065 float cg = c[1] / cm;
2066 float cb = c[2] / cm;
2067 if(cindex == (cl.scores[cl.playerentity - 1].colors & 15)) // my team
2069 Sbar_DrawXNum(-32*4, 0, teamcolorsort[i]->frags, 4, 32, cr, cg, cb, 1, 0);
2073 Sbar_DrawXNum(place, -12, teamcolorsort[i]->frags, 4, 12, cr, cg, cb, 1, 0);
2086 // find leading score other than ourselves, to calculate distribution
2087 // find our place in the scoreboard
2088 score = cl.scores[me].frags;
2089 for (i = 0, otherleader = -1, place = 1;i < cl.maxclients;i++)
2091 if (cl.scores[i].name[0] && i != me)
2093 if (otherleader == -1 || cl.scores[i].frags > cl.scores[otherleader].frags)
2095 if (score < cl.scores[i].frags || (score == cl.scores[i].frags && i < me))
2099 distribution = otherleader >= 0 ? score - cl.scores[otherleader].frags : 0;
2101 Sbar_DrawXNum(-3*12, -12, place, 3, 12, 1, 1, 1, 1, 0);
2102 else if (place == 2)
2103 Sbar_DrawXNum(-3*12, -12, place, 3, 12, 1, 1, 0, 1, 0);
2105 Sbar_DrawXNum(-3*12, -12, place, 3, 12, 1, 0, 0, 1, 0);
2106 if (otherleader < 0)
2107 Sbar_DrawXNum(-32*4, 0, score, 4, 32, 1, 1, 1, 1, 0);
2108 if (distribution >= 0)
2110 Sbar_DrawXNum(-7*12, -12, distribution, 4, 12, 1, 1, 1, 1, 0);
2111 Sbar_DrawXNum(-32*4, 0, score, 4, 32, 1, 1, 1, 1, 0);
2113 else if (distribution >= -5)
2115 Sbar_DrawXNum(-7*12, -12, distribution, 4, 12, 1, 1, 0, 1, 0);
2116 Sbar_DrawXNum(-32*4, 0, score, 4, 32, 1, 1, 0, 1, 0);
2120 Sbar_DrawXNum(-7*12, -12, distribution, 4, 12, 1, 0, 0, 1, 0);
2121 Sbar_DrawXNum(-32*4, 0, score, 4, 32, 1, 0, 0, 1, 0);
2126 if (sbar_gametime.integer && cl.statsf[STAT_TIMELIMIT])
2128 timeleft = max(0, cl.statsf[STAT_TIMELIMIT] * 60 - cl.time);
2129 minutes = (int)floor(timeleft / 60);
2130 seconds = (int)(floor(timeleft) - minutes * 60);
2133 Sbar_DrawXNum(-12*6, 32, minutes, 3, 12, 1, 1, 1, 1, 0);
2134 if(sb_colon && sb_colon->tex != r_texture_notexture)
2135 DrawQ_Pic(sbar_x + -12*3, sbar_y + 32, sb_colon, 12, 12, 1, 1, 1, sbar_alpha_fg.value, 0);
2136 Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
2138 else if (minutes >= 1)
2140 Sbar_DrawXNum(-12*6, 32, minutes, 3, 12, 1, 1, 0, 1, 0);
2141 if(sb_colon && sb_colon->tex != r_texture_notexture)
2142 DrawQ_Pic(sbar_x + -12*3, sbar_y + 32, sb_colon, 12, 12, 1, 1, 0, sbar_alpha_fg.value, 0);
2143 Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 0, 1, 0);
2145 else if ((int)(timeleft * 4) & 1)
2146 Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
2148 Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 0, 0, 1, 0);
2150 else if (sbar_gametime.integer)
2152 minutes = (int)floor(cl.time / 60);
2153 seconds = (int)(floor(cl.time) - minutes * 60);
2154 Sbar_DrawXNum(-12*6, 32, minutes, 3, 12, 1, 1, 1, 1, 0);
2155 if(sb_colon && sb_colon->tex != r_texture_notexture)
2156 DrawQ_Pic(sbar_x + -12*3, sbar_y + 32, sb_colon, 12, 12, 1, 1, 1, sbar_alpha_fg.value, 0);
2157 Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
2160 sbar_x = sbar_x_save;
2161 sbar_y = sbar_y_save;
2166 Sbar_IntermissionOverlay
2170 void Sbar_IntermissionOverlay (void)
2175 if (cl.gametype == GAME_DEATHMATCH)
2177 Sbar_DeathmatchOverlay ();
2181 sbar_x = (vid_conwidth.integer - 320) >> 1;
2182 sbar_y = (vid_conheight.integer - 200) >> 1;
2184 DrawQ_Pic (sbar_x + 64, sbar_y + 24, sb_complete, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
2185 DrawQ_Pic (sbar_x + 0, sbar_y + 56, sb_inter, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
2188 dig = (int)cl.completed_time / 60;
2189 Sbar_DrawNum (160, 64, dig, 3, 0);
2190 num = (int)cl.completed_time - dig*60;
2191 Sbar_DrawPic (234,64,sb_colon);
2192 Sbar_DrawPic (246,64,sb_nums[0][num/10]);
2193 Sbar_DrawPic (266,64,sb_nums[0][num%10]);
2195 // LA: Display as "a" instead of "a/b" if b is 0
2196 if(cl.stats[STAT_TOTALSECRETS])
2198 Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
2199 if (gamemode != GAME_NEXUIZ)
2200 Sbar_DrawPic (232, 104, sb_slash);
2201 Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
2205 Sbar_DrawNum (240, 104, cl.stats[STAT_SECRETS], 3, 0);
2208 if(cl.stats[STAT_TOTALMONSTERS])
2210 Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
2211 if (gamemode != GAME_NEXUIZ)
2212 Sbar_DrawPic (232, 144, sb_slash);
2213 Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
2217 Sbar_DrawNum (240, 144, cl.stats[STAT_MONSTERS], 3, 0);
2228 void Sbar_FinaleOverlay (void)
2230 DrawQ_Pic((vid_conwidth.integer - sb_finale->width)/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);