2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 // sbar.c -- status bar code
26 #define STAT_MINUS 10 // num frame for '-' stats digit
27 cachepic_t *sb_nums[2][11];
28 cachepic_t *sb_colon, *sb_slash;
31 cachepic_t *sb_scorebar;
32 // AK only used by NEX
33 cachepic_t *sb_sbar_minimal;
34 cachepic_t *sb_sbar_overlay;
36 // AK changed the bound to 9
37 cachepic_t *sb_weapons[7][9]; // 0 is active, 1 is owned, 2-5 are flashes
38 cachepic_t *sb_ammo[4];
39 cachepic_t *sb_sigil[4];
40 cachepic_t *sb_armor[3];
41 cachepic_t *sb_items[32];
43 // 0-4 are based on health (in 20 increments)
44 // 0 is static, 1 is temporary animation
45 cachepic_t *sb_faces[5][2];
47 cachepic_t *sb_face_invis;
48 cachepic_t *sb_face_quad;
49 cachepic_t *sb_face_invuln;
50 cachepic_t *sb_face_invis_invuln;
52 qboolean sb_showscores;
54 int sb_lines; // scan lines to draw
56 cachepic_t *rsb_invbar[2];
57 cachepic_t *rsb_weapons[5];
58 cachepic_t *rsb_items[2];
59 cachepic_t *rsb_ammo[3];
60 cachepic_t *rsb_teambord; // PGM 01/19/97 - team color border
62 //MED 01/04/97 added two more weapons + 3 alternates for grenade launcher
63 cachepic_t *hsb_weapons[7][5]; // 0 is active, 1 is owned, 2-5 are flashes
64 //MED 01/04/97 added array to simplify weapon parsing
65 int hipweapons[4] = {HIT_LASER_CANNON_BIT,HIT_MJOLNIR_BIT,4,HIT_PROXIMITY_GUN_BIT};
66 //MED 01/04/97 added hipnotic items array
67 cachepic_t *hsb_items[2];
70 cachepic_t *somsb_health;
71 cachepic_t *somsb_ammo[4];
72 cachepic_t *somsb_armor[3];
74 cachepic_t *zymsb_crosshair_center;
75 cachepic_t *zymsb_crosshair_line;
76 cachepic_t *zymsb_crosshair_health;
77 cachepic_t *zymsb_crosshair_ammo;
78 cachepic_t *zymsb_crosshair_clip;
79 cachepic_t *zymsb_crosshair_background;
80 cachepic_t *zymsb_crosshair_left1;
81 cachepic_t *zymsb_crosshair_left2;
82 cachepic_t *zymsb_crosshair_right;
84 cachepic_t *sb_ranking;
85 cachepic_t *sb_complete;
87 cachepic_t *sb_finale;
89 cvar_t showfps = {CVAR_SAVE, "showfps", "0", "shows your rendered fps (frames per second)"};
90 cvar_t showtime = {CVAR_SAVE, "showtime", "0", "shows current time of day (useful on screenshots)"};
91 cvar_t showtime_format = {CVAR_SAVE, "showtime_format", "%H:%M:%S", "format string for time of day"};
92 cvar_t showdate = {CVAR_SAVE, "showdate", "0", "shows current date (useful on screenshots)"};
93 cvar_t showdate_format = {CVAR_SAVE, "showdate_format", "%Y-%m-%d", "format string for date"};
94 cvar_t sbar_alpha_bg = {CVAR_SAVE, "sbar_alpha_bg", "0.4", "opacity value of the statusbar background image"};
95 cvar_t sbar_alpha_fg = {CVAR_SAVE, "sbar_alpha_fg", "1", "opacity value of the statusbar weapon/item icons and numbers"};
97 cvar_t cl_deathscoreboard = {0, "cl_deathscoreboard", "1", "shows scoreboard (+showscores) while dead"};
99 cvar_t crosshair_color_red = {CVAR_SAVE, "crosshair_color_red", "1", "customizable crosshair color"};
100 cvar_t crosshair_color_green = {CVAR_SAVE, "crosshair_color_green", "0", "customizable crosshair color"};
101 cvar_t crosshair_color_blue = {CVAR_SAVE, "crosshair_color_blue", "0", "customizable crosshair color"};
102 cvar_t crosshair_color_alpha = {CVAR_SAVE, "crosshair_color_alpha", "1", "how opaque the crosshair should be"};
103 cvar_t crosshair_size = {CVAR_SAVE, "crosshair_size", "1", "adjusts size of the crosshair on the screen"};
105 void Sbar_MiniDeathmatchOverlay (int x, int y);
106 void Sbar_DeathmatchOverlay (void);
107 void Sbar_IntermissionOverlay (void);
108 void Sbar_FinaleOverlay (void);
118 void Sbar_ShowScores (void)
122 sb_showscores = true;
132 void Sbar_DontShowScores (void)
134 sb_showscores = false;
137 void sbar_start(void)
141 if (gamemode == GAME_NETHERWORLD)
144 else if (gamemode == GAME_SOM)
146 sb_disc = Draw_CachePic("gfx/disc", true);
148 for (i = 0;i < 10;i++)
149 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
151 somsb_health = Draw_CachePic("gfx/hud_health", true);
152 somsb_ammo[0] = Draw_CachePic("gfx/sb_shells", true);
153 somsb_ammo[1] = Draw_CachePic("gfx/sb_nails", true);
154 somsb_ammo[2] = Draw_CachePic("gfx/sb_rocket", true);
155 somsb_ammo[3] = Draw_CachePic("gfx/sb_cells", true);
156 somsb_armor[0] = Draw_CachePic("gfx/sb_armor1", true);
157 somsb_armor[1] = Draw_CachePic("gfx/sb_armor2", true);
158 somsb_armor[2] = Draw_CachePic("gfx/sb_armor3", true);
160 else if (gamemode == GAME_NEXUIZ)
162 for (i = 0;i < 10;i++)
163 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
164 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus", true);
166 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells", true);
167 sb_ammo[1] = Draw_CachePic ("gfx/sb_bullets", true);
168 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket", true);
169 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells", true);
171 sb_items[2] = Draw_CachePic ("gfx/sb_slowmo", true);
172 sb_items[3] = Draw_CachePic ("gfx/sb_invinc", true);
173 sb_items[4] = Draw_CachePic ("gfx/sb_energy", true);
174 sb_items[5] = Draw_CachePic ("gfx/sb_str", true);
176 sb_items[11] = Draw_CachePic ("gfx/sb_flag_red_taken", true);
177 sb_items[12] = Draw_CachePic ("gfx/sb_flag_red_lost", true);
178 sb_items[13] = Draw_CachePic ("gfx/sb_flag_red_carrying", true);
179 sb_items[14] = Draw_CachePic ("gfx/sb_key_carrying", true);
180 sb_items[15] = Draw_CachePic ("gfx/sb_flag_blue_taken", true);
181 sb_items[16] = Draw_CachePic ("gfx/sb_flag_blue_lost", true);
182 sb_items[17] = Draw_CachePic ("gfx/sb_flag_blue_carrying", true);
184 sb_sbar = Draw_CachePic("gfx/sbar", true);
185 sb_sbar_minimal = Draw_CachePic("gfx/sbar_minimal", true);
186 sb_sbar_overlay = Draw_CachePic("gfx/sbar_overlay", true);
188 for(i = 0; i < 9;i++)
189 sb_weapons[0][i] = Draw_CachePic(va("gfx/inv_weapon%i",i), true);
191 else if (gamemode == GAME_ZYMOTIC)
193 zymsb_crosshair_center = Draw_CachePic ("gfx/hud/crosshair_center", true);
194 zymsb_crosshair_line = Draw_CachePic ("gfx/hud/crosshair_line", true);
195 zymsb_crosshair_health = Draw_CachePic ("gfx/hud/crosshair_health", true);
196 zymsb_crosshair_clip = Draw_CachePic ("gfx/hud/crosshair_clip", true);
197 zymsb_crosshair_ammo = Draw_CachePic ("gfx/hud/crosshair_ammo", true);
198 zymsb_crosshair_background = Draw_CachePic ("gfx/hud/crosshair_background", true);
199 zymsb_crosshair_left1 = Draw_CachePic ("gfx/hud/crosshair_left1", true);
200 zymsb_crosshair_left2 = Draw_CachePic ("gfx/hud/crosshair_left2", true);
201 zymsb_crosshair_right = Draw_CachePic ("gfx/hud/crosshair_right", true);
205 sb_disc = Draw_CachePic("gfx/disc", true);
207 for (i = 0;i < 10;i++)
209 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
210 sb_nums[1][i] = Draw_CachePic (va("gfx/anum_%i",i), true);
213 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus", true);
214 sb_nums[1][10] = Draw_CachePic ("gfx/anum_minus", true);
216 sb_colon = Draw_CachePic ("gfx/num_colon", true);
217 sb_slash = Draw_CachePic ("gfx/num_slash", true);
219 sb_weapons[0][0] = Draw_CachePic ("gfx/inv_shotgun", true);
220 sb_weapons[0][1] = Draw_CachePic ("gfx/inv_sshotgun", true);
221 sb_weapons[0][2] = Draw_CachePic ("gfx/inv_nailgun", true);
222 sb_weapons[0][3] = Draw_CachePic ("gfx/inv_snailgun", true);
223 sb_weapons[0][4] = Draw_CachePic ("gfx/inv_rlaunch", true);
224 sb_weapons[0][5] = Draw_CachePic ("gfx/inv_srlaunch", true);
225 sb_weapons[0][6] = Draw_CachePic ("gfx/inv_lightng", true);
227 sb_weapons[1][0] = Draw_CachePic ("gfx/inv2_shotgun", true);
228 sb_weapons[1][1] = Draw_CachePic ("gfx/inv2_sshotgun", true);
229 sb_weapons[1][2] = Draw_CachePic ("gfx/inv2_nailgun", true);
230 sb_weapons[1][3] = Draw_CachePic ("gfx/inv2_snailgun", true);
231 sb_weapons[1][4] = Draw_CachePic ("gfx/inv2_rlaunch", true);
232 sb_weapons[1][5] = Draw_CachePic ("gfx/inv2_srlaunch", true);
233 sb_weapons[1][6] = Draw_CachePic ("gfx/inv2_lightng", true);
235 for (i = 0;i < 5;i++)
237 sb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_shotgun",i+1), true);
238 sb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_sshotgun",i+1), true);
239 sb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_nailgun",i+1), true);
240 sb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_snailgun",i+1), true);
241 sb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_rlaunch",i+1), true);
242 sb_weapons[2+i][5] = Draw_CachePic (va("gfx/inva%i_srlaunch",i+1), true);
243 sb_weapons[2+i][6] = Draw_CachePic (va("gfx/inva%i_lightng",i+1), true);
246 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells", true);
247 sb_ammo[1] = Draw_CachePic ("gfx/sb_nails", true);
248 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket", true);
249 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells", true);
251 sb_armor[0] = Draw_CachePic ("gfx/sb_armor1", true);
252 sb_armor[1] = Draw_CachePic ("gfx/sb_armor2", true);
253 sb_armor[2] = Draw_CachePic ("gfx/sb_armor3", true);
255 sb_items[0] = Draw_CachePic ("gfx/sb_key1", true);
256 sb_items[1] = Draw_CachePic ("gfx/sb_key2", true);
257 sb_items[2] = Draw_CachePic ("gfx/sb_invis", true);
258 sb_items[3] = Draw_CachePic ("gfx/sb_invuln", true);
259 sb_items[4] = Draw_CachePic ("gfx/sb_suit", true);
260 sb_items[5] = Draw_CachePic ("gfx/sb_quad", true);
262 sb_sigil[0] = Draw_CachePic ("gfx/sb_sigil1", true);
263 sb_sigil[1] = Draw_CachePic ("gfx/sb_sigil2", true);
264 sb_sigil[2] = Draw_CachePic ("gfx/sb_sigil3", true);
265 sb_sigil[3] = Draw_CachePic ("gfx/sb_sigil4", true);
267 sb_faces[4][0] = Draw_CachePic ("gfx/face1", true);
268 sb_faces[4][1] = Draw_CachePic ("gfx/face_p1", true);
269 sb_faces[3][0] = Draw_CachePic ("gfx/face2", true);
270 sb_faces[3][1] = Draw_CachePic ("gfx/face_p2", true);
271 sb_faces[2][0] = Draw_CachePic ("gfx/face3", true);
272 sb_faces[2][1] = Draw_CachePic ("gfx/face_p3", true);
273 sb_faces[1][0] = Draw_CachePic ("gfx/face4", true);
274 sb_faces[1][1] = Draw_CachePic ("gfx/face_p4", true);
275 sb_faces[0][0] = Draw_CachePic ("gfx/face5", true);
276 sb_faces[0][1] = Draw_CachePic ("gfx/face_p5", true);
278 sb_face_invis = Draw_CachePic ("gfx/face_invis", true);
279 sb_face_invuln = Draw_CachePic ("gfx/face_invul2", true);
280 sb_face_invis_invuln = Draw_CachePic ("gfx/face_inv2", true);
281 sb_face_quad = Draw_CachePic ("gfx/face_quad", true);
283 sb_sbar = Draw_CachePic ("gfx/sbar", true);
284 sb_ibar = Draw_CachePic ("gfx/ibar", true);
285 sb_scorebar = Draw_CachePic ("gfx/scorebar", true);
287 //MED 01/04/97 added new hipnotic weapons
288 if (gamemode == GAME_HIPNOTIC)
290 hsb_weapons[0][0] = Draw_CachePic ("gfx/inv_laser", true);
291 hsb_weapons[0][1] = Draw_CachePic ("gfx/inv_mjolnir", true);
292 hsb_weapons[0][2] = Draw_CachePic ("gfx/inv_gren_prox", true);
293 hsb_weapons[0][3] = Draw_CachePic ("gfx/inv_prox_gren", true);
294 hsb_weapons[0][4] = Draw_CachePic ("gfx/inv_prox", true);
296 hsb_weapons[1][0] = Draw_CachePic ("gfx/inv2_laser", true);
297 hsb_weapons[1][1] = Draw_CachePic ("gfx/inv2_mjolnir", true);
298 hsb_weapons[1][2] = Draw_CachePic ("gfx/inv2_gren_prox", true);
299 hsb_weapons[1][3] = Draw_CachePic ("gfx/inv2_prox_gren", true);
300 hsb_weapons[1][4] = Draw_CachePic ("gfx/inv2_prox", true);
302 for (i = 0;i < 5;i++)
304 hsb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_laser",i+1), true);
305 hsb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_mjolnir",i+1), true);
306 hsb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_gren_prox",i+1), true);
307 hsb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_prox_gren",i+1), true);
308 hsb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_prox",i+1), true);
311 hsb_items[0] = Draw_CachePic ("gfx/sb_wsuit", true);
312 hsb_items[1] = Draw_CachePic ("gfx/sb_eshld", true);
314 else if (gamemode == GAME_ROGUE)
316 rsb_invbar[0] = Draw_CachePic ("gfx/r_invbar1", true);
317 rsb_invbar[1] = Draw_CachePic ("gfx/r_invbar2", true);
319 rsb_weapons[0] = Draw_CachePic ("gfx/r_lava", true);
320 rsb_weapons[1] = Draw_CachePic ("gfx/r_superlava", true);
321 rsb_weapons[2] = Draw_CachePic ("gfx/r_gren", true);
322 rsb_weapons[3] = Draw_CachePic ("gfx/r_multirock", true);
323 rsb_weapons[4] = Draw_CachePic ("gfx/r_plasma", true);
325 rsb_items[0] = Draw_CachePic ("gfx/r_shield1", true);
326 rsb_items[1] = Draw_CachePic ("gfx/r_agrav1", true);
328 // PGM 01/19/97 - team color border
329 rsb_teambord = Draw_CachePic ("gfx/r_teambord", true);
330 // PGM 01/19/97 - team color border
332 rsb_ammo[0] = Draw_CachePic ("gfx/r_ammolava", true);
333 rsb_ammo[1] = Draw_CachePic ("gfx/r_ammomulti", true);
334 rsb_ammo[2] = Draw_CachePic ("gfx/r_ammoplasma", true);
338 sb_ranking = Draw_CachePic ("gfx/ranking", true);
339 sb_complete = Draw_CachePic ("gfx/complete", true);
340 sb_inter = Draw_CachePic ("gfx/inter", true);
341 sb_finale = Draw_CachePic ("gfx/finale", true);
344 void sbar_shutdown(void)
348 void sbar_newmap(void)
352 void Sbar_Init (void)
354 Cmd_AddCommand("+showscores", Sbar_ShowScores, "show scoreboard");
355 Cmd_AddCommand("-showscores", Sbar_DontShowScores, "hide scoreboard");
356 Cvar_RegisterVariable(&showfps);
357 Cvar_RegisterVariable(&showtime);
358 Cvar_RegisterVariable(&showtime_format);
359 Cvar_RegisterVariable(&showdate);
360 Cvar_RegisterVariable(&showdate_format);
361 Cvar_RegisterVariable(&sbar_alpha_bg);
362 Cvar_RegisterVariable(&sbar_alpha_fg);
363 Cvar_RegisterVariable(&cl_deathscoreboard);
365 Cvar_RegisterVariable(&crosshair_color_red);
366 Cvar_RegisterVariable(&crosshair_color_green);
367 Cvar_RegisterVariable(&crosshair_color_blue);
368 Cvar_RegisterVariable(&crosshair_color_alpha);
369 Cvar_RegisterVariable(&crosshair_size);
371 R_RegisterModule("sbar", sbar_start, sbar_shutdown, sbar_newmap);
375 //=============================================================================
377 // drawing routines are relative to the status bar location
386 void Sbar_DrawPic (int x, int y, cachepic_t *pic)
388 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, sbar_alpha_fg.value, 0);
391 void Sbar_DrawAlphaPic (int x, int y, cachepic_t *pic, float alpha)
393 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, alpha, 0);
400 Draws one solid graphics character
403 void Sbar_DrawCharacter (int x, int y, int num)
405 DrawQ_String (sbar_x + x + 4 , sbar_y + y, va("%c", num), 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0, NULL, true);
413 void Sbar_DrawString (int x, int y, char *str)
415 DrawQ_String (sbar_x + x, sbar_y + y, str, 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0, NULL, true);
423 void Sbar_DrawNum (int x, int y, int num, int digits, int color)
428 l = sprintf(str, "%i", num);
442 Sbar_DrawPic (x, y, sb_nums[color][frame]);
455 void Sbar_DrawXNum (int x, int y, int num, int digits, int lettersize, float r, float g, float b, float a, int flags)
460 l = sprintf(str, "%i", num);
465 x += (digits-l) * lettersize;
474 DrawQ_Pic (sbar_x + x, sbar_y + y, sb_nums[0][frame],lettersize,lettersize,r,g,b,a * sbar_alpha_fg.value,flags);
481 //=============================================================================
484 int Sbar_IsTeammatch()
486 // currently only nexuiz uses the team score board
487 return ((gamemode == GAME_NEXUIZ)
488 && (teamplay.integer > 0));
496 static int fragsort[MAX_SCOREBOARD];
497 static int scoreboardlines;
499 //[515]: Sbar_GetPlayer for csqc "getplayerkey" func
500 int Sbar_GetPlayer (int index)
505 if(index >= scoreboardlines)
507 index = fragsort[index];
509 if(index >= scoreboardlines)
514 static scoreboard_t teams[MAX_SCOREBOARD];
515 static int teamsort[MAX_SCOREBOARD];
516 static int teamlines;
517 void Sbar_SortFrags (void)
523 for (i=0 ; i<cl.maxclients ; i++)
525 if (cl.scores[i].name[0])
527 fragsort[scoreboardlines] = i;
532 for (i=0 ; i<scoreboardlines ; i++)
533 for (j=0 ; j<scoreboardlines-1-i ; j++)
534 if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j+1]].frags)
537 fragsort[j] = fragsort[j+1];
542 if (Sbar_IsTeammatch ())
544 // now sort players by teams.
545 for (i=0 ; i<scoreboardlines ; i++)
547 for (j=0 ; j<scoreboardlines-1-i ; j++)
549 if (cl.scores[fragsort[j]].colors < cl.scores[fragsort[j+1]].colors)
552 fragsort[j] = fragsort[j+1];
558 // calculate team scores
560 for (i=0 ; i<scoreboardlines ; i++)
562 if (color != (cl.scores[fragsort[i]].colors & 15))
564 const char* teamname;
566 color = cl.scores[fragsort[i]].colors & 15;
572 teamname = "^1Red Team";
575 teamname = "^4Blue Team";
578 teamname = "^6Pink Team";
581 teamname = "^3Yellow Team";
584 teamname = "Total Team Score";
587 strlcpy(teams[teamlines-1].name, teamname, sizeof(teams[teamlines-1].name));
589 teams[teamlines-1].frags = 0;
590 teams[teamlines-1].colors = color + 16 * color;
593 if (cl.scores[fragsort[i]].frags != -666)
595 // do not add spedcators
596 // (ugly hack for nexuiz)
597 teams[teamlines-1].frags += cl.scores[fragsort[i]].frags;
601 // now sort teams by scores.
602 for (i=0 ; i<teamlines ; i++)
604 for (i=0 ; i<teamlines ; i++)
606 for (j=0 ; j<teamlines-1-i ; j++)
608 if (teams[teamsort[j]].frags < teams[teamsort[j+1]].frags)
611 teamsort[j] = teamsort[j+1];
624 void Sbar_SoloScoreboard (void)
627 char str[80], timestr[40];
629 int minutes, seconds;
632 t = (cl.intermission ? cl.completed_time : cl.time);
633 minutes = (int)(t / 60);
634 seconds = (int)(t - 60*floor(t/60));
636 // monsters and secrets are now both on the top row
637 if (gamemode != GAME_NEXUIZ)
638 Sbar_DrawString(8, 4, va("Monsters:%3i /%3i Secrets :%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS], cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]));
640 // figure out the map's filename without path or extension
641 strlcpy(str, FS_FileWithoutPath(cl.worldmodel ? cl.worldmodel->name : ""), sizeof(str));
642 if (strrchr(str, '.'))
643 *(strrchr(str, '.')) = 0;
645 // append a : separator and then the full title
646 strlcat(str, ":", sizeof(str));
647 strlcat(str, cl.levelname, sizeof(str));
649 // make the time string
650 max = 38 - sprintf(timestr, " %i:%02i", minutes, seconds);
652 // if there's a newline character, terminate the string there
653 if (strchr(str, '\n'))
654 *(strchr(str, '\n')) = 0;
656 // pad with spaces to fill the allotted space and append the time
657 i = bound(0, (int)strlen(str), max);
661 strlcat(str, timestr, sizeof(str));
663 // print the line of text
664 Sbar_DrawString(8, 12, str);
668 int minutes, seconds, tens, units;
671 if (gamemode != GAME_NEXUIZ) {
672 sprintf (str,"Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
673 Sbar_DrawString (8, 4, str);
675 sprintf (str,"Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
676 Sbar_DrawString (8, 12, str);
680 minutes = (int)(cl.time / 60);
681 seconds = (int)(cl.time - 60*minutes);
683 units = seconds - 10*tens;
684 sprintf (str,"Time :%3i:%i%i", minutes, tens, units);
685 Sbar_DrawString (184, 4, str);
688 if (gamemode == GAME_NEXUIZ) {
689 l = (int) strlen (cl.worldmodel->name);
690 Sbar_DrawString (232 - l*4, 12, cl.worldmodel->name);
692 l = (int) strlen (cl.levelname);
693 Sbar_DrawString (232 - l*4, 12, cl.levelname);
703 void Sbar_DrawScoreboard (void)
705 Sbar_SoloScoreboard ();
706 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
707 //if (cl.gametype == GAME_DEATHMATCH)
709 Sbar_DeathmatchOverlay ();
712 //=============================================================================
714 // AK to make DrawInventory smaller
715 static void Sbar_DrawWeapon(int nr, float fade, int active)
717 // width = 300, height = 100
718 const int w_width = 300, w_height = 100, w_space = 10;
719 const float w_scale = 0.4;
721 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);
722 //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);
730 void Sbar_DrawInventory (void)
737 if (gamemode == GAME_ROGUE)
739 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
740 Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], sbar_alpha_bg.value);
742 Sbar_DrawAlphaPic (0, -24, rsb_invbar[1], sbar_alpha_bg.value);
745 Sbar_DrawAlphaPic (0, -24, sb_ibar, sbar_alpha_bg.value);
748 for (i=0 ; i<7 ; i++)
750 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<i) )
752 time = cl.item_gettime[i];
753 flashon = (int)(max(0, cl.time - time)*10);
756 if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i) )
762 flashon = (flashon%5) + 2;
764 Sbar_DrawAlphaPic (i*24, -16, sb_weapons[flashon][i], sbar_alpha_bg.value);
770 if (gamemode == GAME_HIPNOTIC)
772 int grenadeflashing=0;
773 for (i=0 ; i<4 ; i++)
775 if (cl.stats[STAT_ITEMS] & (1<<hipweapons[i]) )
777 time = max(0, cl.item_gettime[hipweapons[i]]);
778 flashon = (int)((cl.time - time)*10);
781 if ( cl.stats[STAT_ACTIVEWEAPON] == (1<<hipweapons[i]) )
787 flashon = (flashon%5) + 2;
789 // check grenade launcher
792 if (cl.stats[STAT_ITEMS] & HIT_PROXIMITY_GUN)
797 Sbar_DrawPic (96, -16, hsb_weapons[flashon][2]);
803 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<4))
805 if (!grenadeflashing)
806 Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
809 Sbar_DrawPic (96, -16, hsb_weapons[flashon][4]);
812 Sbar_DrawPic (176 + (i*24), -16, hsb_weapons[flashon][i]);
817 if (gamemode == GAME_ROGUE)
819 // check for powered up weapon.
820 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
822 if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i))
823 Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]);
827 for (i=0 ; i<4 ; i++)
829 sprintf (num, "%3i",cl.stats[STAT_SHELLS+i] );
831 Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[0] - '0');
833 Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[1] - '0');
835 Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0');
839 for (i=0 ; i<6 ; i++)
840 if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
842 //MED 01/04/97 changed keys
843 if (gamemode != GAME_HIPNOTIC || (i>1))
844 Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
847 //MED 01/04/97 added hipnotic items
849 if (gamemode == GAME_HIPNOTIC)
851 for (i=0 ; i<2 ; i++)
852 if (cl.stats[STAT_ITEMS] & (1<<(24+i)))
853 Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
856 if (gamemode == GAME_ROGUE)
859 for (i=0 ; i<2 ; i++)
860 if (cl.stats[STAT_ITEMS] & (1<<(29+i)))
861 Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
866 for (i=0 ; i<4 ; i++)
867 if (cl.stats[STAT_ITEMS] & (1<<(28+i)))
868 Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
872 //=============================================================================
879 void Sbar_DrawFrags (void)
889 l = min(scoreboardlines, 4);
893 for (i = 0;i < l;i++)
899 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
900 DrawQ_Fill (sbar_x + x + 10, sbar_y - 23, 28, 4, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
901 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
902 DrawQ_Fill (sbar_x + x + 10, sbar_y + 4 - 23, 28, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
906 sprintf (num, "%3i",f);
908 if (k == cl.viewentity - 1)
910 Sbar_DrawCharacter ( x + 2, -24, 16);
911 Sbar_DrawCharacter ( x + 32 - 4, -24, 17);
913 Sbar_DrawCharacter (x + 8, -24, num[0]);
914 Sbar_DrawCharacter (x + 16, -24, num[1]);
915 Sbar_DrawCharacter (x + 24, -24, num[2]);
920 //=============================================================================
928 void Sbar_DrawFace (void)
932 // PGM 01/19/97 - team color drawing
933 // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
934 if (gamemode == GAME_ROGUE && !cl.islocalgame && (teamplay.integer > 3) && (teamplay.integer < 7))
940 s = &cl.scores[cl.viewentity - 1];
942 Sbar_DrawPic (112, 0, rsb_teambord);
943 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
944 DrawQ_Fill (sbar_x + 113, vid_conheight.integer-SBAR_HEIGHT+3, 22, 9, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
945 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
946 DrawQ_Fill (sbar_x + 113, vid_conheight.integer-SBAR_HEIGHT+12, 22, 9, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
950 sprintf (num, "%3i",f);
952 if ((s->colors & 0xf0)==0)
955 Sbar_DrawCharacter(109, 3, 18 + num[0] - '0');
957 Sbar_DrawCharacter(116, 3, 18 + num[1] - '0');
959 Sbar_DrawCharacter(123, 3, 18 + num[2] - '0');
963 Sbar_DrawCharacter ( 109, 3, num[0]);
964 Sbar_DrawCharacter ( 116, 3, num[1]);
965 Sbar_DrawCharacter ( 123, 3, num[2]);
970 // PGM 01/19/97 - team color drawing
972 if ( (cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
973 Sbar_DrawPic (112, 0, sb_face_invis_invuln);
974 else if (cl.stats[STAT_ITEMS] & IT_QUAD)
975 Sbar_DrawPic (112, 0, sb_face_quad );
976 else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
977 Sbar_DrawPic (112, 0, sb_face_invis );
978 else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
979 Sbar_DrawPic (112, 0, sb_face_invuln);
982 f = cl.stats[STAT_HEALTH] / 20;
984 Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]);
988 void Sbar_ShowFPS(void)
990 float fps_x, fps_y, fps_scalex, fps_scaley, fps_height;
994 qboolean red = false;
1001 static double nexttime = 0, lasttime = 0;
1002 static double framerate = 0;
1003 static int framecount = 0;
1006 if (newtime >= nexttime)
1008 framerate = framecount / (newtime - lasttime);
1010 nexttime = max(nexttime + 1, lasttime - 1);
1016 if ((red = (calc < 1.0f)))
1017 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0f / calc + 0.5));
1019 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(calc + 0.5));
1021 if (showtime.integer)
1022 strlcpy(timestring, Sys_TimeString(showtime_format.string), sizeof(timestring));
1023 if (showdate.integer)
1024 strlcpy(datestring, Sys_TimeString(showdate_format.string), sizeof(datestring));
1025 if (fpsstring[0] || timestring[0])
1029 fps_height = fps_scaley * ((fpsstring[0] != 0) + (timestring[0] != 0) + (datestring[0] != 0));
1030 //fps_y = vid_conheight.integer - sb_lines; // yes this may draw over the sbar
1031 //fps_y = bound(0, fps_y, vid_conheight.integer - fps_height);
1032 fps_y = vid_conheight.integer - fps_height;
1035 fps_x = vid_conwidth.integer - fps_scalex * strlen(fpsstring);
1036 DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(fpsstring), fps_scaley, 0, 0, 0, 0.5, 0);
1038 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 0, 0, 1, 0, NULL, true);
1040 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true);
1041 fps_y += fps_scaley;
1045 fps_x = vid_conwidth.integer - fps_scalex * strlen(timestring);
1046 DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(timestring), fps_scaley, 0, 0, 0, 0.5, 0);
1047 DrawQ_String(fps_x, fps_y, timestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true);
1048 fps_y += fps_scaley;
1052 fps_x = vid_conwidth.integer - fps_scalex * strlen(datestring);
1053 DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(datestring), fps_scaley, 0, 0, 0, 0.5, 0);
1054 DrawQ_String(fps_x, fps_y, datestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true);
1055 fps_y += fps_scaley;
1060 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)
1063 c2 = bound(0, c2, 1);
1064 c1 = bound(0, c1, 1 - c2);
1066 r[1] = rangey + rangeheight * (c2 + c1);
1067 r[2] = rangey + rangeheight * (c2);
1071 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);
1073 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);
1075 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);
1077 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);
1085 extern float v_dmg_time, v_dmg_roll, v_dmg_pitch;
1086 extern cvar_t v_kicktime;
1087 void Sbar_Draw (void)
1091 if(cl.csqc_vidvars.drawenginesbar) //[515]: csqc drawsbar
1093 if (cl.intermission == 1)
1095 if(gamemode == GAME_NEXUIZ) // display full scoreboard (that is, show scores + map name)
1097 Sbar_DrawScoreboard();
1100 Sbar_IntermissionOverlay();
1103 else if (cl.intermission == 2)
1105 if(gamemode == GAME_NEXUIZ) // Nexuiz allows TAB to override the voting screens to recall the scores
1108 Sbar_DrawScoreboard();
1111 Sbar_FinaleOverlay();
1115 if (gamemode == GAME_NETHERWORLD)
1118 else if (gamemode == GAME_SOM)
1120 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1121 Sbar_DrawScoreboard ();
1124 // this is the top left of the sbar area
1126 sbar_y = vid_conheight.integer - 24*3;
1129 if (cl.stats[STAT_ARMOR])
1131 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1132 Sbar_DrawPic(0, 0, somsb_armor[2]);
1133 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1134 Sbar_DrawPic(0, 0, somsb_armor[1]);
1135 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1136 Sbar_DrawPic(0, 0, somsb_armor[0]);
1137 Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1141 Sbar_DrawPic(0, 24, somsb_health);
1142 Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1145 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1146 Sbar_DrawPic(0, 48, somsb_ammo[0]);
1147 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1148 Sbar_DrawPic(0, 48, somsb_ammo[1]);
1149 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1150 Sbar_DrawPic(0, 48, somsb_ammo[2]);
1151 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1152 Sbar_DrawPic(0, 48, somsb_ammo[3]);
1153 Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
1154 if (cl.stats[STAT_SHELLS])
1155 Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
1158 else if (gamemode == GAME_NEXUIZ)
1160 sbar_y = vid_conheight.integer - 47;
1161 sbar_x = (vid_conwidth.integer - 640)/2;
1163 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1165 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1166 Sbar_DrawScoreboard ();
1172 int redflag, blueflag;
1174 // calculate intensity to draw weapons bar at
1175 fade = 3 - 2 * (cl.time - cl.weapontime);
1178 fade = min(fade, 1);
1179 for (i = 0; i < 8;i++)
1180 if (cl.stats[STAT_ITEMS] & (1 << i))
1181 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1183 if((cl.stats[STAT_ITEMS] & (1<<12)))
1184 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1187 //if (!cl.islocalgame)
1188 // Sbar_DrawFrags ();
1191 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1193 Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1196 redflag = ((cl.stats[STAT_ITEMS]>>15) & 3);
1197 blueflag = ((cl.stats[STAT_ITEMS]>>17) & 3);
1198 if (redflag == 3 && blueflag == 3)
1200 // The Impossible Combination[tm]
1201 // Can only happen in Key Hunt mode...
1202 Sbar_DrawPic (10 - sbar_x, -179, sb_items[14]);
1207 Sbar_DrawPic (10 - sbar_x, -109, sb_items[redflag+10]);
1209 Sbar_DrawPic (10 - sbar_x, -169, sb_items[blueflag+14]);
1213 Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1216 if(cl.stats[STAT_HEALTH] > 100)
1217 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1218 else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1219 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1221 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1223 // AK dont draw ammo for the laser
1224 if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1226 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1227 Sbar_DrawPic (519, 0, sb_ammo[0]);
1228 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1229 Sbar_DrawPic (519, 0, sb_ammo[1]);
1230 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1231 Sbar_DrawPic (519, 0, sb_ammo[2]);
1232 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1233 Sbar_DrawPic (519, 0, sb_ammo[3]);
1235 if(cl.stats[STAT_AMMO] <= 10)
1236 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1238 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1243 DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1246 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1247 // Sbar_MiniDeathmatchOverlay (0, 17);
1249 else if (gamemode == GAME_ZYMOTIC)
1252 float scale = 64.0f / 256.0f;
1253 float kickoffset[3];
1254 VectorClear(kickoffset);
1257 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1258 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1260 sbar_x = (int)((vid_conwidth.integer - 256 * scale)/2 + kickoffset[0]);
1261 sbar_y = (int)((vid_conheight.integer - 256 * scale)/2 + kickoffset[1]);
1262 // left1 16, 48 : 126 -66
1263 // left2 16, 128 : 196 -66
1264 // right 176, 48 : 196 -136
1265 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);
1266 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);
1267 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);
1268 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1270 float scale = 128.0f / 256.0f;
1271 float healthstart, healthheight, healthstarttc, healthendtc;
1272 float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1273 float ammostart, ammoheight, ammostarttc, ammoendtc;
1274 float clipstart, clipheight, clipstarttc, clipendtc;
1275 float kickoffset[3], offset;
1276 VectorClear(kickoffset);
1279 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1280 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1282 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1283 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1284 offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1285 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);
1286 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);
1287 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);
1288 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);
1289 healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1290 shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1291 healthstart = 204 - healthheight;
1292 shieldstart = healthstart - shieldheight;
1293 healthstarttc = healthstart * (1.0f / 256.0f);
1294 healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1295 shieldstarttc = shieldstart * (1.0f / 256.0f);
1296 shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1297 ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1298 ammostart = 114 - ammoheight;
1299 ammostarttc = ammostart * (1.0f / 256.0f);
1300 ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1301 clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1302 clipstart = 190 - clipheight;
1303 clipstarttc = clipstart * (1.0f / 256.0f);
1304 clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1305 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);
1306 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);
1307 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);
1308 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);
1309 DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1310 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1313 else // Quake and others
1315 sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1316 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1317 //if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1318 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1321 sbar_x = (vid_conwidth.integer - 320)/2;
1325 if (gamemode != GAME_GOODVSBAD2)
1326 Sbar_DrawInventory ();
1327 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1331 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1333 if (gamemode != GAME_GOODVSBAD2)
1334 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1335 Sbar_DrawScoreboard ();
1339 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1341 // keys (hipnotic only)
1342 //MED 01/04/97 moved keys here so they would not be overwritten
1343 if (gamemode == GAME_HIPNOTIC)
1345 if (cl.stats[STAT_ITEMS] & IT_KEY1)
1346 Sbar_DrawPic (209, 3, sb_items[0]);
1347 if (cl.stats[STAT_ITEMS] & IT_KEY2)
1348 Sbar_DrawPic (209, 12, sb_items[1]);
1351 if (gamemode != GAME_GOODVSBAD2)
1353 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1355 Sbar_DrawNum (24, 0, 666, 3, 1);
1356 Sbar_DrawPic (0, 0, sb_disc);
1360 if (gamemode == GAME_ROGUE)
1362 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1363 if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1364 Sbar_DrawPic (0, 0, sb_armor[2]);
1365 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1366 Sbar_DrawPic (0, 0, sb_armor[1]);
1367 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1368 Sbar_DrawPic (0, 0, sb_armor[0]);
1372 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1373 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1374 Sbar_DrawPic (0, 0, sb_armor[2]);
1375 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1376 Sbar_DrawPic (0, 0, sb_armor[1]);
1377 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1378 Sbar_DrawPic (0, 0, sb_armor[0]);
1387 Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1390 if (gamemode == GAME_ROGUE)
1392 if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1393 Sbar_DrawPic (224, 0, sb_ammo[0]);
1394 else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1395 Sbar_DrawPic (224, 0, sb_ammo[1]);
1396 else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1397 Sbar_DrawPic (224, 0, sb_ammo[2]);
1398 else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1399 Sbar_DrawPic (224, 0, sb_ammo[3]);
1400 else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1401 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1402 else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1403 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1404 else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1405 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1409 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1410 Sbar_DrawPic (224, 0, sb_ammo[0]);
1411 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1412 Sbar_DrawPic (224, 0, sb_ammo[1]);
1413 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1414 Sbar_DrawPic (224, 0, sb_ammo[2]);
1415 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1416 Sbar_DrawPic (224, 0, sb_ammo[3]);
1419 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1423 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1424 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1425 if (!cl.islocalgame && vid_conwidth.integer > 320)
1427 if (gamemode == GAME_TRANSFUSION)
1428 Sbar_MiniDeathmatchOverlay (0, 0);
1430 Sbar_MiniDeathmatchOverlay (324, vid_conheight.integer - sb_lines);
1437 if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && crosshair.integer <= NUMCROSSHAIRS && !cl.intermission && !r_letterbox.value && (pic = r_crosshairs[crosshair.integer]))
1438 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);
1440 if (cl_prydoncursor.integer)
1441 DrawQ_Pic((cl.cmd.cursor_screen[0] + 1) * 0.5 * vid_conwidth.integer, (cl.cmd.cursor_screen[1] + 1) * 0.5 * vid_conheight.integer, Draw_CachePic(va("gfx/prydoncursor%03i", cl_prydoncursor.integer), true), 0, 0, 1, 1, 1, 1, 0);
1444 //=============================================================================
1448 Sbar_DeathmatchOverlay
1452 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1456 minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : cl.time - s->qw_entertime) / 60.0);
1457 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1459 if (s->qw_spectator)
1461 if (s->qw_ping || s->qw_packetloss)
1462 DrawQ_String(x, y, va("%4i %3i %4i spectator %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes, (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1464 DrawQ_String(x, y, va(" %4i spectator %c%s", minutes, (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1468 // draw colors behind score
1469 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1470 DrawQ_Fill(x + 14*8, y+1, 40, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
1471 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1472 DrawQ_Fill(x + 14*8, y+4, 40, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
1474 //DrawQ_String(x, y, va("%c%4i %s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, true);
1475 if (s->qw_ping || s->qw_packetloss)
1476 DrawQ_String(x, y, va("%4i %3i %4i %5i %-4s %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1478 DrawQ_String(x, y, va(" %4i %5i %-4s %c%s", minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1483 if (s->qw_spectator)
1485 if (s->qw_ping || s->qw_packetloss)
1486 DrawQ_String(x, y, va("%4i %3i spect %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1488 DrawQ_String(x, y, va(" spect %c%s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1492 // draw colors behind score
1493 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1494 DrawQ_Fill(x + 9*8, y+1, 40, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
1495 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1496 DrawQ_Fill(x + 9*8, y+4, 40, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
1498 //DrawQ_String(x, y, va("%c%4i %s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, true);
1499 if (s->qw_ping || s->qw_packetloss)
1500 DrawQ_String(x, y, va("%4i %3i %5i %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), (int) s->frags, (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1502 DrawQ_String(x, y, va(" %5i %c%s", (int) s->frags, (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1508 void Sbar_DeathmatchOverlay (void)
1512 // request new ping times every two second
1513 if (cl.last_ping_request < realtime - 2 && cls.netcon)
1515 cl.last_ping_request = realtime;
1516 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1518 MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
1519 MSG_WriteString(&cls.netcon->message, "pings");
1521 else if (cls.protocol == PROTOCOL_QUAKE || cls.protocol == PROTOCOL_QUAKEDP || cls.protocol == PROTOCOL_NEHAHRAMOVIE || cls.protocol == PROTOCOL_DARKPLACES1 || cls.protocol == PROTOCOL_DARKPLACES2 || cls.protocol == PROTOCOL_DARKPLACES3 || cls.protocol == PROTOCOL_DARKPLACES4 || cls.protocol == PROTOCOL_DARKPLACES5 || cls.protocol == PROTOCOL_DARKPLACES6/* || cls.protocol == PROTOCOL_DARKPLACES7*/)
1523 // 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
1524 static int ping_anyway_counter = 0;
1525 if(cl.parsingtextexpectingpingforscores == 1)
1527 Con_DPrintf("want to send ping, but still waiting for other reply\n");
1528 if(++ping_anyway_counter >= 5)
1529 cl.parsingtextexpectingpingforscores = 0;
1531 if(cl.parsingtextexpectingpingforscores != 1)
1533 ping_anyway_counter = 0;
1534 cl.parsingtextexpectingpingforscores = 1; // hide the output of the next ping report
1535 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1536 MSG_WriteString(&cls.netcon->message, "ping");
1541 // 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
1542 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1543 MSG_WriteString(&cls.netcon->message, "pings");
1547 DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1553 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1555 x = (vid_conwidth.integer - (26 + 15) * 8) / 2; // 26 characters until name, then we assume 15 character names (they can be longer but usually aren't)
1556 DrawQ_String(x, y, va("ping pl%% time frags team name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1560 x = (vid_conwidth.integer - (16 + 15) * 8) / 2; // 16 characters until name, then we assume 15 character names (they can be longer but usually aren't)
1561 DrawQ_String(x, y, va("ping pl%% frags name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1565 if (Sbar_IsTeammatch ())
1567 // show team scores first
1568 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1569 y += (int)Sbar_PrintScoreboardItem((teams + teamsort[i]), x, y);
1573 for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1574 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1579 Sbar_DeathmatchOverlay
1583 void Sbar_MiniDeathmatchOverlay (int x, int y)
1587 // decide where to print
1588 if (gamemode == GAME_TRANSFUSION)
1589 numlines = (vid_conwidth.integer - x + 127) / 128;
1591 numlines = (vid_conheight.integer - y + 7) / 8;
1593 // give up if there isn't room
1594 if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1601 for (i = 0; i < scoreboardlines; i++)
1602 if (fragsort[i] == cl.playerentity - 1)
1607 i = min(i, scoreboardlines - numlines);
1610 if (gamemode == GAME_TRANSFUSION)
1612 for (;i < scoreboardlines && x < vid_conwidth.integer;i++)
1613 x += 128 + (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1617 for (;i < scoreboardlines && y < vid_conheight.integer;i++)
1618 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1624 Sbar_IntermissionOverlay
1628 void Sbar_IntermissionOverlay (void)
1633 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1634 //if (cl.gametype == GAME_DEATHMATCH)
1635 if (!cl.islocalgame)
1637 Sbar_DeathmatchOverlay ();
1641 sbar_x = (vid_conwidth.integer - 320) >> 1;
1642 sbar_y = (vid_conheight.integer - 200) >> 1;
1644 DrawQ_Pic (sbar_x + 64, sbar_y + 24, sb_complete, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1645 DrawQ_Pic (sbar_x + 0, sbar_y + 56, sb_inter, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1648 dig = (int)cl.completed_time / 60;
1649 Sbar_DrawNum (160, 64, dig, 3, 0);
1650 num = (int)cl.completed_time - dig*60;
1651 if (gamemode != GAME_NEXUIZ)
1652 Sbar_DrawPic (234,64,sb_colon);
1653 Sbar_DrawPic (246,64,sb_nums[0][num/10]);
1654 Sbar_DrawPic (266,64,sb_nums[0][num%10]);
1656 Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
1657 if (gamemode != GAME_NEXUIZ)
1658 Sbar_DrawPic (232, 104, sb_slash);
1659 Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1661 Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1662 if (gamemode != GAME_NEXUIZ)
1663 Sbar_DrawPic (232, 144, sb_slash);
1664 Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1675 void Sbar_FinaleOverlay (void)
1677 DrawQ_Pic((vid_conwidth.integer - sb_finale->width)/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);