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[15] = Draw_CachePic ("gfx/sb_flag_blue_taken", true);
180 sb_items[16] = Draw_CachePic ("gfx/sb_flag_blue_lost", true);
181 sb_items[17] = Draw_CachePic ("gfx/sb_flag_blue_carrying", true);
183 sb_sbar = Draw_CachePic("gfx/sbar", true);
184 sb_sbar_minimal = Draw_CachePic("gfx/sbar_minimal", true);
185 sb_sbar_overlay = Draw_CachePic("gfx/sbar_overlay", true);
187 for(i = 0; i < 9;i++)
188 sb_weapons[0][i] = Draw_CachePic(va("gfx/inv_weapon%i",i), true);
190 else if (gamemode == GAME_ZYMOTIC)
192 zymsb_crosshair_center = Draw_CachePic ("gfx/hud/crosshair_center", true);
193 zymsb_crosshair_line = Draw_CachePic ("gfx/hud/crosshair_line", true);
194 zymsb_crosshair_health = Draw_CachePic ("gfx/hud/crosshair_health", true);
195 zymsb_crosshair_clip = Draw_CachePic ("gfx/hud/crosshair_clip", true);
196 zymsb_crosshair_ammo = Draw_CachePic ("gfx/hud/crosshair_ammo", true);
197 zymsb_crosshair_background = Draw_CachePic ("gfx/hud/crosshair_background", true);
198 zymsb_crosshair_left1 = Draw_CachePic ("gfx/hud/crosshair_left1", true);
199 zymsb_crosshair_left2 = Draw_CachePic ("gfx/hud/crosshair_left2", true);
200 zymsb_crosshair_right = Draw_CachePic ("gfx/hud/crosshair_right", true);
204 sb_disc = Draw_CachePic("gfx/disc", true);
206 for (i = 0;i < 10;i++)
208 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
209 sb_nums[1][i] = Draw_CachePic (va("gfx/anum_%i",i), true);
212 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus", true);
213 sb_nums[1][10] = Draw_CachePic ("gfx/anum_minus", true);
215 sb_colon = Draw_CachePic ("gfx/num_colon", true);
216 sb_slash = Draw_CachePic ("gfx/num_slash", true);
218 sb_weapons[0][0] = Draw_CachePic ("gfx/inv_shotgun", true);
219 sb_weapons[0][1] = Draw_CachePic ("gfx/inv_sshotgun", true);
220 sb_weapons[0][2] = Draw_CachePic ("gfx/inv_nailgun", true);
221 sb_weapons[0][3] = Draw_CachePic ("gfx/inv_snailgun", true);
222 sb_weapons[0][4] = Draw_CachePic ("gfx/inv_rlaunch", true);
223 sb_weapons[0][5] = Draw_CachePic ("gfx/inv_srlaunch", true);
224 sb_weapons[0][6] = Draw_CachePic ("gfx/inv_lightng", true);
226 sb_weapons[1][0] = Draw_CachePic ("gfx/inv2_shotgun", true);
227 sb_weapons[1][1] = Draw_CachePic ("gfx/inv2_sshotgun", true);
228 sb_weapons[1][2] = Draw_CachePic ("gfx/inv2_nailgun", true);
229 sb_weapons[1][3] = Draw_CachePic ("gfx/inv2_snailgun", true);
230 sb_weapons[1][4] = Draw_CachePic ("gfx/inv2_rlaunch", true);
231 sb_weapons[1][5] = Draw_CachePic ("gfx/inv2_srlaunch", true);
232 sb_weapons[1][6] = Draw_CachePic ("gfx/inv2_lightng", true);
234 for (i = 0;i < 5;i++)
236 sb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_shotgun",i+1), true);
237 sb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_sshotgun",i+1), true);
238 sb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_nailgun",i+1), true);
239 sb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_snailgun",i+1), true);
240 sb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_rlaunch",i+1), true);
241 sb_weapons[2+i][5] = Draw_CachePic (va("gfx/inva%i_srlaunch",i+1), true);
242 sb_weapons[2+i][6] = Draw_CachePic (va("gfx/inva%i_lightng",i+1), true);
245 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells", true);
246 sb_ammo[1] = Draw_CachePic ("gfx/sb_nails", true);
247 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket", true);
248 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells", true);
250 sb_armor[0] = Draw_CachePic ("gfx/sb_armor1", true);
251 sb_armor[1] = Draw_CachePic ("gfx/sb_armor2", true);
252 sb_armor[2] = Draw_CachePic ("gfx/sb_armor3", true);
254 sb_items[0] = Draw_CachePic ("gfx/sb_key1", true);
255 sb_items[1] = Draw_CachePic ("gfx/sb_key2", true);
256 sb_items[2] = Draw_CachePic ("gfx/sb_invis", true);
257 sb_items[3] = Draw_CachePic ("gfx/sb_invuln", true);
258 sb_items[4] = Draw_CachePic ("gfx/sb_suit", true);
259 sb_items[5] = Draw_CachePic ("gfx/sb_quad", true);
261 sb_sigil[0] = Draw_CachePic ("gfx/sb_sigil1", true);
262 sb_sigil[1] = Draw_CachePic ("gfx/sb_sigil2", true);
263 sb_sigil[2] = Draw_CachePic ("gfx/sb_sigil3", true);
264 sb_sigil[3] = Draw_CachePic ("gfx/sb_sigil4", true);
266 sb_faces[4][0] = Draw_CachePic ("gfx/face1", true);
267 sb_faces[4][1] = Draw_CachePic ("gfx/face_p1", true);
268 sb_faces[3][0] = Draw_CachePic ("gfx/face2", true);
269 sb_faces[3][1] = Draw_CachePic ("gfx/face_p2", true);
270 sb_faces[2][0] = Draw_CachePic ("gfx/face3", true);
271 sb_faces[2][1] = Draw_CachePic ("gfx/face_p3", true);
272 sb_faces[1][0] = Draw_CachePic ("gfx/face4", true);
273 sb_faces[1][1] = Draw_CachePic ("gfx/face_p4", true);
274 sb_faces[0][0] = Draw_CachePic ("gfx/face5", true);
275 sb_faces[0][1] = Draw_CachePic ("gfx/face_p5", true);
277 sb_face_invis = Draw_CachePic ("gfx/face_invis", true);
278 sb_face_invuln = Draw_CachePic ("gfx/face_invul2", true);
279 sb_face_invis_invuln = Draw_CachePic ("gfx/face_inv2", true);
280 sb_face_quad = Draw_CachePic ("gfx/face_quad", true);
282 sb_sbar = Draw_CachePic ("gfx/sbar", true);
283 sb_ibar = Draw_CachePic ("gfx/ibar", true);
284 sb_scorebar = Draw_CachePic ("gfx/scorebar", true);
286 //MED 01/04/97 added new hipnotic weapons
287 if (gamemode == GAME_HIPNOTIC)
289 hsb_weapons[0][0] = Draw_CachePic ("gfx/inv_laser", true);
290 hsb_weapons[0][1] = Draw_CachePic ("gfx/inv_mjolnir", true);
291 hsb_weapons[0][2] = Draw_CachePic ("gfx/inv_gren_prox", true);
292 hsb_weapons[0][3] = Draw_CachePic ("gfx/inv_prox_gren", true);
293 hsb_weapons[0][4] = Draw_CachePic ("gfx/inv_prox", true);
295 hsb_weapons[1][0] = Draw_CachePic ("gfx/inv2_laser", true);
296 hsb_weapons[1][1] = Draw_CachePic ("gfx/inv2_mjolnir", true);
297 hsb_weapons[1][2] = Draw_CachePic ("gfx/inv2_gren_prox", true);
298 hsb_weapons[1][3] = Draw_CachePic ("gfx/inv2_prox_gren", true);
299 hsb_weapons[1][4] = Draw_CachePic ("gfx/inv2_prox", true);
301 for (i = 0;i < 5;i++)
303 hsb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_laser",i+1), true);
304 hsb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_mjolnir",i+1), true);
305 hsb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_gren_prox",i+1), true);
306 hsb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_prox_gren",i+1), true);
307 hsb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_prox",i+1), true);
310 hsb_items[0] = Draw_CachePic ("gfx/sb_wsuit", true);
311 hsb_items[1] = Draw_CachePic ("gfx/sb_eshld", true);
313 else if (gamemode == GAME_ROGUE)
315 rsb_invbar[0] = Draw_CachePic ("gfx/r_invbar1", true);
316 rsb_invbar[1] = Draw_CachePic ("gfx/r_invbar2", true);
318 rsb_weapons[0] = Draw_CachePic ("gfx/r_lava", true);
319 rsb_weapons[1] = Draw_CachePic ("gfx/r_superlava", true);
320 rsb_weapons[2] = Draw_CachePic ("gfx/r_gren", true);
321 rsb_weapons[3] = Draw_CachePic ("gfx/r_multirock", true);
322 rsb_weapons[4] = Draw_CachePic ("gfx/r_plasma", true);
324 rsb_items[0] = Draw_CachePic ("gfx/r_shield1", true);
325 rsb_items[1] = Draw_CachePic ("gfx/r_agrav1", true);
327 // PGM 01/19/97 - team color border
328 rsb_teambord = Draw_CachePic ("gfx/r_teambord", true);
329 // PGM 01/19/97 - team color border
331 rsb_ammo[0] = Draw_CachePic ("gfx/r_ammolava", true);
332 rsb_ammo[1] = Draw_CachePic ("gfx/r_ammomulti", true);
333 rsb_ammo[2] = Draw_CachePic ("gfx/r_ammoplasma", true);
337 sb_ranking = Draw_CachePic ("gfx/ranking", true);
338 sb_complete = Draw_CachePic ("gfx/complete", true);
339 sb_inter = Draw_CachePic ("gfx/inter", true);
340 sb_finale = Draw_CachePic ("gfx/finale", true);
343 void sbar_shutdown(void)
347 void sbar_newmap(void)
351 void Sbar_Init (void)
353 Cmd_AddCommand("+showscores", Sbar_ShowScores, "show scoreboard");
354 Cmd_AddCommand("-showscores", Sbar_DontShowScores, "hide scoreboard");
355 Cvar_RegisterVariable(&showfps);
356 Cvar_RegisterVariable(&showtime);
357 Cvar_RegisterVariable(&showtime_format);
358 Cvar_RegisterVariable(&showdate);
359 Cvar_RegisterVariable(&showdate_format);
360 Cvar_RegisterVariable(&sbar_alpha_bg);
361 Cvar_RegisterVariable(&sbar_alpha_fg);
362 Cvar_RegisterVariable(&cl_deathscoreboard);
364 Cvar_RegisterVariable(&crosshair_color_red);
365 Cvar_RegisterVariable(&crosshair_color_green);
366 Cvar_RegisterVariable(&crosshair_color_blue);
367 Cvar_RegisterVariable(&crosshair_color_alpha);
368 Cvar_RegisterVariable(&crosshair_size);
370 R_RegisterModule("sbar", sbar_start, sbar_shutdown, sbar_newmap);
374 //=============================================================================
376 // drawing routines are relative to the status bar location
385 void Sbar_DrawPic (int x, int y, cachepic_t *pic)
387 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, sbar_alpha_fg.value, 0);
390 void Sbar_DrawAlphaPic (int x, int y, cachepic_t *pic, float alpha)
392 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, alpha, 0);
399 Draws one solid graphics character
402 void Sbar_DrawCharacter (int x, int y, int num)
404 DrawQ_String (sbar_x + x + 4 , sbar_y + y, va("%c", num), 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0);
412 void Sbar_DrawString (int x, int y, char *str)
414 DrawQ_String (sbar_x + x, sbar_y + y, str, 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0);
422 void Sbar_DrawNum (int x, int y, int num, int digits, int color)
427 l = sprintf(str, "%i", num);
441 Sbar_DrawPic (x, y, sb_nums[color][frame]);
454 void Sbar_DrawXNum (int x, int y, int num, int digits, int lettersize, float r, float g, float b, float a, int flags)
459 l = sprintf(str, "%i", num);
464 x += (digits-l) * lettersize;
473 DrawQ_Pic (sbar_x + x, sbar_y + y, sb_nums[0][frame],lettersize,lettersize,r,g,b,a * sbar_alpha_fg.value,flags);
480 //=============================================================================
483 int Sbar_IsTeammatch()
485 // currently only nexuiz uses the team score board
486 return ((gamemode == GAME_NEXUIZ)
487 && (teamplay.integer > 0));
495 static int fragsort[MAX_SCOREBOARD];
496 static int scoreboardlines;
498 //[515]: Sbar_GetPlayer for csqc "getplayerkey" func
499 int Sbar_GetPlayer (int index)
504 if(index >= scoreboardlines)
506 index = fragsort[index];
508 if(index >= scoreboardlines)
513 static scoreboard_t teams[MAX_SCOREBOARD];
514 static int teamsort[MAX_SCOREBOARD];
515 static int teamlines;
516 void Sbar_SortFrags (void)
522 for (i=0 ; i<cl.maxclients ; i++)
524 if (cl.scores[i].name[0])
526 fragsort[scoreboardlines] = i;
531 for (i=0 ; i<scoreboardlines ; i++)
532 for (j=0 ; j<scoreboardlines-1-i ; j++)
533 if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j+1]].frags)
536 fragsort[j] = fragsort[j+1];
541 if (Sbar_IsTeammatch ())
543 // now sort players by teams.
544 for (i=0 ; i<scoreboardlines ; i++)
546 for (j=0 ; j<scoreboardlines-1-i ; j++)
548 if (cl.scores[fragsort[j]].colors < cl.scores[fragsort[j+1]].colors)
551 fragsort[j] = fragsort[j+1];
557 // calculate team scores
559 for (i=0 ; i<scoreboardlines ; i++)
561 if (color != (cl.scores[fragsort[i]].colors & 15))
563 const char* teamname;
565 color = cl.scores[fragsort[i]].colors & 15;
571 teamname = "^1Red Team";
574 teamname = "^4Blue Team";
577 teamname = "^6Pink Team";
580 teamname = "^3Yellow Team";
583 teamname = "Total Team Score";
586 strlcpy(teams[teamlines-1].name, teamname, sizeof(teams[teamlines-1].name));
588 teams[teamlines-1].frags = 0;
589 teams[teamlines-1].colors = color + 16 * color;
592 if (cl.scores[fragsort[i]].frags != -666)
594 // do not add spedcators
595 // (ugly hack for nexuiz)
596 teams[teamlines-1].frags += cl.scores[fragsort[i]].frags;
600 // now sort teams by scores.
601 for (i=0 ; i<teamlines ; i++)
603 for (i=0 ; i<teamlines ; i++)
605 for (j=0 ; j<teamlines-1-i ; j++)
607 if (teams[teamsort[j]].frags < teams[teamsort[j+1]].frags)
610 teamsort[j] = teamsort[j+1];
623 void Sbar_SoloScoreboard (void)
626 char str[80], timestr[40];
628 int minutes, seconds;
630 minutes = (int)(cl.time / 60);
631 seconds = (int)(cl.time - 60*floor(cl.time/60));
633 // monsters and secrets are now both on the top row
634 if (gamemode != GAME_NEXUIZ)
635 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]));
637 // figure out the map's filename without path or extension
638 strlcpy(str, FS_FileWithoutPath(cl.worldmodel ? cl.worldmodel->name : ""), sizeof(str));
639 if (strrchr(str, '.'))
640 *(strrchr(str, '.')) = 0;
642 // append a : separator and then the full title
643 strlcat(str, ":", sizeof(str));
644 strlcat(str, cl.levelname, sizeof(str));
646 // make the time string
647 max = 38 - sprintf(timestr, " %i:%02i", minutes, seconds);
649 // if there's a newline character, terminate the string there
650 if (strchr(str, '\n'))
651 *(strchr(str, '\n')) = 0;
653 // pad with spaces to fill the allotted space and append the time
654 i = bound(0, (int)strlen(str), max);
658 strlcat(str, timestr, sizeof(str));
660 // print the line of text
661 Sbar_DrawString(8, 12, str);
665 int minutes, seconds, tens, units;
668 if (gamemode != GAME_NEXUIZ) {
669 sprintf (str,"Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
670 Sbar_DrawString (8, 4, str);
672 sprintf (str,"Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
673 Sbar_DrawString (8, 12, str);
677 minutes = (int)(cl.time / 60);
678 seconds = (int)(cl.time - 60*minutes);
680 units = seconds - 10*tens;
681 sprintf (str,"Time :%3i:%i%i", minutes, tens, units);
682 Sbar_DrawString (184, 4, str);
685 if (gamemode == GAME_NEXUIZ) {
686 l = (int) strlen (cl.worldmodel->name);
687 Sbar_DrawString (232 - l*4, 12, cl.worldmodel->name);
689 l = (int) strlen (cl.levelname);
690 Sbar_DrawString (232 - l*4, 12, cl.levelname);
700 void Sbar_DrawScoreboard (void)
702 Sbar_SoloScoreboard ();
703 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
704 //if (cl.gametype == GAME_DEATHMATCH)
706 Sbar_DeathmatchOverlay ();
709 //=============================================================================
711 // AK to make DrawInventory smaller
712 static void Sbar_DrawWeapon(int nr, float fade, int active)
714 // width = 300, height = 100
715 const int w_width = 300, w_height = 100, w_space = 10;
716 const float w_scale = 0.4;
718 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_ADDITIVE);
719 //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);
722 DrawQ_Pic(vid_conwidth.integer - (w_width + w_space) * w_scale, (w_height + w_space) * w_scale * nr + w_space, NULL, w_width * w_scale, w_height * w_scale, 0.3, 0.3, 0.3, fade * sbar_alpha_fg.value, DRAWFLAG_ADDITIVE);
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_Pic (sbar_x + x + 10, sbar_y - 23, NULL, 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_Pic (sbar_x + x + 10, sbar_y + 4 - 23, NULL, 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_Pic (sbar_x + 113, vid_conheight.integer-SBAR_HEIGHT+3, NULL, 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_Pic (sbar_x + 113, vid_conheight.integer-SBAR_HEIGHT+12, NULL, 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;
1005 newtime = Sys_DoubleTime();
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_Pic(fps_x, fps_y, NULL, 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);
1040 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
1041 fps_y += fps_scaley;
1045 fps_x = vid_conwidth.integer - fps_scalex * strlen(timestring);
1046 DrawQ_Pic(fps_x, fps_y, NULL, 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);
1048 fps_y += fps_scaley;
1052 fps_x = vid_conwidth.integer - fps_scalex * strlen(datestring);
1053 DrawQ_Pic(fps_x, fps_y, NULL, 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);
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 Sbar_IntermissionOverlay();
1098 else if (cl.intermission == 2)
1100 Sbar_FinaleOverlay();
1104 if (gamemode == GAME_NETHERWORLD)
1107 else if (gamemode == GAME_SOM)
1109 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1110 Sbar_DrawScoreboard ();
1113 // this is the top left of the sbar area
1115 sbar_y = vid_conheight.integer - 24*3;
1118 if (cl.stats[STAT_ARMOR])
1120 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1121 Sbar_DrawPic(0, 0, somsb_armor[2]);
1122 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1123 Sbar_DrawPic(0, 0, somsb_armor[1]);
1124 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1125 Sbar_DrawPic(0, 0, somsb_armor[0]);
1126 Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1130 Sbar_DrawPic(0, 24, somsb_health);
1131 Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1134 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1135 Sbar_DrawPic(0, 48, somsb_ammo[0]);
1136 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1137 Sbar_DrawPic(0, 48, somsb_ammo[1]);
1138 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1139 Sbar_DrawPic(0, 48, somsb_ammo[2]);
1140 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1141 Sbar_DrawPic(0, 48, somsb_ammo[3]);
1142 Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
1143 if (cl.stats[STAT_SHELLS])
1144 Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
1147 else if (gamemode == GAME_NEXUIZ)
1149 sbar_y = vid_conheight.integer - 47;
1150 sbar_x = (vid_conwidth.integer - 640)/2;
1152 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1154 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1155 Sbar_DrawScoreboard ();
1162 int redflag, blueflag;
1164 // we have a max time 2s (min time = 0)
1165 if ((time = max(0, cl.time - cl.weapontime)) < 2)
1167 fade = (1.0 - 0.5 * time);
1169 for (i = 0; i < 8;i++)
1170 if (cl.stats[STAT_ITEMS] & (1 << i))
1171 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1173 if((cl.stats[STAT_ITEMS] & (1<<12)))
1174 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1177 //if (!cl.islocalgame)
1178 // Sbar_DrawFrags ();
1181 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1183 Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1186 redflag = ((cl.stats[STAT_ITEMS]>>15) & 3);
1188 Sbar_DrawPic (10, -85, sb_items[redflag+10]);
1189 blueflag = ((cl.stats[STAT_ITEMS]>>17) & 3);
1191 Sbar_DrawPic (10, -145, sb_items[blueflag+14]);
1194 Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1197 if(cl.stats[STAT_HEALTH] > 100)
1198 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1199 else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1200 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1202 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1204 // AK dont draw ammo for the laser
1205 if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1207 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1208 Sbar_DrawPic (519, 0, sb_ammo[0]);
1209 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1210 Sbar_DrawPic (519, 0, sb_ammo[1]);
1211 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1212 Sbar_DrawPic (519, 0, sb_ammo[2]);
1213 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1214 Sbar_DrawPic (519, 0, sb_ammo[3]);
1216 if(cl.stats[STAT_AMMO] <= 10)
1217 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1219 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1224 DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1227 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1228 // Sbar_MiniDeathmatchOverlay (0, 17);
1230 else if (gamemode == GAME_ZYMOTIC)
1233 float scale = 64.0f / 256.0f;
1234 float kickoffset[3];
1235 VectorClear(kickoffset);
1238 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1239 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1241 sbar_x = (int)((vid_conwidth.integer - 256 * scale)/2 + kickoffset[0]);
1242 sbar_y = (int)((vid_conheight.integer - 256 * scale)/2 + kickoffset[1]);
1243 // left1 16, 48 : 126 -66
1244 // left2 16, 128 : 196 -66
1245 // right 176, 48 : 196 -136
1246 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);
1247 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);
1248 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);
1249 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1251 float scale = 128.0f / 256.0f;
1252 float healthstart, healthheight, healthstarttc, healthendtc;
1253 float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1254 float ammostart, ammoheight, ammostarttc, ammoendtc;
1255 float clipstart, clipheight, clipstarttc, clipendtc;
1256 float kickoffset[3], offset;
1257 VectorClear(kickoffset);
1260 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1261 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1263 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1264 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1265 offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1266 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);
1267 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);
1268 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);
1269 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);
1270 healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1271 shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1272 healthstart = 204 - healthheight;
1273 shieldstart = healthstart - shieldheight;
1274 healthstarttc = healthstart * (1.0f / 256.0f);
1275 healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1276 shieldstarttc = shieldstart * (1.0f / 256.0f);
1277 shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1278 ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1279 ammostart = 114 - ammoheight;
1280 ammostarttc = ammostart * (1.0f / 256.0f);
1281 ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1282 clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1283 clipstart = 190 - clipheight;
1284 clipstarttc = clipstart * (1.0f / 256.0f);
1285 clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1286 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);
1287 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);
1288 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);
1289 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);
1290 DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1291 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1294 else // Quake and others
1296 sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1297 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1298 //if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1299 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1302 sbar_x = (vid_conwidth.integer - 320)/2;
1306 if (gamemode != GAME_GOODVSBAD2)
1307 Sbar_DrawInventory ();
1308 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1312 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1314 if (gamemode != GAME_GOODVSBAD2)
1315 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1316 Sbar_DrawScoreboard ();
1320 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1322 // keys (hipnotic only)
1323 //MED 01/04/97 moved keys here so they would not be overwritten
1324 if (gamemode == GAME_HIPNOTIC)
1326 if (cl.stats[STAT_ITEMS] & IT_KEY1)
1327 Sbar_DrawPic (209, 3, sb_items[0]);
1328 if (cl.stats[STAT_ITEMS] & IT_KEY2)
1329 Sbar_DrawPic (209, 12, sb_items[1]);
1332 if (gamemode != GAME_GOODVSBAD2)
1334 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1336 Sbar_DrawNum (24, 0, 666, 3, 1);
1337 Sbar_DrawPic (0, 0, sb_disc);
1341 if (gamemode == GAME_ROGUE)
1343 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1344 if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1345 Sbar_DrawPic (0, 0, sb_armor[2]);
1346 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1347 Sbar_DrawPic (0, 0, sb_armor[1]);
1348 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1349 Sbar_DrawPic (0, 0, sb_armor[0]);
1353 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1354 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1355 Sbar_DrawPic (0, 0, sb_armor[2]);
1356 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1357 Sbar_DrawPic (0, 0, sb_armor[1]);
1358 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1359 Sbar_DrawPic (0, 0, sb_armor[0]);
1368 Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1371 if (gamemode == GAME_ROGUE)
1373 if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1374 Sbar_DrawPic (224, 0, sb_ammo[0]);
1375 else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1376 Sbar_DrawPic (224, 0, sb_ammo[1]);
1377 else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1378 Sbar_DrawPic (224, 0, sb_ammo[2]);
1379 else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1380 Sbar_DrawPic (224, 0, sb_ammo[3]);
1381 else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1382 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1383 else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1384 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1385 else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1386 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1390 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1391 Sbar_DrawPic (224, 0, sb_ammo[0]);
1392 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1393 Sbar_DrawPic (224, 0, sb_ammo[1]);
1394 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1395 Sbar_DrawPic (224, 0, sb_ammo[2]);
1396 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1397 Sbar_DrawPic (224, 0, sb_ammo[3]);
1400 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1404 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1405 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1406 if (!cl.islocalgame && vid_conwidth.integer > 320)
1408 if (gamemode == GAME_TRANSFUSION)
1409 Sbar_MiniDeathmatchOverlay (0, 0);
1411 Sbar_MiniDeathmatchOverlay (324, vid_conheight.integer - sb_lines);
1418 if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && crosshair.integer <= NUMCROSSHAIRS && !cl.intermission && !r_letterbox.value && (pic = r_crosshairs[crosshair.integer]))
1419 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);
1421 if (cl_prydoncursor.integer)
1422 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);
1425 //=============================================================================
1429 Sbar_DeathmatchOverlay
1433 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1437 minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : cl.time - s->qw_entertime) / 60.0);
1438 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1440 if (s->qw_spectator)
1442 if (s->qw_ping || s->qw_packetloss)
1443 DrawQ_ColoredString(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 );
1445 DrawQ_ColoredString(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 );
1449 // draw colors behind score
1450 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1451 DrawQ_Pic(x + 14*8, y+1, NULL, 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);
1452 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1453 DrawQ_Pic(x + 14*8, y+4, NULL, 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);
1455 //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);
1456 if (s->qw_ping || s->qw_packetloss)
1457 DrawQ_ColoredString(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 );
1459 DrawQ_ColoredString(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 );
1464 if (s->qw_spectator)
1466 if (s->qw_ping || s->qw_packetloss)
1467 DrawQ_ColoredString(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 );
1469 DrawQ_ColoredString(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 );
1473 // draw colors behind score
1474 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1475 DrawQ_Pic(x + 9*8, y+1, NULL, 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);
1476 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1477 DrawQ_Pic(x + 9*8, y+4, NULL, 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);
1479 //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);
1480 if (s->qw_ping || s->qw_packetloss)
1481 DrawQ_ColoredString(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 );
1483 DrawQ_ColoredString(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 );
1489 void Sbar_DeathmatchOverlay (void)
1493 // request new ping times every two second
1494 if (cl.last_ping_request < realtime - 2 && cls.netcon)
1496 cl.last_ping_request = realtime;
1497 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1499 MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
1500 MSG_WriteString(&cls.netcon->message, "pings");
1502 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)
1504 // 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
1505 static int ping_anyway_counter = 0;
1506 if(cl.parsingtextexpectingpingforscores == 1)
1508 Con_DPrintf("want to send ping, but still waiting for other reply\n");
1509 if(++ping_anyway_counter >= 5)
1510 cl.parsingtextexpectingpingforscores = 0;
1512 if(cl.parsingtextexpectingpingforscores != 1)
1514 ping_anyway_counter = 0;
1515 cl.parsingtextexpectingpingforscores = 1; // hide the output of the next ping report
1516 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1517 MSG_WriteString(&cls.netcon->message, "ping");
1522 // newer server definitely has pings command, so use it for more efficiency
1523 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1524 MSG_WriteString(&cls.netcon->message, "pings");
1528 DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1534 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1536 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)
1537 DrawQ_ColoredString(x, y, va("ping pl%% time frags team name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1541 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)
1542 DrawQ_ColoredString(x, y, va("ping pl%% frags name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1546 if (Sbar_IsTeammatch ())
1548 // show team scores first
1549 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1550 y += (int)Sbar_PrintScoreboardItem((teams + teamsort[i]), x, y);
1554 for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1555 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1560 Sbar_DeathmatchOverlay
1564 void Sbar_MiniDeathmatchOverlay (int x, int y)
1568 // decide where to print
1569 if (gamemode == GAME_TRANSFUSION)
1570 numlines = (vid_conwidth.integer - x + 127) / 128;
1572 numlines = (vid_conheight.integer - y + 7) / 8;
1574 // give up if there isn't room
1575 if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1582 for (i = 0; i < scoreboardlines; i++)
1583 if (fragsort[i] == cl.playerentity - 1)
1588 i = min(i, scoreboardlines - numlines);
1591 if (gamemode == GAME_TRANSFUSION)
1593 for (;i < scoreboardlines && x < vid_conwidth.integer;i++)
1594 x += 128 + (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1598 for (;i < scoreboardlines && y < vid_conheight.integer;i++)
1599 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1605 Sbar_IntermissionOverlay
1609 void Sbar_IntermissionOverlay (void)
1614 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1615 //if (cl.gametype == GAME_DEATHMATCH)
1616 if (!cl.islocalgame)
1618 Sbar_DeathmatchOverlay ();
1622 sbar_x = (vid_conwidth.integer - 320) >> 1;
1623 sbar_y = (vid_conheight.integer - 200) >> 1;
1625 DrawQ_Pic (sbar_x + 64, sbar_y + 24, sb_complete, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1626 DrawQ_Pic (sbar_x + 0, sbar_y + 56, sb_inter, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1629 dig = (int)cl.completed_time / 60;
1630 Sbar_DrawNum (160, 64, dig, 3, 0);
1631 num = (int)cl.completed_time - dig*60;
1632 if (gamemode != GAME_NEXUIZ)
1633 Sbar_DrawPic (234,64,sb_colon);
1634 Sbar_DrawPic (246,64,sb_nums[0][num/10]);
1635 Sbar_DrawPic (266,64,sb_nums[0][num%10]);
1637 Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
1638 if (gamemode != GAME_NEXUIZ)
1639 Sbar_DrawPic (232, 104, sb_slash);
1640 Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1642 Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1643 if (gamemode != GAME_NEXUIZ)
1644 Sbar_DrawPic (232, 144, sb_slash);
1645 Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1656 void Sbar_FinaleOverlay (void)
1658 DrawQ_Pic((vid_conwidth.integer - sb_finale->width)/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);