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 || gamemode == GAME_BLOODOMNICIDE)
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, NULL, NULL);
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 (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 (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 // format is like this: e1m1:The Sligpate Complex
688 dpsnprintf(str, sizeof(str), "%s:%s", cl.worldbasename, cl.worldmessage);
690 // if there's a newline character, terminate the string there
691 if (strchr(str, '\n'))
692 *(strchr(str, '\n')) = 0;
694 // make the time string
695 timelen = dpsnprintf(timestr, sizeof(timestr), " %i:%02i", minutes, seconds);
697 // truncate the level name if necessary to make room for time
699 if ((int)strlen(str) > max)
702 // print the filename and message
703 Sbar_DrawString(8, 12, str);
706 Sbar_DrawString(8 + max*8, 12, timestr);
710 int minutes, seconds, tens, units;
713 if (gamemode != GAME_NEXUIZ) {
714 dpsnprintf (str, sizeof(str), "Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
715 Sbar_DrawString (8, 4, str);
717 dpsnprintf (str, sizeof(str), "Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
718 Sbar_DrawString (8, 12, str);
722 minutes = (int)(cl.time / 60);
723 seconds = (int)(cl.time - 60*minutes);
725 units = seconds - 10*tens;
726 dpsnprintf (str, sizeof(str), "Time :%3i:%i%i", minutes, tens, units);
727 Sbar_DrawString (184, 4, str);
730 if (gamemode == GAME_NEXUIZ) {
731 l = (int) strlen (cl.worldname);
732 Sbar_DrawString (232 - l*4, 12, cl.worldname);
734 l = (int) strlen (cl.worldmessage);
735 Sbar_DrawString (232 - l*4, 12, cl.worldmessage);
745 void Sbar_DrawScoreboard (void)
747 Sbar_SoloScoreboard ();
748 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
749 //if (cl.gametype == GAME_DEATHMATCH)
751 Sbar_DeathmatchOverlay ();
754 //=============================================================================
756 // AK to make DrawInventory smaller
757 static void Sbar_DrawWeapon(int nr, float fade, int active)
759 if (sbar_hudselector.integer == 1)
761 // width = 300, height = 100
762 const int w_width = 32, w_height = 12, w_space = 2, font_size = 8;
764 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);
766 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, FONT_DEFAULT);
770 // width = 300, height = 100
771 const int w_width = 300, w_height = 100, w_space = 10;
772 const float w_scale = 0.4;
774 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);
775 //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, FONT_DEFAULT);
784 void Sbar_DrawInventory (void)
791 if (gamemode == GAME_ROGUE)
793 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
794 Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], sbar_alpha_bg.value);
796 Sbar_DrawAlphaPic (0, -24, rsb_invbar[1], sbar_alpha_bg.value);
799 Sbar_DrawAlphaPic (0, -24, sb_ibar, sbar_alpha_bg.value);
802 for (i=0 ; i<7 ; i++)
804 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<i) )
806 time = cl.item_gettime[i];
807 flashon = (int)(max(0, cl.time - time)*10);
810 if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i) )
816 flashon = (flashon%5) + 2;
818 Sbar_DrawAlphaPic (i*24, -16, sb_weapons[flashon][i], sbar_alpha_bg.value);
824 if (gamemode == GAME_HIPNOTIC)
826 int grenadeflashing=0;
827 for (i=0 ; i<4 ; i++)
829 if (cl.stats[STAT_ITEMS] & (1<<hipweapons[i]) )
831 time = max(0, cl.item_gettime[hipweapons[i]]);
832 flashon = (int)((cl.time - time)*10);
835 if ( cl.stats[STAT_ACTIVEWEAPON] == (1<<hipweapons[i]) )
841 flashon = (flashon%5) + 2;
843 // check grenade launcher
846 if (cl.stats[STAT_ITEMS] & HIT_PROXIMITY_GUN)
851 Sbar_DrawPic (96, -16, hsb_weapons[flashon][2]);
857 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<4))
859 if (!grenadeflashing)
860 Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
863 Sbar_DrawPic (96, -16, hsb_weapons[flashon][4]);
866 Sbar_DrawPic (176 + (i*24), -16, hsb_weapons[flashon][i]);
871 if (gamemode == GAME_ROGUE)
873 // check for powered up weapon.
874 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
876 if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i))
877 Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]);
881 for (i=0 ; i<4 ; i++)
883 dpsnprintf (num, sizeof(num), "%4i",cl.stats[STAT_SHELLS+i] );
885 Sbar_DrawCharacter ( (6*i+0)*8 - 2, -24, 18 + num[0] - '0');
887 Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[1] - '0');
889 Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[2] - '0');
891 Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[3] - '0');
895 for (i=0 ; i<6 ; i++)
896 if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
898 //MED 01/04/97 changed keys
899 if (gamemode != GAME_HIPNOTIC || (i>1))
900 Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
903 //MED 01/04/97 added hipnotic items
905 if (gamemode == GAME_HIPNOTIC)
907 for (i=0 ; i<2 ; i++)
908 if (cl.stats[STAT_ITEMS] & (1<<(24+i)))
909 Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
912 if (gamemode == GAME_ROGUE)
915 for (i=0 ; i<2 ; i++)
916 if (cl.stats[STAT_ITEMS] & (1<<(29+i)))
917 Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
922 for (i=0 ; i<4 ; i++)
923 if (cl.stats[STAT_ITEMS] & (1<<(28+i)))
924 Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
928 //=============================================================================
935 void Sbar_DrawFrags (void)
945 l = min(scoreboardlines, 4);
949 for (i = 0;i < l;i++)
955 c = palette_rgb_pantsscoreboard[(s->colors & 0xf0) >> 4];
956 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);
957 c = palette_rgb_shirtscoreboard[s->colors & 0xf];
958 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);
962 dpsnprintf (num, sizeof(num), "%3i",f);
964 if (k == cl.viewentity - 1)
966 Sbar_DrawCharacter ( x + 2, -24, 16);
967 Sbar_DrawCharacter ( x + 32 - 4, -24, 17);
969 Sbar_DrawCharacter (x + 8, -24, num[0]);
970 Sbar_DrawCharacter (x + 16, -24, num[1]);
971 Sbar_DrawCharacter (x + 24, -24, num[2]);
976 //=============================================================================
984 void Sbar_DrawFace (void)
988 // PGM 01/19/97 - team color drawing
989 // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
990 if (gamemode == GAME_ROGUE && !cl.islocalgame && (teamplay.integer > 3) && (teamplay.integer < 7))
996 s = &cl.scores[cl.viewentity - 1];
998 Sbar_DrawPic (112, 0, rsb_teambord);
999 c = palette_rgb_pantsscoreboard[(s->colors & 0xf0) >> 4];
1000 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);
1001 c = palette_rgb_shirtscoreboard[s->colors & 0xf];
1002 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);
1006 dpsnprintf (num, sizeof(num), "%3i",f);
1008 if ((s->colors & 0xf0)==0)
1011 Sbar_DrawCharacter(109, 3, 18 + num[0] - '0');
1013 Sbar_DrawCharacter(116, 3, 18 + num[1] - '0');
1015 Sbar_DrawCharacter(123, 3, 18 + num[2] - '0');
1019 Sbar_DrawCharacter ( 109, 3, num[0]);
1020 Sbar_DrawCharacter ( 116, 3, num[1]);
1021 Sbar_DrawCharacter ( 123, 3, num[2]);
1026 // PGM 01/19/97 - team color drawing
1028 if ( (cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
1029 Sbar_DrawPic (112, 0, sb_face_invis_invuln);
1030 else if (cl.stats[STAT_ITEMS] & IT_QUAD)
1031 Sbar_DrawPic (112, 0, sb_face_quad );
1032 else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
1033 Sbar_DrawPic (112, 0, sb_face_invis );
1034 else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1035 Sbar_DrawPic (112, 0, sb_face_invuln);
1038 f = cl.stats[STAT_HEALTH] / 20;
1040 Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]);
1043 double topspeed = 0;
1044 double topspeedxy = 0;
1045 time_t current_time = 3;
1046 time_t top_time = 0;
1047 time_t topxy_time = 0;
1049 static void get_showspeed_unit(int unitnumber, double *conversion_factor, const char **unit)
1052 unitnumber = showspeed.integer;
1057 if(gamemode == GAME_NEXUIZ)
1061 *conversion_factor = 1.0;
1065 *conversion_factor = 0.0254;
1066 if(gamemode != GAME_NEXUIZ) *conversion_factor *= 1.5;
1067 // 1qu=1.5in is for non-Nexuiz only - Nexuiz players are overly large, but 1qu=1in fixes that
1071 *conversion_factor = 0.0254 * 3.6;
1072 if(gamemode != GAME_NEXUIZ) *conversion_factor *= 1.5;
1076 *conversion_factor = 0.0254 * 3.6 * 0.6213711922;
1077 if(gamemode != GAME_NEXUIZ) *conversion_factor *= 1.5;
1081 *conversion_factor = 0.0254 * 1.943844492; // 1 m/s = 1.943844492 knots, because 1 knot = 1.852 km/h
1082 if(gamemode != GAME_NEXUIZ) *conversion_factor *= 1.5;
1087 static double showfps_nexttime = 0, showfps_lasttime = -1;
1088 static double showfps_framerate = 0;
1089 static int showfps_framecount = 0;
1091 void Sbar_ShowFPS_Update(void)
1093 double interval = 1;
1096 if (newtime >= showfps_nexttime)
1098 showfps_framerate = showfps_framecount / (newtime - showfps_lasttime);
1099 if (showfps_nexttime < newtime - interval * 1.5)
1100 showfps_nexttime = newtime;
1101 showfps_lasttime = newtime;
1102 showfps_nexttime += interval;
1103 showfps_framecount = 0;
1105 showfps_framecount++;
1108 void Sbar_ShowFPS(void)
1110 float fps_x, fps_y, fps_scalex, fps_scaley, fps_height;
1111 char soundstring[32];
1113 char timestring[32];
1114 char datestring[32];
1115 char timedemostring1[32];
1116 char timedemostring2[32];
1117 char speedstring[32];
1118 char blurstring[32];
1119 char topspeedstring[48];
1120 qboolean red = false;
1123 timedemostring1[0] = 0;
1124 timedemostring2[0] = 0;
1129 topspeedstring[0] = 0;
1130 if (showfps.integer)
1132 red = (showfps_framerate < 1.0f);
1133 if(showfps.integer == 2)
1134 dpsnprintf(fpsstring, sizeof(fpsstring), "%7.3f mspf", (1000.0 / showfps_framerate));
1136 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0 / showfps_framerate + 0.5));
1138 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(showfps_framerate + 0.5));
1141 dpsnprintf(timedemostring1, sizeof(timedemostring1), "frame%4i %f", cls.td_frames, realtime - cls.td_starttime);
1142 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);
1145 if (showtime.integer)
1146 strlcpy(timestring, Sys_TimeString(showtime_format.string), sizeof(timestring));
1147 if (showdate.integer)
1148 strlcpy(datestring, Sys_TimeString(showdate_format.string), sizeof(datestring));
1149 if (showblur.integer)
1150 dpsnprintf(blurstring, sizeof(blurstring), "%3i%% blur", (int)(cl.motionbluralpha * 100));
1151 if (showsound.integer)
1152 dpsnprintf(soundstring, sizeof(soundstring), "%4i/4%i at %3ims", cls.soundstats.mixedsounds, cls.soundstats.totalsounds, cls.soundstats.latency_milliseconds);
1153 if (showspeed.integer || showtopspeed.integer)
1155 double speed, speedxy, f;
1157 speed = VectorLength(cl.movement_velocity);
1158 speedxy = sqrt(cl.movement_velocity[0] * cl.movement_velocity[0] + cl.movement_velocity[1] * cl.movement_velocity[1]);
1159 if (showspeed.integer)
1161 get_showspeed_unit(showspeed.integer, &f, &unit);
1162 dpsnprintf(speedstring, sizeof(speedstring), "%.0f (%.0f) %s", f*speed, f*speedxy, unit);
1164 if (showtopspeed.integer)
1166 qboolean topspeed_latched = false, topspeedxy_latched = false;
1167 get_showspeed_unit(showtopspeed.integer, &f, &unit);
1168 if (speed >= topspeed || current_time - top_time > 3)
1174 topspeed_latched = true;
1175 if (speedxy >= topspeedxy || current_time - topxy_time > 3)
1177 topspeedxy = speedxy;
1181 topspeedxy_latched = true;
1182 dpsnprintf(topspeedstring, sizeof(topspeedstring), "%s%.0f%s (%s%.0f%s) %s",
1183 topspeed_latched ? "^1" : "^xf88", f*topspeed, "^xf88",
1184 topspeedxy_latched ? "^1" : "^xf88", f*topspeedxy, "^xf88",
1186 time(¤t_time);
1189 if (fpsstring[0] || timedemostring1[0] || timedemostring2[0] || timestring[0] || datestring[0] || speedstring[0] || blurstring[0] || topspeedstring[0])
1193 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));
1194 //fps_y = vid_conheight.integer - sb_lines; // yes this may draw over the sbar
1195 //fps_y = bound(0, fps_y, vid_conheight.integer - fps_height);
1196 fps_y = vid_conheight.integer - sbar_info_pos.integer - fps_height;
1199 fps_x = vid_conwidth.integer - DrawQ_TextWidth(soundstring, 0, fps_scalex, fps_scaley, true, FONT_INFOBAR);
1200 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1201 DrawQ_String(fps_x, fps_y, soundstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1202 fps_y += fps_scaley;
1206 r_draw2d_force = true;
1207 fps_x = vid_conwidth.integer - DrawQ_TextWidth(fpsstring, 0, fps_scalex, fps_scaley, true, FONT_INFOBAR);
1208 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1210 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 0, 0, 1, 0, NULL, true, FONT_INFOBAR);
1212 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1213 fps_y += fps_scaley;
1214 r_draw2d_force = false;
1216 if (timedemostring1[0])
1218 fps_x = vid_conwidth.integer - DrawQ_TextWidth(timedemostring1, 0, fps_scalex, fps_scaley, true, FONT_INFOBAR);
1219 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1220 DrawQ_String(fps_x, fps_y, timedemostring1, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1221 fps_y += fps_scaley;
1223 if (timedemostring2[0])
1225 fps_x = vid_conwidth.integer - DrawQ_TextWidth(timedemostring2, 0, fps_scalex, fps_scaley, true, FONT_INFOBAR);
1226 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1227 DrawQ_String(fps_x, fps_y, timedemostring2, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1228 fps_y += fps_scaley;
1232 fps_x = vid_conwidth.integer - DrawQ_TextWidth(timestring, 0, fps_scalex, fps_scaley, true, FONT_INFOBAR);
1233 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1234 DrawQ_String(fps_x, fps_y, timestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1235 fps_y += fps_scaley;
1239 fps_x = vid_conwidth.integer - DrawQ_TextWidth(datestring, 0, fps_scalex, fps_scaley, true, FONT_INFOBAR);
1240 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1241 DrawQ_String(fps_x, fps_y, datestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1242 fps_y += fps_scaley;
1246 fps_x = vid_conwidth.integer - DrawQ_TextWidth(speedstring, 0, fps_scalex, fps_scaley, true, FONT_INFOBAR);
1247 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1248 DrawQ_String(fps_x, fps_y, speedstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1249 fps_y += fps_scaley;
1251 if (topspeedstring[0])
1253 fps_x = vid_conwidth.integer - DrawQ_TextWidth(topspeedstring, 0, fps_scalex, fps_scaley, false, FONT_INFOBAR);
1254 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1255 DrawQ_String(fps_x, fps_y, topspeedstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, false, FONT_INFOBAR);
1256 fps_y += fps_scaley;
1260 fps_x = vid_conwidth.integer - DrawQ_TextWidth(blurstring, 0, fps_scalex, fps_scaley, true, FONT_INFOBAR);
1261 DrawQ_Fill(fps_x, fps_y, vid_conwidth.integer - fps_x, fps_scaley, 0, 0, 0, 0.5, 0);
1262 DrawQ_String(fps_x, fps_y, blurstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true, FONT_INFOBAR);
1263 fps_y += fps_scaley;
1268 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)
1271 c2 = bound(0, c2, 1);
1272 c1 = bound(0, c1, 1 - c2);
1274 r[1] = rangey + rangeheight * (c2 + c1);
1275 r[2] = rangey + rangeheight * (c2);
1279 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);
1281 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);
1283 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);
1285 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);
1293 extern float v_dmg_time, v_dmg_roll, v_dmg_pitch;
1294 extern cvar_t v_kicktime;
1295 void Sbar_Score (int margin);
1296 void Sbar_Draw (void)
1300 if(cl.csqc_vidvars.drawenginesbar) //[515]: csqc drawsbar
1303 Sbar_DrawScoreboard ();
1304 else if (cl.intermission == 1)
1306 if(gamemode == GAME_NEXUIZ) // display full scoreboard (that is, show scores + map name)
1308 Sbar_DrawScoreboard();
1311 Sbar_IntermissionOverlay();
1313 else if (cl.intermission == 2)
1314 Sbar_FinaleOverlay();
1315 else if (gamemode == GAME_DELUXEQUAKE)
1318 else if (gamemode == GAME_SOM)
1320 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1321 Sbar_DrawScoreboard ();
1324 // this is the top left of the sbar area
1326 sbar_y = vid_conheight.integer - 24*3;
1329 if (cl.stats[STAT_ARMOR])
1331 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1332 Sbar_DrawPic(0, 0, somsb_armor[2]);
1333 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1334 Sbar_DrawPic(0, 0, somsb_armor[1]);
1335 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1336 Sbar_DrawPic(0, 0, somsb_armor[0]);
1337 Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1341 Sbar_DrawPic(0, 24, somsb_health);
1342 Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1345 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1346 Sbar_DrawPic(0, 48, somsb_ammo[0]);
1347 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1348 Sbar_DrawPic(0, 48, somsb_ammo[1]);
1349 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1350 Sbar_DrawPic(0, 48, somsb_ammo[2]);
1351 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1352 Sbar_DrawPic(0, 48, somsb_ammo[3]);
1353 Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
1354 if (cl.stats[STAT_SHELLS])
1355 Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
1358 else if (gamemode == GAME_NEXUIZ)
1360 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1362 sbar_x = (vid_conwidth.integer - 640)/2;
1363 sbar_y = vid_conheight.integer - 47;
1364 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1365 Sbar_DrawScoreboard ();
1367 else if (sb_lines && sbar_hudselector.integer == 1)
1371 int redflag, blueflag;
1374 sbar_x = (vid_conwidth.integer - 320)/2;
1375 sbar_y = vid_conheight.integer - 24 - 16;
1377 // calculate intensity to draw weapons bar at
1378 fade = 3.2 - 2 * (cl.time - cl.weapontime);
1379 fade = bound(0.7, fade, 1);
1380 for (i = 0; i < 8;i++)
1381 if (cl.stats[STAT_ITEMS] & (1 << i))
1382 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1383 if((cl.stats[STAT_ITEMS] & (1<<12)))
1384 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1387 redflag = ((cl.stats[STAT_ITEMS]>>15) & 3);
1388 blueflag = ((cl.stats[STAT_ITEMS]>>17) & 3);
1389 x = sbar_flagstatus_right.integer ? vid_conwidth.integer - 10 - sbar_x - 64 : 10 - sbar_x;
1390 if (redflag == 3 && blueflag == 3)
1392 // The Impossible Combination[tm]
1393 // Can only happen in Key Hunt mode...
1394 Sbar_DrawPic ((int) x, (int) ((vid_conheight.integer - sbar_y) - (sbar_flagstatus_pos.value + 128)), sb_items[14]);
1399 Sbar_DrawPic ((int) x, (int) ((vid_conheight.integer - sbar_y) - (sbar_flagstatus_pos.value + 64)), sb_items[redflag+10]);
1401 Sbar_DrawPic ((int) x, (int) ((vid_conheight.integer - sbar_y) - (sbar_flagstatus_pos.value + 128)), sb_items[blueflag+14]);
1405 if (cl.stats[STAT_ARMOR] > 0)
1407 Sbar_DrawStretchPic (72, 0, sb_armor[0], sbar_alpha_fg.value, 24, 24);
1408 if(cl.stats[STAT_ARMOR] > 200)
1409 Sbar_DrawXNum(0,0,cl.stats[STAT_ARMOR],3,24,0,1,0,1,0);
1410 else if(cl.stats[STAT_ARMOR] > 100)
1411 Sbar_DrawXNum(0,0,cl.stats[STAT_ARMOR],3,24,0.2,1,0.2,1,0);
1412 else if(cl.stats[STAT_ARMOR] > 50)
1413 Sbar_DrawXNum(0,0,cl.stats[STAT_ARMOR],3,24,0.6,0.7,0.8,1,0);
1414 else if(cl.stats[STAT_ARMOR] > 25)
1415 Sbar_DrawXNum(0,0,cl.stats[STAT_ARMOR],3,24,1,1,0.2,1,0);
1417 Sbar_DrawXNum(0,0,cl.stats[STAT_ARMOR],3,24,0.7,0,0,1,0);
1421 if (cl.stats[STAT_HEALTH] != 0)
1423 Sbar_DrawStretchPic (184, 0, sb_health, sbar_alpha_fg.value, 24, 24);
1424 if(cl.stats[STAT_HEALTH] > 200)
1425 Sbar_DrawXNum(112,0,cl.stats[STAT_HEALTH],3,24,0,1,0,1,0);
1426 else if(cl.stats[STAT_HEALTH] > 100)
1427 Sbar_DrawXNum(112,0,cl.stats[STAT_HEALTH],3,24,0.2,1,0.2,1,0);
1428 else if(cl.stats[STAT_HEALTH] > 50)
1429 Sbar_DrawXNum(112,0,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1430 else if(cl.stats[STAT_HEALTH] > 25)
1431 Sbar_DrawXNum(112,0,cl.stats[STAT_HEALTH],3,24,1,1,0.2,1,0);
1433 Sbar_DrawXNum(112,0,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1437 if ((cl.stats[STAT_ITEMS] & (NEX_IT_SHELLS | NEX_IT_BULLETS | NEX_IT_ROCKETS | NEX_IT_CELLS)) || cl.stats[STAT_AMMO] != 0)
1439 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1440 Sbar_DrawStretchPic (296, 0, sb_ammo[0], sbar_alpha_fg.value, 24, 24);
1441 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1442 Sbar_DrawStretchPic (296, 0, sb_ammo[1], sbar_alpha_fg.value, 24, 24);
1443 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1444 Sbar_DrawStretchPic (296, 0, sb_ammo[2], sbar_alpha_fg.value, 24, 24);
1445 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1446 Sbar_DrawStretchPic (296, 0, sb_ammo[3], sbar_alpha_fg.value, 24, 24);
1447 if(cl.stats[STAT_AMMO] > 10)
1448 Sbar_DrawXNum(224, 0, cl.stats[STAT_AMMO], 3, 24, 0.6,0.7,0.8,1,0);
1450 Sbar_DrawXNum(224, 0, cl.stats[STAT_AMMO], 3, 24, 0.7,0,0,1,0);
1453 if (sbar_x + 320 + 160 <= vid_conwidth.integer)
1454 Sbar_MiniDeathmatchOverlay (sbar_x + 320, sbar_y);
1457 // The margin can be at most 8 to support 640x480 console size:
1458 // 320 + 2 * (144 + 16) = 640
1464 int redflag, blueflag;
1467 sbar_x = (vid_conwidth.integer - 640)/2;
1468 sbar_y = vid_conheight.integer - 47;
1470 // calculate intensity to draw weapons bar at
1471 fade = 3 - 2 * (cl.time - cl.weapontime);
1474 fade = min(fade, 1);
1475 for (i = 0; i < 8;i++)
1476 if (cl.stats[STAT_ITEMS] & (1 << i))
1477 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1479 if((cl.stats[STAT_ITEMS] & (1<<12)))
1480 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1483 //if (!cl.islocalgame)
1484 // Sbar_DrawFrags ();
1487 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1489 Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1492 redflag = ((cl.stats[STAT_ITEMS]>>15) & 3);
1493 blueflag = ((cl.stats[STAT_ITEMS]>>17) & 3);
1494 x = sbar_flagstatus_right.integer ? vid_conwidth.integer - 10 - sbar_x - 64 : 10 - sbar_x;
1495 if (redflag == 3 && blueflag == 3)
1497 // The Impossible Combination[tm]
1498 // Can only happen in Key Hunt mode...
1499 Sbar_DrawPic ((int) x, -179, sb_items[14]);
1504 Sbar_DrawPic ((int) x, -117, sb_items[redflag+10]);
1506 Sbar_DrawPic ((int) x, -177, sb_items[blueflag+14]);
1510 Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1513 if(cl.stats[STAT_HEALTH] > 100)
1514 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1515 else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1516 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1518 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1520 // AK dont draw ammo for the laser
1521 if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1523 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1524 Sbar_DrawPic (519, 0, sb_ammo[0]);
1525 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1526 Sbar_DrawPic (519, 0, sb_ammo[1]);
1527 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1528 Sbar_DrawPic (519, 0, sb_ammo[2]);
1529 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1530 Sbar_DrawPic (519, 0, sb_ammo[3]);
1532 if(cl.stats[STAT_AMMO] <= 10)
1533 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1535 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1540 DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1542 if (sbar_x + 600 + 160 <= vid_conwidth.integer)
1543 Sbar_MiniDeathmatchOverlay (sbar_x + 600, sbar_y);
1548 // Mini scoreboard uses 12*4 per other team, that is, 144
1549 // pixels when there are four teams...
1550 // Nexuiz by default sets vid_conwidth to 800... makes
1552 // so we need to shift it by 64 pixels to the right to fit
1553 // BUT: then it overlaps with the image that gets drawn
1554 // for viewsize 100! Therefore, just account for 3 teams,
1555 // that is, 96 pixels mini scoreboard size, needing 16 pixels
1559 else if (gamemode == GAME_ZYMOTIC)
1562 float scale = 64.0f / 256.0f;
1563 float kickoffset[3];
1564 VectorClear(kickoffset);
1567 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1568 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1570 sbar_x = (int)((vid_conwidth.integer - 256 * scale)/2 + kickoffset[0]);
1571 sbar_y = (int)((vid_conheight.integer - 256 * scale)/2 + kickoffset[1]);
1572 // left1 16, 48 : 126 -66
1573 // left2 16, 128 : 196 -66
1574 // right 176, 48 : 196 -136
1575 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);
1576 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);
1577 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);
1578 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1580 float scale = 128.0f / 256.0f;
1581 float healthstart, healthheight, healthstarttc, healthendtc;
1582 float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1583 float ammostart, ammoheight, ammostarttc, ammoendtc;
1584 float clipstart, clipheight, clipstarttc, clipendtc;
1585 float kickoffset[3], offset;
1586 VectorClear(kickoffset);
1589 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1590 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1592 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1593 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1594 offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1595 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);
1596 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);
1597 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);
1598 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);
1599 healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1600 shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1601 healthstart = 204 - healthheight;
1602 shieldstart = healthstart - shieldheight;
1603 healthstarttc = healthstart * (1.0f / 256.0f);
1604 healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1605 shieldstarttc = shieldstart * (1.0f / 256.0f);
1606 shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1607 ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1608 ammostart = 114 - ammoheight;
1609 ammostarttc = ammostart * (1.0f / 256.0f);
1610 ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1611 clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1612 clipstart = 190 - clipheight;
1613 clipstarttc = clipstart * (1.0f / 256.0f);
1614 clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1615 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);
1616 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);
1617 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);
1618 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);
1619 DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1620 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1623 else // Quake and others
1625 sbar_x = (vid_conwidth.integer - 320)/2;
1626 sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1627 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1628 //if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1632 if (gamemode != GAME_GOODVSBAD2)
1633 Sbar_DrawInventory ();
1634 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1638 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1640 if (gamemode != GAME_GOODVSBAD2)
1641 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1642 Sbar_DrawScoreboard ();
1646 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1648 // keys (hipnotic only)
1649 //MED 01/04/97 moved keys here so they would not be overwritten
1650 if (gamemode == GAME_HIPNOTIC)
1652 if (cl.stats[STAT_ITEMS] & IT_KEY1)
1653 Sbar_DrawPic (209, 3, sb_items[0]);
1654 if (cl.stats[STAT_ITEMS] & IT_KEY2)
1655 Sbar_DrawPic (209, 12, sb_items[1]);
1658 if (gamemode != GAME_GOODVSBAD2)
1660 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1662 Sbar_DrawNum (24, 0, 666, 3, 1);
1663 Sbar_DrawPic (0, 0, sb_disc);
1667 if (gamemode == GAME_ROGUE)
1669 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1670 if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1671 Sbar_DrawPic (0, 0, sb_armor[2]);
1672 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1673 Sbar_DrawPic (0, 0, sb_armor[1]);
1674 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1675 Sbar_DrawPic (0, 0, sb_armor[0]);
1679 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1680 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1681 Sbar_DrawPic (0, 0, sb_armor[2]);
1682 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1683 Sbar_DrawPic (0, 0, sb_armor[1]);
1684 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1685 Sbar_DrawPic (0, 0, sb_armor[0]);
1694 Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1697 if (gamemode == GAME_ROGUE)
1699 if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1700 Sbar_DrawPic (224, 0, sb_ammo[0]);
1701 else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1702 Sbar_DrawPic (224, 0, sb_ammo[1]);
1703 else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1704 Sbar_DrawPic (224, 0, sb_ammo[2]);
1705 else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1706 Sbar_DrawPic (224, 0, sb_ammo[3]);
1707 else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1708 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1709 else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1710 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1711 else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1712 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1716 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1717 Sbar_DrawPic (224, 0, sb_ammo[0]);
1718 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1719 Sbar_DrawPic (224, 0, sb_ammo[1]);
1720 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1721 Sbar_DrawPic (224, 0, sb_ammo[2]);
1722 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1723 Sbar_DrawPic (224, 0, sb_ammo[3]);
1726 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1728 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1729 if ((!cl.islocalgame || cl.gametype != GAME_COOP))
1731 if (gamemode == GAME_TRANSFUSION)
1732 Sbar_MiniDeathmatchOverlay (0, 0);
1734 Sbar_MiniDeathmatchOverlay (sbar_x + 324, vid_conheight.integer - 8*8);
1741 if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && !cl.intermission && !r_letterbox.value)
1743 pic = Draw_CachePic (va("gfx/crosshair%i", crosshair.integer));
1744 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);
1747 if (cl_prydoncursor.integer > 0)
1748 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);
1751 //=============================================================================
1755 Sbar_DeathmatchOverlay
1759 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1762 qboolean myself = false;
1764 minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : cl.time - s->qw_entertime) / 60.0);
1766 if((s - cl.scores) == cl.playerentity - 1)
1768 if((s - teams) >= 0 && (s - teams) < MAX_SCOREBOARD)
1769 if((s->colors & 15) == (cl.scores[cl.playerentity - 1].colors & 15))
1772 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1774 if (s->qw_spectator)
1776 if (s->qw_ping || s->qw_packetloss)
1777 DrawQ_String(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 );
1779 DrawQ_String(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 );
1783 // draw colors behind score
1789 c = palette_rgb_pantsscoreboard[(s->colors & 0xf0) >> 4];
1790 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);
1791 c = palette_rgb_shirtscoreboard[s->colors & 0xf];
1792 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);
1794 //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, FONT_DEFAULT);
1795 if (s->qw_ping || s->qw_packetloss)
1796 DrawQ_String(x, y, va("%4i %3i %4i %5i %-4s %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1798 DrawQ_String(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 );
1803 if (s->qw_spectator)
1805 if (s->qw_ping || s->qw_packetloss)
1806 DrawQ_String(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 );
1808 DrawQ_String(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 );
1812 // draw colors behind score
1813 c = palette_rgb_pantsscoreboard[(s->colors & 0xf0) >> 4];
1814 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);
1815 c = palette_rgb_shirtscoreboard[s->colors & 0xf];
1816 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);
1818 //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, FONT_DEFAULT);
1819 if (s->qw_ping || s->qw_packetloss)
1820 DrawQ_String(x, y, va("%4i %3i %5i %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), (int) s->frags, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1822 DrawQ_String(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 );
1828 void Sbar_DeathmatchOverlay (void)
1830 int i, y, xmin, xmax, ymin, ymax;
1832 // request new ping times every two second
1833 if (cl.last_ping_request < realtime - 2 && cls.netcon)
1835 cl.last_ping_request = realtime;
1836 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1838 MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
1839 MSG_WriteString(&cls.netcon->message, "pings");
1841 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*/)
1843 // 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
1844 static int ping_anyway_counter = 0;
1845 if(cl.parsingtextexpectingpingforscores == 1)
1847 Con_DPrintf("want to send ping, but still waiting for other reply\n");
1848 if(++ping_anyway_counter >= 5)
1849 cl.parsingtextexpectingpingforscores = 0;
1851 if(cl.parsingtextexpectingpingforscores != 1)
1853 ping_anyway_counter = 0;
1854 cl.parsingtextexpectingpingforscores = 1; // hide the output of the next ping report
1855 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1856 MSG_WriteString(&cls.netcon->message, "ping");
1861 // 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
1862 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1863 MSG_WriteString(&cls.netcon->message, "pings");
1871 ymax = 40 + 8 + (Sbar_IsTeammatch() ? (teamlines * 8 + 5): 0) + scoreboardlines * 8 - 1;
1873 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1874 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)
1876 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)
1877 xmax = vid_conwidth.integer - xmin;
1879 if(gamemode == GAME_NEXUIZ)
1880 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);
1882 DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1886 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1888 DrawQ_String(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 );
1892 DrawQ_String(xmin, y, va("ping pl%% frags name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false, FONT_SBAR );
1896 if (Sbar_IsTeammatch ())
1898 // show team scores first
1899 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1900 y += (int)Sbar_PrintScoreboardItem((teams + teamsort[i]), xmin, y);
1904 for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1905 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], xmin, y);
1910 Sbar_MiniDeathmatchOverlay
1914 void Sbar_MiniDeathmatchOverlay (int x, int y)
1916 int i, j, numlines, range_begin, range_end, myteam, teamsep;
1918 // do not draw this if sbar_miniscoreboard_size is zero
1919 if(sbar_miniscoreboard_size.value == 0)
1921 // adjust the given y if sbar_miniscoreboard_size doesn't indicate default (< 0)
1922 if(sbar_miniscoreboard_size.value > 0)
1923 y = (int) (vid_conheight.integer - sbar_miniscoreboard_size.value * 8);
1928 // decide where to print
1929 if (gamemode == GAME_TRANSFUSION)
1930 numlines = (vid_conwidth.integer - x + 127) / 128;
1932 numlines = (vid_conheight.integer - y + 7) / 8;
1934 // give up if there isn't room
1935 if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1939 for (i = 0; i < scoreboardlines; i++)
1940 if (fragsort[i] == cl.playerentity - 1)
1944 range_end = scoreboardlines;
1947 if (gamemode != GAME_TRANSFUSION)
1948 if (Sbar_IsTeammatch ())
1950 // reserve space for the team scores
1951 numlines -= teamlines;
1953 // find first and last player of my team (only draw the team totals and my own team)
1954 range_begin = range_end = i;
1955 myteam = cl.scores[fragsort[i]].colors & 15;
1956 while(range_begin > 0 && (cl.scores[fragsort[range_begin-1]].colors & 15) == myteam)
1958 while(range_end < scoreboardlines && (cl.scores[fragsort[range_end]].colors & 15) == myteam)
1961 // looks better than two players
1971 i = min(i, range_end - numlines);
1972 i = max(i, range_begin);
1974 if (gamemode == GAME_TRANSFUSION)
1976 for (;i < range_end && x < vid_conwidth.integer;i++)
1977 x += 128 + (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1981 if(range_end - i < numlines) // won't draw to bottom?
1982 y += 8 * (numlines - (range_end - i)); // bottom align
1983 // show team scores first
1984 for (j = 0;j < teamlines && y < vid_conheight.integer;j++)
1985 y += (int)Sbar_PrintScoreboardItem((teams + teamsort[j]), x, y);
1987 for (;i < range_end && y < vid_conheight.integer;i++)
1988 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1992 int Sbar_TeamColorCompare(const void *t1_, const void *t2_)
1994 static int const sortorder[16] =
2013 const scoreboard_t *t1 = *(scoreboard_t **) t1_;
2014 const scoreboard_t *t2 = *(scoreboard_t **) t2_;
2015 int tc1 = sortorder[t1->colors & 15];
2016 int tc2 = sortorder[t2->colors & 15];
2020 void Sbar_Score (int margin)
2022 int i, me, score, otherleader, place, distribution, minutes, seconds;
2024 int sbar_x_save = sbar_x;
2025 int sbar_y_save = sbar_y;
2028 sbar_y = (int) (vid_conheight.value - (32+12));
2031 me = cl.playerentity - 1;
2032 if (sbar_scorerank.integer && me >= 0 && me < cl.maxclients)
2034 if(Sbar_IsTeammatch())
2038 // team1 team3 team4
2042 scoreboard_t *teamcolorsort[16];
2045 for(i = 0; i < teamlines; ++i)
2046 teamcolorsort[i] = &(teams[i]);
2048 // Now sort them by color
2049 qsort(teamcolorsort, teamlines, sizeof(*teamcolorsort), Sbar_TeamColorCompare);
2052 // -12*4: four digits space
2053 place = (teamlines - 1) * (-12 * 4);
2055 for(i = 0; i < teamlines; ++i)
2057 int cindex = teamcolorsort[i]->colors & 15;
2058 unsigned char *c = palette_rgb_shirtscoreboard[cindex];
2059 float cm = max(max(c[0], c[1]), c[2]);
2060 float cr = c[0] / cm;
2061 float cg = c[1] / cm;
2062 float cb = c[2] / cm;
2063 if(cindex == (cl.scores[cl.playerentity - 1].colors & 15)) // my team
2065 Sbar_DrawXNum(-32*4, 0, teamcolorsort[i]->frags, 4, 32, cr, cg, cb, 1, 0);
2069 Sbar_DrawXNum(place, -12, teamcolorsort[i]->frags, 4, 12, cr, cg, cb, 1, 0);
2082 // find leading score other than ourselves, to calculate distribution
2083 // find our place in the scoreboard
2084 score = cl.scores[me].frags;
2085 for (i = 0, otherleader = -1, place = 1;i < cl.maxclients;i++)
2087 if (cl.scores[i].name[0] && i != me)
2089 if (otherleader == -1 || cl.scores[i].frags > cl.scores[otherleader].frags)
2091 if (score < cl.scores[i].frags || (score == cl.scores[i].frags && i < me))
2095 distribution = otherleader >= 0 ? score - cl.scores[otherleader].frags : 0;
2097 Sbar_DrawXNum(-3*12, -12, place, 3, 12, 1, 1, 1, 1, 0);
2098 else if (place == 2)
2099 Sbar_DrawXNum(-3*12, -12, place, 3, 12, 1, 1, 0, 1, 0);
2101 Sbar_DrawXNum(-3*12, -12, place, 3, 12, 1, 0, 0, 1, 0);
2102 if (otherleader < 0)
2103 Sbar_DrawXNum(-32*4, 0, score, 4, 32, 1, 1, 1, 1, 0);
2104 if (distribution >= 0)
2106 Sbar_DrawXNum(-7*12, -12, distribution, 4, 12, 1, 1, 1, 1, 0);
2107 Sbar_DrawXNum(-32*4, 0, score, 4, 32, 1, 1, 1, 1, 0);
2109 else if (distribution >= -5)
2111 Sbar_DrawXNum(-7*12, -12, distribution, 4, 12, 1, 1, 0, 1, 0);
2112 Sbar_DrawXNum(-32*4, 0, score, 4, 32, 1, 1, 0, 1, 0);
2116 Sbar_DrawXNum(-7*12, -12, distribution, 4, 12, 1, 0, 0, 1, 0);
2117 Sbar_DrawXNum(-32*4, 0, score, 4, 32, 1, 0, 0, 1, 0);
2122 if (sbar_gametime.integer && cl.statsf[STAT_TIMELIMIT])
2124 timeleft = max(0, cl.statsf[STAT_TIMELIMIT] * 60 - cl.time);
2125 minutes = (int)floor(timeleft / 60);
2126 seconds = (int)(floor(timeleft) - minutes * 60);
2129 Sbar_DrawXNum(-12*6, 32, minutes, 3, 12, 1, 1, 1, 1, 0);
2130 if(sb_colon && sb_colon->tex != r_texture_notexture)
2131 DrawQ_Pic(sbar_x + -12*3, sbar_y + 32, sb_colon, 12, 12, 1, 1, 1, sbar_alpha_fg.value, 0);
2132 Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
2134 else if (minutes >= 1)
2136 Sbar_DrawXNum(-12*6, 32, minutes, 3, 12, 1, 1, 0, 1, 0);
2137 if(sb_colon && sb_colon->tex != r_texture_notexture)
2138 DrawQ_Pic(sbar_x + -12*3, sbar_y + 32, sb_colon, 12, 12, 1, 1, 0, sbar_alpha_fg.value, 0);
2139 Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 0, 1, 0);
2141 else if ((int)(timeleft * 4) & 1)
2142 Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
2144 Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 0, 0, 1, 0);
2146 else if (sbar_gametime.integer)
2148 minutes = (int)floor(cl.time / 60);
2149 seconds = (int)(floor(cl.time) - minutes * 60);
2150 Sbar_DrawXNum(-12*6, 32, minutes, 3, 12, 1, 1, 1, 1, 0);
2151 if(sb_colon && sb_colon->tex != r_texture_notexture)
2152 DrawQ_Pic(sbar_x + -12*3, sbar_y + 32, sb_colon, 12, 12, 1, 1, 1, sbar_alpha_fg.value, 0);
2153 Sbar_DrawXNum(-12*2, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
2156 sbar_x = sbar_x_save;
2157 sbar_y = sbar_y_save;
2162 Sbar_IntermissionOverlay
2166 void Sbar_IntermissionOverlay (void)
2171 if (cl.gametype == GAME_DEATHMATCH)
2173 Sbar_DeathmatchOverlay ();
2177 sbar_x = (vid_conwidth.integer - 320) >> 1;
2178 sbar_y = (vid_conheight.integer - 200) >> 1;
2180 DrawQ_Pic (sbar_x + 64, sbar_y + 24, sb_complete, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
2181 DrawQ_Pic (sbar_x + 0, sbar_y + 56, sb_inter, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
2184 dig = (int)cl.completed_time / 60;
2185 Sbar_DrawNum (160, 64, dig, 3, 0);
2186 num = (int)cl.completed_time - dig*60;
2187 Sbar_DrawPic (234,64,sb_colon);
2188 Sbar_DrawPic (246,64,sb_nums[0][num/10]);
2189 Sbar_DrawPic (266,64,sb_nums[0][num%10]);
2191 // LA: Display as "a" instead of "a/b" if b is 0
2192 if(cl.stats[STAT_TOTALSECRETS])
2194 Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
2195 if (gamemode != GAME_NEXUIZ)
2196 Sbar_DrawPic (232, 104, sb_slash);
2197 Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
2201 Sbar_DrawNum (240, 104, cl.stats[STAT_SECRETS], 3, 0);
2204 if(cl.stats[STAT_TOTALMONSTERS])
2206 Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
2207 if (gamemode != GAME_NEXUIZ)
2208 Sbar_DrawPic (232, 144, sb_slash);
2209 Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
2213 Sbar_DrawNum (240, 144, cl.stats[STAT_MONSTERS], 3, 0);
2224 void Sbar_FinaleOverlay (void)
2226 DrawQ_Pic((vid_conwidth.integer - sb_finale->width)/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);