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];
46 cachepic_t *sb_health; // GAME_NEXUIZ
48 cachepic_t *sb_face_invis;
49 cachepic_t *sb_face_quad;
50 cachepic_t *sb_face_invuln;
51 cachepic_t *sb_face_invis_invuln;
53 qboolean sb_showscores;
55 int sb_lines; // scan lines to draw
57 cachepic_t *rsb_invbar[2];
58 cachepic_t *rsb_weapons[5];
59 cachepic_t *rsb_items[2];
60 cachepic_t *rsb_ammo[3];
61 cachepic_t *rsb_teambord; // PGM 01/19/97 - team color border
63 //MED 01/04/97 added two more weapons + 3 alternates for grenade launcher
64 cachepic_t *hsb_weapons[7][5]; // 0 is active, 1 is owned, 2-5 are flashes
65 //MED 01/04/97 added array to simplify weapon parsing
66 int hipweapons[4] = {HIT_LASER_CANNON_BIT,HIT_MJOLNIR_BIT,4,HIT_PROXIMITY_GUN_BIT};
67 //MED 01/04/97 added hipnotic items array
68 cachepic_t *hsb_items[2];
71 cachepic_t *somsb_health;
72 cachepic_t *somsb_ammo[4];
73 cachepic_t *somsb_armor[3];
75 cachepic_t *zymsb_crosshair_center;
76 cachepic_t *zymsb_crosshair_line;
77 cachepic_t *zymsb_crosshair_health;
78 cachepic_t *zymsb_crosshair_ammo;
79 cachepic_t *zymsb_crosshair_clip;
80 cachepic_t *zymsb_crosshair_background;
81 cachepic_t *zymsb_crosshair_left1;
82 cachepic_t *zymsb_crosshair_left2;
83 cachepic_t *zymsb_crosshair_right;
85 cachepic_t *sb_ranking;
86 cachepic_t *sb_complete;
88 cachepic_t *sb_finale;
90 cvar_t showfps = {CVAR_SAVE, "showfps", "0", "shows your rendered fps (frames per second)"};
91 cvar_t showtime = {CVAR_SAVE, "showtime", "0", "shows current time of day (useful on screenshots)"};
92 cvar_t showtime_format = {CVAR_SAVE, "showtime_format", "%H:%M:%S", "format string for time of day"};
93 cvar_t showdate = {CVAR_SAVE, "showdate", "0", "shows current date (useful on screenshots)"};
94 cvar_t showdate_format = {CVAR_SAVE, "showdate_format", "%Y-%m-%d", "format string for date"};
95 cvar_t sbar_alpha_bg = {CVAR_SAVE, "sbar_alpha_bg", "0.4", "opacity value of the statusbar background image"};
96 cvar_t sbar_alpha_fg = {CVAR_SAVE, "sbar_alpha_fg", "1", "opacity value of the statusbar weapon/item icons and numbers"};
97 cvar_t sbar_hudselector = {CVAR_SAVE, "sbar_hudselector", "0", "selects which of the builtin hud layouts to use (meaning is somewhat dependent on gamemode, so nexuiz has a very different set of hud layouts than quake for example)"};
99 cvar_t cl_deathscoreboard = {0, "cl_deathscoreboard", "1", "shows scoreboard (+showscores) while dead"};
101 cvar_t crosshair_color_red = {CVAR_SAVE, "crosshair_color_red", "1", "customizable crosshair color"};
102 cvar_t crosshair_color_green = {CVAR_SAVE, "crosshair_color_green", "0", "customizable crosshair color"};
103 cvar_t crosshair_color_blue = {CVAR_SAVE, "crosshair_color_blue", "0", "customizable crosshair color"};
104 cvar_t crosshair_color_alpha = {CVAR_SAVE, "crosshair_color_alpha", "1", "how opaque the crosshair should be"};
105 cvar_t crosshair_size = {CVAR_SAVE, "crosshair_size", "1", "adjusts size of the crosshair on the screen"};
107 void Sbar_MiniDeathmatchOverlay (int x, int y);
108 void Sbar_DeathmatchOverlay (void);
109 void Sbar_IntermissionOverlay (void);
110 void Sbar_FinaleOverlay (void);
120 void Sbar_ShowScores (void)
124 sb_showscores = true;
134 void Sbar_DontShowScores (void)
136 sb_showscores = false;
139 void sbar_start(void)
143 if (gamemode == GAME_NETHERWORLD)
146 else if (gamemode == GAME_SOM)
148 sb_disc = Draw_CachePic("gfx/disc", true);
150 for (i = 0;i < 10;i++)
151 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
153 somsb_health = Draw_CachePic("gfx/hud_health", true);
154 somsb_ammo[0] = Draw_CachePic("gfx/sb_shells", true);
155 somsb_ammo[1] = Draw_CachePic("gfx/sb_nails", true);
156 somsb_ammo[2] = Draw_CachePic("gfx/sb_rocket", true);
157 somsb_ammo[3] = Draw_CachePic("gfx/sb_cells", true);
158 somsb_armor[0] = Draw_CachePic("gfx/sb_armor1", true);
159 somsb_armor[1] = Draw_CachePic("gfx/sb_armor2", true);
160 somsb_armor[2] = Draw_CachePic("gfx/sb_armor3", true);
162 else if (gamemode == GAME_NEXUIZ)
164 for (i = 0;i < 10;i++)
165 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
166 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus", true);
168 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells", true);
169 sb_ammo[1] = Draw_CachePic ("gfx/sb_bullets", true);
170 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket", true);
171 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells", true);
173 sb_armor[0] = Draw_CachePic ("gfx/sb_armor", true);
177 sb_health = Draw_CachePic ("gfx/sb_health", true);
179 sb_items[2] = Draw_CachePic ("gfx/sb_slowmo", true);
180 sb_items[3] = Draw_CachePic ("gfx/sb_invinc", true);
181 sb_items[4] = Draw_CachePic ("gfx/sb_energy", true);
182 sb_items[5] = Draw_CachePic ("gfx/sb_str", true);
184 sb_items[11] = Draw_CachePic ("gfx/sb_flag_red_taken", true);
185 sb_items[12] = Draw_CachePic ("gfx/sb_flag_red_lost", true);
186 sb_items[13] = Draw_CachePic ("gfx/sb_flag_red_carrying", true);
187 sb_items[14] = Draw_CachePic ("gfx/sb_key_carrying", true);
188 sb_items[15] = Draw_CachePic ("gfx/sb_flag_blue_taken", true);
189 sb_items[16] = Draw_CachePic ("gfx/sb_flag_blue_lost", true);
190 sb_items[17] = Draw_CachePic ("gfx/sb_flag_blue_carrying", true);
192 sb_sbar = Draw_CachePic("gfx/sbar", true);
193 sb_sbar_minimal = Draw_CachePic("gfx/sbar_minimal", true);
194 sb_sbar_overlay = Draw_CachePic("gfx/sbar_overlay", true);
196 for(i = 0; i < 9;i++)
197 sb_weapons[0][i] = Draw_CachePic(va("gfx/inv_weapon%i",i), true);
199 else if (gamemode == GAME_ZYMOTIC)
201 zymsb_crosshair_center = Draw_CachePic ("gfx/hud/crosshair_center", true);
202 zymsb_crosshair_line = Draw_CachePic ("gfx/hud/crosshair_line", true);
203 zymsb_crosshair_health = Draw_CachePic ("gfx/hud/crosshair_health", true);
204 zymsb_crosshair_clip = Draw_CachePic ("gfx/hud/crosshair_clip", true);
205 zymsb_crosshair_ammo = Draw_CachePic ("gfx/hud/crosshair_ammo", true);
206 zymsb_crosshair_background = Draw_CachePic ("gfx/hud/crosshair_background", true);
207 zymsb_crosshair_left1 = Draw_CachePic ("gfx/hud/crosshair_left1", true);
208 zymsb_crosshair_left2 = Draw_CachePic ("gfx/hud/crosshair_left2", true);
209 zymsb_crosshair_right = Draw_CachePic ("gfx/hud/crosshair_right", true);
213 sb_disc = Draw_CachePic("gfx/disc", true);
215 for (i = 0;i < 10;i++)
217 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
218 sb_nums[1][i] = Draw_CachePic (va("gfx/anum_%i",i), true);
221 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus", true);
222 sb_nums[1][10] = Draw_CachePic ("gfx/anum_minus", true);
224 sb_colon = Draw_CachePic ("gfx/num_colon", true);
225 sb_slash = Draw_CachePic ("gfx/num_slash", true);
227 sb_weapons[0][0] = Draw_CachePic ("gfx/inv_shotgun", true);
228 sb_weapons[0][1] = Draw_CachePic ("gfx/inv_sshotgun", true);
229 sb_weapons[0][2] = Draw_CachePic ("gfx/inv_nailgun", true);
230 sb_weapons[0][3] = Draw_CachePic ("gfx/inv_snailgun", true);
231 sb_weapons[0][4] = Draw_CachePic ("gfx/inv_rlaunch", true);
232 sb_weapons[0][5] = Draw_CachePic ("gfx/inv_srlaunch", true);
233 sb_weapons[0][6] = Draw_CachePic ("gfx/inv_lightng", true);
235 sb_weapons[1][0] = Draw_CachePic ("gfx/inv2_shotgun", true);
236 sb_weapons[1][1] = Draw_CachePic ("gfx/inv2_sshotgun", true);
237 sb_weapons[1][2] = Draw_CachePic ("gfx/inv2_nailgun", true);
238 sb_weapons[1][3] = Draw_CachePic ("gfx/inv2_snailgun", true);
239 sb_weapons[1][4] = Draw_CachePic ("gfx/inv2_rlaunch", true);
240 sb_weapons[1][5] = Draw_CachePic ("gfx/inv2_srlaunch", true);
241 sb_weapons[1][6] = Draw_CachePic ("gfx/inv2_lightng", true);
243 for (i = 0;i < 5;i++)
245 sb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_shotgun",i+1), true);
246 sb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_sshotgun",i+1), true);
247 sb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_nailgun",i+1), true);
248 sb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_snailgun",i+1), true);
249 sb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_rlaunch",i+1), true);
250 sb_weapons[2+i][5] = Draw_CachePic (va("gfx/inva%i_srlaunch",i+1), true);
251 sb_weapons[2+i][6] = Draw_CachePic (va("gfx/inva%i_lightng",i+1), true);
254 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells", true);
255 sb_ammo[1] = Draw_CachePic ("gfx/sb_nails", true);
256 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket", true);
257 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells", true);
259 sb_armor[0] = Draw_CachePic ("gfx/sb_armor1", true);
260 sb_armor[1] = Draw_CachePic ("gfx/sb_armor2", true);
261 sb_armor[2] = Draw_CachePic ("gfx/sb_armor3", true);
263 sb_items[0] = Draw_CachePic ("gfx/sb_key1", true);
264 sb_items[1] = Draw_CachePic ("gfx/sb_key2", true);
265 sb_items[2] = Draw_CachePic ("gfx/sb_invis", true);
266 sb_items[3] = Draw_CachePic ("gfx/sb_invuln", true);
267 sb_items[4] = Draw_CachePic ("gfx/sb_suit", true);
268 sb_items[5] = Draw_CachePic ("gfx/sb_quad", true);
270 sb_sigil[0] = Draw_CachePic ("gfx/sb_sigil1", true);
271 sb_sigil[1] = Draw_CachePic ("gfx/sb_sigil2", true);
272 sb_sigil[2] = Draw_CachePic ("gfx/sb_sigil3", true);
273 sb_sigil[3] = Draw_CachePic ("gfx/sb_sigil4", true);
275 sb_faces[4][0] = Draw_CachePic ("gfx/face1", true);
276 sb_faces[4][1] = Draw_CachePic ("gfx/face_p1", true);
277 sb_faces[3][0] = Draw_CachePic ("gfx/face2", true);
278 sb_faces[3][1] = Draw_CachePic ("gfx/face_p2", true);
279 sb_faces[2][0] = Draw_CachePic ("gfx/face3", true);
280 sb_faces[2][1] = Draw_CachePic ("gfx/face_p3", true);
281 sb_faces[1][0] = Draw_CachePic ("gfx/face4", true);
282 sb_faces[1][1] = Draw_CachePic ("gfx/face_p4", true);
283 sb_faces[0][0] = Draw_CachePic ("gfx/face5", true);
284 sb_faces[0][1] = Draw_CachePic ("gfx/face_p5", true);
286 sb_face_invis = Draw_CachePic ("gfx/face_invis", true);
287 sb_face_invuln = Draw_CachePic ("gfx/face_invul2", true);
288 sb_face_invis_invuln = Draw_CachePic ("gfx/face_inv2", true);
289 sb_face_quad = Draw_CachePic ("gfx/face_quad", true);
291 sb_sbar = Draw_CachePic ("gfx/sbar", true);
292 sb_ibar = Draw_CachePic ("gfx/ibar", true);
293 sb_scorebar = Draw_CachePic ("gfx/scorebar", true);
295 //MED 01/04/97 added new hipnotic weapons
296 if (gamemode == GAME_HIPNOTIC)
298 hsb_weapons[0][0] = Draw_CachePic ("gfx/inv_laser", true);
299 hsb_weapons[0][1] = Draw_CachePic ("gfx/inv_mjolnir", true);
300 hsb_weapons[0][2] = Draw_CachePic ("gfx/inv_gren_prox", true);
301 hsb_weapons[0][3] = Draw_CachePic ("gfx/inv_prox_gren", true);
302 hsb_weapons[0][4] = Draw_CachePic ("gfx/inv_prox", true);
304 hsb_weapons[1][0] = Draw_CachePic ("gfx/inv2_laser", true);
305 hsb_weapons[1][1] = Draw_CachePic ("gfx/inv2_mjolnir", true);
306 hsb_weapons[1][2] = Draw_CachePic ("gfx/inv2_gren_prox", true);
307 hsb_weapons[1][3] = Draw_CachePic ("gfx/inv2_prox_gren", true);
308 hsb_weapons[1][4] = Draw_CachePic ("gfx/inv2_prox", true);
310 for (i = 0;i < 5;i++)
312 hsb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_laser",i+1), true);
313 hsb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_mjolnir",i+1), true);
314 hsb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_gren_prox",i+1), true);
315 hsb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_prox_gren",i+1), true);
316 hsb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_prox",i+1), true);
319 hsb_items[0] = Draw_CachePic ("gfx/sb_wsuit", true);
320 hsb_items[1] = Draw_CachePic ("gfx/sb_eshld", true);
322 else if (gamemode == GAME_ROGUE)
324 rsb_invbar[0] = Draw_CachePic ("gfx/r_invbar1", true);
325 rsb_invbar[1] = Draw_CachePic ("gfx/r_invbar2", true);
327 rsb_weapons[0] = Draw_CachePic ("gfx/r_lava", true);
328 rsb_weapons[1] = Draw_CachePic ("gfx/r_superlava", true);
329 rsb_weapons[2] = Draw_CachePic ("gfx/r_gren", true);
330 rsb_weapons[3] = Draw_CachePic ("gfx/r_multirock", true);
331 rsb_weapons[4] = Draw_CachePic ("gfx/r_plasma", true);
333 rsb_items[0] = Draw_CachePic ("gfx/r_shield1", true);
334 rsb_items[1] = Draw_CachePic ("gfx/r_agrav1", true);
336 // PGM 01/19/97 - team color border
337 rsb_teambord = Draw_CachePic ("gfx/r_teambord", true);
338 // PGM 01/19/97 - team color border
340 rsb_ammo[0] = Draw_CachePic ("gfx/r_ammolava", true);
341 rsb_ammo[1] = Draw_CachePic ("gfx/r_ammomulti", true);
342 rsb_ammo[2] = Draw_CachePic ("gfx/r_ammoplasma", true);
346 sb_ranking = Draw_CachePic ("gfx/ranking", true);
347 sb_complete = Draw_CachePic ("gfx/complete", true);
348 sb_inter = Draw_CachePic ("gfx/inter", true);
349 sb_finale = Draw_CachePic ("gfx/finale", true);
352 void sbar_shutdown(void)
356 void sbar_newmap(void)
360 void Sbar_Init (void)
362 Cmd_AddCommand("+showscores", Sbar_ShowScores, "show scoreboard");
363 Cmd_AddCommand("-showscores", Sbar_DontShowScores, "hide scoreboard");
364 Cvar_RegisterVariable(&showfps);
365 Cvar_RegisterVariable(&showtime);
366 Cvar_RegisterVariable(&showtime_format);
367 Cvar_RegisterVariable(&showdate);
368 Cvar_RegisterVariable(&showdate_format);
369 Cvar_RegisterVariable(&sbar_alpha_bg);
370 Cvar_RegisterVariable(&sbar_alpha_fg);
371 Cvar_RegisterVariable(&sbar_hudselector);
372 Cvar_RegisterVariable(&cl_deathscoreboard);
374 Cvar_RegisterVariable(&crosshair_color_red);
375 Cvar_RegisterVariable(&crosshair_color_green);
376 Cvar_RegisterVariable(&crosshair_color_blue);
377 Cvar_RegisterVariable(&crosshair_color_alpha);
378 Cvar_RegisterVariable(&crosshair_size);
380 R_RegisterModule("sbar", sbar_start, sbar_shutdown, sbar_newmap);
384 //=============================================================================
386 // drawing routines are relative to the status bar location
395 void Sbar_DrawStretchPic (int x, int y, cachepic_t *pic, float alpha, float overridewidth, float overrideheight)
397 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, overridewidth, overrideheight, 1, 1, 1, alpha, 0);
400 void Sbar_DrawPic (int x, int y, cachepic_t *pic)
402 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, sbar_alpha_fg.value, 0);
405 void Sbar_DrawAlphaPic (int x, int y, cachepic_t *pic, float alpha)
407 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, alpha, 0);
414 Draws one solid graphics character
417 void Sbar_DrawCharacter (int x, int y, int num)
419 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);
427 void Sbar_DrawString (int x, int y, char *str)
429 DrawQ_String (sbar_x + x, sbar_y + y, str, 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0, NULL, false);
437 void Sbar_DrawNum (int x, int y, int num, int digits, int color)
442 l = sprintf(str, "%i", num);
456 Sbar_DrawPic (x, y, sb_nums[color][frame]);
469 void Sbar_DrawXNum (int x, int y, int num, int digits, int lettersize, float r, float g, float b, float a, int flags)
477 l = sprintf(str, "%0*i", digits, num);
480 l = sprintf(str, "%i", num);
485 x += (digits-l) * lettersize;
494 DrawQ_Pic (sbar_x + x, sbar_y + y, sb_nums[0][frame],lettersize,lettersize,r,g,b,a * sbar_alpha_fg.value,flags);
501 //=============================================================================
504 int Sbar_IsTeammatch()
506 // currently only nexuiz uses the team score board
507 return ((gamemode == GAME_NEXUIZ)
508 && (teamplay.integer > 0));
516 static int fragsort[MAX_SCOREBOARD];
517 static int scoreboardlines;
519 //[515]: Sbar_GetPlayer for csqc "getplayerkey" func
520 int Sbar_GetPlayer (int index)
525 if(index >= scoreboardlines)
527 index = fragsort[index];
529 if(index >= scoreboardlines)
534 static scoreboard_t teams[MAX_SCOREBOARD];
535 static int teamsort[MAX_SCOREBOARD];
536 static int teamlines;
537 void Sbar_SortFrags (void)
543 for (i=0 ; i<cl.maxclients ; i++)
545 if (cl.scores[i].name[0])
547 fragsort[scoreboardlines] = i;
552 for (i=0 ; i<scoreboardlines ; i++)
553 for (j=0 ; j<scoreboardlines-1-i ; j++)
554 if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j+1]].frags)
557 fragsort[j] = fragsort[j+1];
562 if (Sbar_IsTeammatch ())
564 // now sort players by teams.
565 for (i=0 ; i<scoreboardlines ; i++)
567 for (j=0 ; j<scoreboardlines-1-i ; j++)
569 if (cl.scores[fragsort[j]].colors < cl.scores[fragsort[j+1]].colors)
572 fragsort[j] = fragsort[j+1];
578 // calculate team scores
580 for (i=0 ; i<scoreboardlines ; i++)
582 if (color != (cl.scores[fragsort[i]].colors & 15))
584 const char* teamname;
586 color = cl.scores[fragsort[i]].colors & 15;
592 teamname = "^1Red Team";
595 teamname = "^4Blue Team";
598 teamname = "^6Pink Team";
601 teamname = "^3Yellow Team";
604 teamname = "Total Team Score";
607 strlcpy(teams[teamlines-1].name, teamname, sizeof(teams[teamlines-1].name));
609 teams[teamlines-1].frags = 0;
610 teams[teamlines-1].colors = color + 16 * color;
613 if (cl.scores[fragsort[i]].frags != -666)
615 // do not add spedcators
616 // (ugly hack for nexuiz)
617 teams[teamlines-1].frags += cl.scores[fragsort[i]].frags;
621 // now sort teams by scores.
622 for (i=0 ; i<teamlines ; i++)
624 for (i=0 ; i<teamlines ; i++)
626 for (j=0 ; j<teamlines-1-i ; j++)
628 if (teams[teamsort[j]].frags < teams[teamsort[j+1]].frags)
631 teamsort[j] = teamsort[j+1];
644 void Sbar_SoloScoreboard (void)
647 char str[80], timestr[40];
649 int minutes, seconds;
652 t = (cl.intermission ? cl.completed_time : cl.time);
653 minutes = (int)(t / 60);
654 seconds = (int)(t - 60*floor(t/60));
656 // monsters and secrets are now both on the top row
657 if (cl.stats[STAT_TOTALMONSTERS])
658 Sbar_DrawString(8, 4, va("Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]));
659 if (cl.stats[STAT_TOTALSECRETS])
660 Sbar_DrawString(8+22*8, 4, va("Secrets:%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]));
662 // figure out the map's filename without path or extension
663 strlcpy(str, FS_FileWithoutPath(cl.worldmodel ? cl.worldmodel->name : ""), sizeof(str));
664 if (strrchr(str, '.'))
665 *(strrchr(str, '.')) = 0;
667 // append a : separator and then the full title
668 strlcat(str, ":", sizeof(str));
669 strlcat(str, cl.levelname, sizeof(str));
671 // if there's a newline character, terminate the string there
672 if (strchr(str, '\n'))
673 *(strchr(str, '\n')) = 0;
675 // make the time string
676 timelen = sprintf(timestr, " %i:%02i", minutes, seconds);
678 // truncate the level name if necessary to make room for time
680 if ((int)strlen(str) > max)
683 // print the filename and message
684 Sbar_DrawString(8, 12, str);
687 Sbar_DrawString(8 + max*8, 12, timestr);
691 int minutes, seconds, tens, units;
694 if (gamemode != GAME_NEXUIZ) {
695 sprintf (str,"Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
696 Sbar_DrawString (8, 4, str);
698 sprintf (str,"Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
699 Sbar_DrawString (8, 12, str);
703 minutes = (int)(cl.time / 60);
704 seconds = (int)(cl.time - 60*minutes);
706 units = seconds - 10*tens;
707 sprintf (str,"Time :%3i:%i%i", minutes, tens, units);
708 Sbar_DrawString (184, 4, str);
711 if (gamemode == GAME_NEXUIZ) {
712 l = (int) strlen (cl.worldmodel->name);
713 Sbar_DrawString (232 - l*4, 12, cl.worldmodel->name);
715 l = (int) strlen (cl.levelname);
716 Sbar_DrawString (232 - l*4, 12, cl.levelname);
726 void Sbar_DrawScoreboard (void)
728 Sbar_SoloScoreboard ();
729 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
730 //if (cl.gametype == GAME_DEATHMATCH)
732 Sbar_DeathmatchOverlay ();
735 //=============================================================================
737 // AK to make DrawInventory smaller
738 static void Sbar_DrawWeapon(int nr, float fade, int active)
740 if (sbar_hudselector.integer == 1)
742 // width = 300, height = 100
743 const int w_width = 32, w_height = 12, w_space = 2, font_size = 8;
745 DrawQ_Pic((vid_conwidth.integer - w_width * 9) * 0.5 + w_width * nr, vid_conheight.integer - w_height, sb_weapons[0][nr], w_width, w_height, (active) ? 1 : 0.6, active ? 1 : 0.6, active ? 1 : 0.6, (active ? 1 : 0.6) * fade * sbar_alpha_fg.value, DRAWFLAG_NORMAL);
746 DrawQ_String((vid_conwidth.integer - w_width * 9) * 0.5 + w_width * nr + w_space, vid_conheight.integer - w_height + w_space, va("%i",nr+1), 0, font_size, font_size, 1, 1, 0, sbar_alpha_fg.value, 0, NULL, true);
750 // width = 300, height = 100
751 const int w_width = 300, w_height = 100, w_space = 10;
752 const float w_scale = 0.4;
754 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);
755 //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);
764 void Sbar_DrawInventory (void)
771 if (gamemode == GAME_ROGUE)
773 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
774 Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], sbar_alpha_bg.value);
776 Sbar_DrawAlphaPic (0, -24, rsb_invbar[1], sbar_alpha_bg.value);
779 Sbar_DrawAlphaPic (0, -24, sb_ibar, sbar_alpha_bg.value);
782 for (i=0 ; i<7 ; i++)
784 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<i) )
786 time = cl.item_gettime[i];
787 flashon = (int)(max(0, cl.time - time)*10);
790 if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i) )
796 flashon = (flashon%5) + 2;
798 Sbar_DrawAlphaPic (i*24, -16, sb_weapons[flashon][i], sbar_alpha_bg.value);
804 if (gamemode == GAME_HIPNOTIC)
806 int grenadeflashing=0;
807 for (i=0 ; i<4 ; i++)
809 if (cl.stats[STAT_ITEMS] & (1<<hipweapons[i]) )
811 time = max(0, cl.item_gettime[hipweapons[i]]);
812 flashon = (int)((cl.time - time)*10);
815 if ( cl.stats[STAT_ACTIVEWEAPON] == (1<<hipweapons[i]) )
821 flashon = (flashon%5) + 2;
823 // check grenade launcher
826 if (cl.stats[STAT_ITEMS] & HIT_PROXIMITY_GUN)
831 Sbar_DrawPic (96, -16, hsb_weapons[flashon][2]);
837 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<4))
839 if (!grenadeflashing)
840 Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
843 Sbar_DrawPic (96, -16, hsb_weapons[flashon][4]);
846 Sbar_DrawPic (176 + (i*24), -16, hsb_weapons[flashon][i]);
851 if (gamemode == GAME_ROGUE)
853 // check for powered up weapon.
854 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
856 if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i))
857 Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]);
861 for (i=0 ; i<4 ; i++)
863 sprintf (num, "%3i",cl.stats[STAT_SHELLS+i] );
865 Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[0] - '0');
867 Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[1] - '0');
869 Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0');
873 for (i=0 ; i<6 ; i++)
874 if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
876 //MED 01/04/97 changed keys
877 if (gamemode != GAME_HIPNOTIC || (i>1))
878 Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
881 //MED 01/04/97 added hipnotic items
883 if (gamemode == GAME_HIPNOTIC)
885 for (i=0 ; i<2 ; i++)
886 if (cl.stats[STAT_ITEMS] & (1<<(24+i)))
887 Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
890 if (gamemode == GAME_ROGUE)
893 for (i=0 ; i<2 ; i++)
894 if (cl.stats[STAT_ITEMS] & (1<<(29+i)))
895 Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
900 for (i=0 ; i<4 ; i++)
901 if (cl.stats[STAT_ITEMS] & (1<<(28+i)))
902 Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
906 //=============================================================================
913 void Sbar_DrawFrags (void)
923 l = min(scoreboardlines, 4);
927 for (i = 0;i < l;i++)
933 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
934 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);
935 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
936 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);
940 sprintf (num, "%3i",f);
942 if (k == cl.viewentity - 1)
944 Sbar_DrawCharacter ( x + 2, -24, 16);
945 Sbar_DrawCharacter ( x + 32 - 4, -24, 17);
947 Sbar_DrawCharacter (x + 8, -24, num[0]);
948 Sbar_DrawCharacter (x + 16, -24, num[1]);
949 Sbar_DrawCharacter (x + 24, -24, num[2]);
954 //=============================================================================
962 void Sbar_DrawFace (void)
966 // PGM 01/19/97 - team color drawing
967 // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
968 if (gamemode == GAME_ROGUE && !cl.islocalgame && (teamplay.integer > 3) && (teamplay.integer < 7))
974 s = &cl.scores[cl.viewentity - 1];
976 Sbar_DrawPic (112, 0, rsb_teambord);
977 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
978 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);
979 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
980 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);
984 sprintf (num, "%3i",f);
986 if ((s->colors & 0xf0)==0)
989 Sbar_DrawCharacter(109, 3, 18 + num[0] - '0');
991 Sbar_DrawCharacter(116, 3, 18 + num[1] - '0');
993 Sbar_DrawCharacter(123, 3, 18 + num[2] - '0');
997 Sbar_DrawCharacter ( 109, 3, num[0]);
998 Sbar_DrawCharacter ( 116, 3, num[1]);
999 Sbar_DrawCharacter ( 123, 3, num[2]);
1004 // PGM 01/19/97 - team color drawing
1006 if ( (cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
1007 Sbar_DrawPic (112, 0, sb_face_invis_invuln);
1008 else if (cl.stats[STAT_ITEMS] & IT_QUAD)
1009 Sbar_DrawPic (112, 0, sb_face_quad );
1010 else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
1011 Sbar_DrawPic (112, 0, sb_face_invis );
1012 else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1013 Sbar_DrawPic (112, 0, sb_face_invuln);
1016 f = cl.stats[STAT_HEALTH] / 20;
1018 Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]);
1022 void Sbar_ShowFPS(void)
1024 float fps_x, fps_y, fps_scalex, fps_scaley, fps_height;
1026 char timestring[32];
1027 char datestring[32];
1028 qboolean red = false;
1032 if (showfps.integer)
1035 static double nexttime = 0, lasttime = 0;
1036 static double framerate = 0;
1037 static int framecount = 0;
1040 if (newtime >= nexttime)
1042 framerate = framecount / (newtime - lasttime);
1044 nexttime = max(nexttime + 1, lasttime - 1);
1050 if ((red = (calc < 1.0f)))
1051 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0f / calc + 0.5));
1053 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(calc + 0.5));
1055 if (showtime.integer)
1056 strlcpy(timestring, Sys_TimeString(showtime_format.string), sizeof(timestring));
1057 if (showdate.integer)
1058 strlcpy(datestring, Sys_TimeString(showdate_format.string), sizeof(datestring));
1059 if (fpsstring[0] || timestring[0])
1063 fps_height = fps_scaley * ((fpsstring[0] != 0) + (timestring[0] != 0) + (datestring[0] != 0));
1064 //fps_y = vid_conheight.integer - sb_lines; // yes this may draw over the sbar
1065 //fps_y = bound(0, fps_y, vid_conheight.integer - fps_height);
1066 fps_y = vid_conheight.integer - fps_height;
1069 fps_x = vid_conwidth.integer - fps_scalex * strlen(fpsstring);
1070 DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(fpsstring), fps_scaley, 0, 0, 0, 0.5, 0);
1072 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 0, 0, 1, 0, NULL, true);
1074 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true);
1075 fps_y += fps_scaley;
1079 fps_x = vid_conwidth.integer - fps_scalex * strlen(timestring);
1080 DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(timestring), fps_scaley, 0, 0, 0, 0.5, 0);
1081 DrawQ_String(fps_x, fps_y, timestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true);
1082 fps_y += fps_scaley;
1086 fps_x = vid_conwidth.integer - fps_scalex * strlen(datestring);
1087 DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(datestring), fps_scaley, 0, 0, 0, 0.5, 0);
1088 DrawQ_String(fps_x, fps_y, datestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true);
1089 fps_y += fps_scaley;
1094 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)
1097 c2 = bound(0, c2, 1);
1098 c1 = bound(0, c1, 1 - c2);
1100 r[1] = rangey + rangeheight * (c2 + c1);
1101 r[2] = rangey + rangeheight * (c2);
1105 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);
1107 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);
1109 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);
1111 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);
1119 extern float v_dmg_time, v_dmg_roll, v_dmg_pitch;
1120 extern cvar_t v_kicktime;
1121 void Sbar_Score (void);
1122 void Sbar_Draw (void)
1126 if(cl.csqc_vidvars.drawenginesbar) //[515]: csqc drawsbar
1129 Sbar_DrawScoreboard ();
1130 else if (cl.intermission == 1)
1132 if(gamemode == GAME_NEXUIZ) // display full scoreboard (that is, show scores + map name)
1134 Sbar_DrawScoreboard();
1137 Sbar_IntermissionOverlay();
1139 else if (cl.intermission == 2)
1140 Sbar_FinaleOverlay();
1141 else if (gamemode == GAME_NETHERWORLD)
1144 else if (gamemode == GAME_SOM)
1146 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1147 Sbar_DrawScoreboard ();
1150 // this is the top left of the sbar area
1152 sbar_y = vid_conheight.integer - 24*3;
1155 if (cl.stats[STAT_ARMOR])
1157 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1158 Sbar_DrawPic(0, 0, somsb_armor[2]);
1159 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1160 Sbar_DrawPic(0, 0, somsb_armor[1]);
1161 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1162 Sbar_DrawPic(0, 0, somsb_armor[0]);
1163 Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1167 Sbar_DrawPic(0, 24, somsb_health);
1168 Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1171 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1172 Sbar_DrawPic(0, 48, somsb_ammo[0]);
1173 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1174 Sbar_DrawPic(0, 48, somsb_ammo[1]);
1175 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1176 Sbar_DrawPic(0, 48, somsb_ammo[2]);
1177 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1178 Sbar_DrawPic(0, 48, somsb_ammo[3]);
1179 Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
1180 if (cl.stats[STAT_SHELLS])
1181 Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
1184 else if (gamemode == GAME_NEXUIZ)
1186 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1188 sbar_x = (vid_conwidth.integer - 640)/2;
1189 sbar_y = vid_conheight.integer - 47;
1190 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1191 Sbar_DrawScoreboard ();
1193 else if (sb_lines && sbar_hudselector.integer == 1)
1197 int redflag, blueflag;
1199 sbar_x = (vid_conwidth.integer - 320)/2;
1200 sbar_y = vid_conheight.integer - 24 - 16;
1202 // calculate intensity to draw weapons bar at
1203 fade = 3.2 - 2 * (cl.time - cl.weapontime);
1204 fade = bound(0.7, fade, 1);
1205 for (i = 0; i < 8;i++)
1206 if (cl.stats[STAT_ITEMS] & (1 << i))
1207 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1208 if((cl.stats[STAT_ITEMS] & (1<<12)))
1209 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1212 redflag = ((cl.stats[STAT_ITEMS]>>15) & 3);
1213 blueflag = ((cl.stats[STAT_ITEMS]>>17) & 3);
1214 if (redflag == 3 && blueflag == 3)
1216 // The Impossible Combination[tm]
1217 // Can only happen in Key Hunt mode...
1218 Sbar_DrawPic (10 - sbar_x, -179, sb_items[14]);
1223 Sbar_DrawPic (10 - sbar_x, -109, sb_items[redflag+10]);
1225 Sbar_DrawPic (10 - sbar_x, -169, sb_items[blueflag+14]);
1229 if (cl.stats[STAT_ARMOR] > 0)
1231 Sbar_DrawStretchPic (0, 0, sb_armor[0], sbar_alpha_fg.value, 24, 24);
1232 if(cl.stats[STAT_ARMOR] > 100)
1233 Sbar_DrawXNum(24,0,cl.stats[STAT_ARMOR],3,24,1,1,0,1,0);
1234 else if(cl.stats[STAT_ARMOR] > 25)
1235 Sbar_DrawXNum(24,0,cl.stats[STAT_ARMOR],3,24,0.6,0.7,0.8,1,0);
1237 Sbar_DrawXNum(24,0,cl.stats[STAT_ARMOR],3,24,0.7,0,0,1,0);
1241 if (cl.stats[STAT_HEALTH] != 0)
1243 Sbar_DrawStretchPic (112, 0, sb_health, sbar_alpha_fg.value, 24, 24);
1244 if(cl.stats[STAT_HEALTH] > 100)
1245 Sbar_DrawXNum(136,0,cl.stats[STAT_HEALTH],3,24,1,1,0,1,0);
1246 else if(cl.stats[STAT_HEALTH] > 25)
1247 Sbar_DrawXNum(136,0,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1249 Sbar_DrawXNum(136,0,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1253 if ((cl.stats[STAT_ITEMS] & (NEX_IT_SHELLS | NEX_IT_BULLETS | NEX_IT_ROCKETS | NEX_IT_CELLS)) || cl.stats[STAT_AMMO] != 0)
1255 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1256 Sbar_DrawStretchPic (224, 0, sb_ammo[0], sbar_alpha_fg.value, 24, 24);
1257 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1258 Sbar_DrawStretchPic (224, 0, sb_ammo[1], sbar_alpha_fg.value, 24, 24);
1259 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1260 Sbar_DrawStretchPic (224, 0, sb_ammo[2], sbar_alpha_fg.value, 24, 24);
1261 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1262 Sbar_DrawStretchPic (224, 0, sb_ammo[3], sbar_alpha_fg.value, 24, 24);
1263 if(cl.stats[STAT_AMMO] > 10)
1264 Sbar_DrawXNum(248, 0, cl.stats[STAT_AMMO], 3, 24, 0.6,0.7,0.8,1,0);
1266 Sbar_DrawXNum(248, 0, cl.stats[STAT_AMMO], 3, 24, 0.7,0,0,1,0);
1269 if (sbar_x + 320 + 160 <= vid_conwidth.integer)
1270 Sbar_MiniDeathmatchOverlay (sbar_x + 320, sbar_y);
1278 int redflag, blueflag;
1280 sbar_x = (vid_conwidth.integer - 640)/2;
1281 sbar_y = vid_conheight.integer - 47;
1283 // calculate intensity to draw weapons bar at
1284 fade = 3 - 2 * (cl.time - cl.weapontime);
1287 fade = min(fade, 1);
1288 for (i = 0; i < 8;i++)
1289 if (cl.stats[STAT_ITEMS] & (1 << i))
1290 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1292 if((cl.stats[STAT_ITEMS] & (1<<12)))
1293 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1296 //if (!cl.islocalgame)
1297 // Sbar_DrawFrags ();
1300 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1302 Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1305 redflag = ((cl.stats[STAT_ITEMS]>>15) & 3);
1306 blueflag = ((cl.stats[STAT_ITEMS]>>17) & 3);
1307 if (redflag == 3 && blueflag == 3)
1309 // The Impossible Combination[tm]
1310 // Can only happen in Key Hunt mode...
1311 Sbar_DrawPic (10 - sbar_x, -179, sb_items[14]);
1316 Sbar_DrawPic (10 - sbar_x, -109, sb_items[redflag+10]);
1318 Sbar_DrawPic (10 - sbar_x, -169, sb_items[blueflag+14]);
1322 Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1325 if(cl.stats[STAT_HEALTH] > 100)
1326 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1327 else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1328 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1330 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1332 // AK dont draw ammo for the laser
1333 if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1335 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1336 Sbar_DrawPic (519, 0, sb_ammo[0]);
1337 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1338 Sbar_DrawPic (519, 0, sb_ammo[1]);
1339 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1340 Sbar_DrawPic (519, 0, sb_ammo[2]);
1341 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1342 Sbar_DrawPic (519, 0, sb_ammo[3]);
1344 if(cl.stats[STAT_AMMO] <= 10)
1345 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1347 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1352 DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1354 if (sbar_x + 600 + 160 <= vid_conwidth.integer)
1355 Sbar_MiniDeathmatchOverlay (sbar_x + 600, sbar_y);
1361 else if (gamemode == GAME_ZYMOTIC)
1364 float scale = 64.0f / 256.0f;
1365 float kickoffset[3];
1366 VectorClear(kickoffset);
1369 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1370 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1372 sbar_x = (int)((vid_conwidth.integer - 256 * scale)/2 + kickoffset[0]);
1373 sbar_y = (int)((vid_conheight.integer - 256 * scale)/2 + kickoffset[1]);
1374 // left1 16, 48 : 126 -66
1375 // left2 16, 128 : 196 -66
1376 // right 176, 48 : 196 -136
1377 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);
1378 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);
1379 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);
1380 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1382 float scale = 128.0f / 256.0f;
1383 float healthstart, healthheight, healthstarttc, healthendtc;
1384 float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1385 float ammostart, ammoheight, ammostarttc, ammoendtc;
1386 float clipstart, clipheight, clipstarttc, clipendtc;
1387 float kickoffset[3], offset;
1388 VectorClear(kickoffset);
1391 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1392 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1394 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1395 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1396 offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1397 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);
1398 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);
1399 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);
1400 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);
1401 healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1402 shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1403 healthstart = 204 - healthheight;
1404 shieldstart = healthstart - shieldheight;
1405 healthstarttc = healthstart * (1.0f / 256.0f);
1406 healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1407 shieldstarttc = shieldstart * (1.0f / 256.0f);
1408 shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1409 ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1410 ammostart = 114 - ammoheight;
1411 ammostarttc = ammostart * (1.0f / 256.0f);
1412 ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1413 clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1414 clipstart = 190 - clipheight;
1415 clipstarttc = clipstart * (1.0f / 256.0f);
1416 clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1417 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);
1418 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);
1419 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);
1420 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);
1421 DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1422 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1425 else // Quake and others
1427 sbar_x = (vid_conwidth.integer - 320)/2;
1428 sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1429 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1430 //if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1434 if (gamemode != GAME_GOODVSBAD2)
1435 Sbar_DrawInventory ();
1436 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1440 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1442 if (gamemode != GAME_GOODVSBAD2)
1443 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1444 Sbar_DrawScoreboard ();
1448 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1450 // keys (hipnotic only)
1451 //MED 01/04/97 moved keys here so they would not be overwritten
1452 if (gamemode == GAME_HIPNOTIC)
1454 if (cl.stats[STAT_ITEMS] & IT_KEY1)
1455 Sbar_DrawPic (209, 3, sb_items[0]);
1456 if (cl.stats[STAT_ITEMS] & IT_KEY2)
1457 Sbar_DrawPic (209, 12, sb_items[1]);
1460 if (gamemode != GAME_GOODVSBAD2)
1462 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1464 Sbar_DrawNum (24, 0, 666, 3, 1);
1465 Sbar_DrawPic (0, 0, sb_disc);
1469 if (gamemode == GAME_ROGUE)
1471 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1472 if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1473 Sbar_DrawPic (0, 0, sb_armor[2]);
1474 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1475 Sbar_DrawPic (0, 0, sb_armor[1]);
1476 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1477 Sbar_DrawPic (0, 0, sb_armor[0]);
1481 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1482 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1483 Sbar_DrawPic (0, 0, sb_armor[2]);
1484 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1485 Sbar_DrawPic (0, 0, sb_armor[1]);
1486 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1487 Sbar_DrawPic (0, 0, sb_armor[0]);
1496 Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1499 if (gamemode == GAME_ROGUE)
1501 if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1502 Sbar_DrawPic (224, 0, sb_ammo[0]);
1503 else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1504 Sbar_DrawPic (224, 0, sb_ammo[1]);
1505 else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1506 Sbar_DrawPic (224, 0, sb_ammo[2]);
1507 else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1508 Sbar_DrawPic (224, 0, sb_ammo[3]);
1509 else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1510 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1511 else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1512 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1513 else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1514 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1518 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1519 Sbar_DrawPic (224, 0, sb_ammo[0]);
1520 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1521 Sbar_DrawPic (224, 0, sb_ammo[1]);
1522 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1523 Sbar_DrawPic (224, 0, sb_ammo[2]);
1524 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1525 Sbar_DrawPic (224, 0, sb_ammo[3]);
1528 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1532 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1533 if ((!cl.islocalgame || cl.gametype != GAME_COOP))
1535 if (gamemode == GAME_TRANSFUSION)
1536 Sbar_MiniDeathmatchOverlay (0, 0);
1538 Sbar_MiniDeathmatchOverlay (sbar_x + 324, vid_conheight.integer - 8*8);
1546 if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && crosshair.integer <= NUMCROSSHAIRS && !cl.intermission && !r_letterbox.value && (pic = r_crosshairs[crosshair.integer]))
1547 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);
1549 if (cl_prydoncursor.integer)
1550 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);
1553 //=============================================================================
1557 Sbar_DeathmatchOverlay
1561 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1564 qboolean myself = false;
1566 minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : cl.time - s->qw_entertime) / 60.0);
1568 if((s - cl.scores) == cl.playerentity - 1)
1570 if((s - teams) >= 0 && (s - teams) < MAX_SCOREBOARD)
1571 if((s->colors & 15) == (cl.scores[cl.playerentity - 1].colors & 15))
1574 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1576 if (s->qw_spectator)
1578 if (s->qw_ping || s->qw_packetloss)
1579 DrawQ_String(x, y, va("%4i %3i %4i spectator %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1581 DrawQ_String(x, y, va(" %4i spectator %c%s", minutes, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1585 // draw colors behind score
1586 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1587 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);
1588 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1589 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);
1591 //DrawQ_String(x, y, va("%c%4i %s", myself ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, true);
1592 if (s->qw_ping || s->qw_packetloss)
1593 DrawQ_String(x, y, va("%4i %3i %4i %5i %-4s %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1595 DrawQ_String(x, y, va(" %4i %5i %-4s %c%s", minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1600 if (s->qw_spectator)
1602 if (s->qw_ping || s->qw_packetloss)
1603 DrawQ_String(x, y, va("%4i %3i spect %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1605 DrawQ_String(x, y, va(" spect %c%s", myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1609 // draw colors behind score
1610 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1611 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);
1612 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1613 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);
1615 //DrawQ_String(x, y, va("%c%4i %s", myself ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, true);
1616 if (s->qw_ping || s->qw_packetloss)
1617 DrawQ_String(x, y, va("%4i %3i %5i %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), (int) s->frags, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1619 DrawQ_String(x, y, va(" %5i %c%s", (int) s->frags, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1625 void Sbar_DeathmatchOverlay (void)
1629 // request new ping times every two second
1630 if (cl.last_ping_request < realtime - 2 && cls.netcon)
1632 cl.last_ping_request = realtime;
1633 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1635 MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
1636 MSG_WriteString(&cls.netcon->message, "pings");
1638 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*/)
1640 // 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
1641 static int ping_anyway_counter = 0;
1642 if(cl.parsingtextexpectingpingforscores == 1)
1644 Con_DPrintf("want to send ping, but still waiting for other reply\n");
1645 if(++ping_anyway_counter >= 5)
1646 cl.parsingtextexpectingpingforscores = 0;
1648 if(cl.parsingtextexpectingpingforscores != 1)
1650 ping_anyway_counter = 0;
1651 cl.parsingtextexpectingpingforscores = 1; // hide the output of the next ping report
1652 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1653 MSG_WriteString(&cls.netcon->message, "ping");
1658 // 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
1659 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1660 MSG_WriteString(&cls.netcon->message, "pings");
1664 DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1670 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1672 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)
1673 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 );
1677 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)
1678 DrawQ_String(x, y, va("ping pl%% frags name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1682 if (Sbar_IsTeammatch ())
1684 // show team scores first
1685 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1686 y += (int)Sbar_PrintScoreboardItem((teams + teamsort[i]), x, y);
1690 for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1691 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1696 Sbar_MiniDeathmatchOverlay
1700 void Sbar_MiniDeathmatchOverlay (int x, int y)
1702 int i, j, numlines, range_begin, range_end, myteam, teamsep;
1707 // decide where to print
1708 if (gamemode == GAME_TRANSFUSION)
1709 numlines = (vid_conwidth.integer - x + 127) / 128;
1711 numlines = (vid_conheight.integer - y + 7) / 8;
1713 // give up if there isn't room
1714 if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1718 for (i = 0; i < scoreboardlines; i++)
1719 if (fragsort[i] == cl.playerentity - 1)
1723 range_end = scoreboardlines;
1726 if (gamemode != GAME_TRANSFUSION)
1727 if (Sbar_IsTeammatch ())
1729 // reserve space for the team scores
1730 numlines -= teamlines;
1732 // find first and last player of my team (only draw the team totals and my own team)
1733 range_begin = range_end = i;
1734 myteam = cl.scores[fragsort[i]].colors & 15;
1735 while(range_begin > 0 && (cl.scores[fragsort[range_begin-1]].colors & 15) == myteam)
1737 while(range_end < scoreboardlines && (cl.scores[fragsort[range_end]].colors & 15) == myteam)
1740 // looks better than two players
1750 i = min(i, range_end - numlines);
1751 i = max(i, range_begin);
1753 if (gamemode == GAME_TRANSFUSION)
1755 for (;i < range_end && x < vid_conwidth.integer;i++)
1756 x += 128 + (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1760 if(range_end - i < numlines) // won't draw to bottom?
1761 y += 8 * (numlines - (range_end - i)); // bottom align
1762 // show team scores first
1763 for (j = 0;j < teamlines && y < vid_conheight.integer;j++)
1764 y += (int)Sbar_PrintScoreboardItem((teams + teamsort[j]), x, y);
1766 for (;i < range_end && y < vid_conheight.integer;i++)
1767 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1771 void Sbar_Score (void)
1773 int i, me, score, otherleader, place, distribution, minutes, seconds;
1776 sbar_y = vid_conheight.value - (32+12);
1777 me = cl.playerentity - 1;
1778 if (me >= 0 && me < cl.maxclients)
1780 // find leading score other than ourselves, to calculate distribution
1781 // find our place in the scoreboard
1782 score = cl.scores[me].frags;
1783 for (i = 0, otherleader = -1, place = 1;i < cl.maxclients;i++)
1785 if (cl.scores[i].name[0] && i != me)
1787 if (otherleader == -1 || cl.scores[i].frags > cl.scores[otherleader].frags)
1789 if (score < cl.scores[i].frags || (score == cl.scores[i].frags && i < me))
1793 distribution = otherleader >= 0 ? score - cl.scores[otherleader].frags : 0;
1795 Sbar_DrawXNum(-3*12-24, -12, place, 3, 12, 1, 1, 1, 1, 0);
1796 else if (place == 2)
1797 Sbar_DrawXNum(-3*12-24, -12, place, 3, 12, 1, 1, 0, 1, 0);
1799 Sbar_DrawXNum(-3*12-24, -12, place, 3, 12, 1, 0, 0, 1, 0);
1800 if (otherleader < 0)
1801 Sbar_DrawXNum(-32*4-24, 0, score, 4, 32, 1, 1, 1, 1, 0);
1802 if (distribution >= 0)
1804 Sbar_DrawXNum(-7*12-24, -12, distribution, 4, 12, 1, 1, 1, 1, 0);
1805 Sbar_DrawXNum(-32*4-24, 0, score, 4, 32, 1, 1, 1, 1, 0);
1807 else if (distribution >= -5)
1809 Sbar_DrawXNum(-7*12-24, -12, distribution, 4, 12, 1, 1, 0, 1, 0);
1810 Sbar_DrawXNum(-32*4-24, 0, score, 4, 32, 1, 1, 0, 1, 0);
1814 Sbar_DrawXNum(-7*12-24, -12, distribution, 4, 12, 1, 0, 0, 1, 0);
1815 Sbar_DrawXNum(-32*4-24, 0, score, 4, 32, 1, 0, 0, 1, 0);
1819 if (cl.statsf[STAT_TIMELIMIT])
1821 timeleft = max(0, cl.statsf[STAT_TIMELIMIT] * 60 - cl.time);
1822 minutes = (int)floor(timeleft / 60);
1823 seconds = (int)(floor(timeleft) - minutes * 60);
1826 Sbar_DrawXNum(-12*6-24, 32, minutes, 3, 12, 1, 1, 1, 1, 0);
1827 Sbar_DrawXNum(-12*2-24, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
1829 else if (minutes >= 1)
1831 Sbar_DrawXNum(-12*6-24, 32, minutes, 3, 12, 1, 1, 0, 1, 0);
1832 Sbar_DrawXNum(-12*2-24, 32, seconds, -2, 12, 1, 1, 0, 1, 0);
1834 else if ((int)(timeleft * 4) & 1)
1835 Sbar_DrawXNum(-12*2-24, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
1837 Sbar_DrawXNum(-12*2-24, 32, seconds, -2, 12, 1, 0, 0, 1, 0);
1841 minutes = (int)floor(cl.time / 60);
1842 seconds = (int)(floor(cl.time) - minutes * 60);
1843 Sbar_DrawXNum(-12*6-24, 32, minutes, 3, 12, 1, 1, 1, 1, 0);
1844 Sbar_DrawXNum(-12*2-24, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
1850 Sbar_IntermissionOverlay
1854 void Sbar_IntermissionOverlay (void)
1859 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1860 //if (cl.gametype == GAME_DEATHMATCH)
1861 if (!cl.islocalgame)
1863 Sbar_DeathmatchOverlay ();
1867 sbar_x = (vid_conwidth.integer - 320) >> 1;
1868 sbar_y = (vid_conheight.integer - 200) >> 1;
1870 DrawQ_Pic (sbar_x + 64, sbar_y + 24, sb_complete, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1871 DrawQ_Pic (sbar_x + 0, sbar_y + 56, sb_inter, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1874 dig = (int)cl.completed_time / 60;
1875 Sbar_DrawNum (160, 64, dig, 3, 0);
1876 num = (int)cl.completed_time - dig*60;
1877 if (gamemode != GAME_NEXUIZ)
1878 Sbar_DrawPic (234,64,sb_colon);
1879 Sbar_DrawPic (246,64,sb_nums[0][num/10]);
1880 Sbar_DrawPic (266,64,sb_nums[0][num%10]);
1882 Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
1883 if (gamemode != GAME_NEXUIZ)
1884 Sbar_DrawPic (232, 104, sb_slash);
1885 Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1887 Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1888 if (gamemode != GAME_NEXUIZ)
1889 Sbar_DrawPic (232, 144, sb_slash);
1890 Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1901 void Sbar_FinaleOverlay (void)
1903 DrawQ_Pic((vid_conwidth.integer - sb_finale->width)/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);