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_y = vid_conheight.integer - SBAR_HEIGHT;
1428 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1429 //if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1430 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1433 sbar_x = (vid_conwidth.integer - 320)/2;
1437 if (gamemode != GAME_GOODVSBAD2)
1438 Sbar_DrawInventory ();
1439 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1443 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1445 if (gamemode != GAME_GOODVSBAD2)
1446 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1447 Sbar_DrawScoreboard ();
1451 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1453 // keys (hipnotic only)
1454 //MED 01/04/97 moved keys here so they would not be overwritten
1455 if (gamemode == GAME_HIPNOTIC)
1457 if (cl.stats[STAT_ITEMS] & IT_KEY1)
1458 Sbar_DrawPic (209, 3, sb_items[0]);
1459 if (cl.stats[STAT_ITEMS] & IT_KEY2)
1460 Sbar_DrawPic (209, 12, sb_items[1]);
1463 if (gamemode != GAME_GOODVSBAD2)
1465 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1467 Sbar_DrawNum (24, 0, 666, 3, 1);
1468 Sbar_DrawPic (0, 0, sb_disc);
1472 if (gamemode == GAME_ROGUE)
1474 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1475 if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1476 Sbar_DrawPic (0, 0, sb_armor[2]);
1477 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1478 Sbar_DrawPic (0, 0, sb_armor[1]);
1479 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1480 Sbar_DrawPic (0, 0, sb_armor[0]);
1484 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1485 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1486 Sbar_DrawPic (0, 0, sb_armor[2]);
1487 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1488 Sbar_DrawPic (0, 0, sb_armor[1]);
1489 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1490 Sbar_DrawPic (0, 0, sb_armor[0]);
1499 Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1502 if (gamemode == GAME_ROGUE)
1504 if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1505 Sbar_DrawPic (224, 0, sb_ammo[0]);
1506 else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1507 Sbar_DrawPic (224, 0, sb_ammo[1]);
1508 else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1509 Sbar_DrawPic (224, 0, sb_ammo[2]);
1510 else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1511 Sbar_DrawPic (224, 0, sb_ammo[3]);
1512 else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1513 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1514 else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1515 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1516 else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1517 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1521 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1522 Sbar_DrawPic (224, 0, sb_ammo[0]);
1523 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1524 Sbar_DrawPic (224, 0, sb_ammo[1]);
1525 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1526 Sbar_DrawPic (224, 0, sb_ammo[2]);
1527 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1528 Sbar_DrawPic (224, 0, sb_ammo[3]);
1531 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1535 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1536 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1537 if (!cl.islocalgame && vid_conwidth.integer > 320)
1539 if (gamemode == GAME_TRANSFUSION)
1540 Sbar_MiniDeathmatchOverlay (0, 0);
1542 Sbar_MiniDeathmatchOverlay (324, vid_conheight.integer - sb_lines);
1551 if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && crosshair.integer <= NUMCROSSHAIRS && !cl.intermission && !r_letterbox.value && (pic = r_crosshairs[crosshair.integer]))
1552 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);
1554 if (cl_prydoncursor.integer)
1555 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);
1558 //=============================================================================
1562 Sbar_DeathmatchOverlay
1566 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1569 qboolean myself = false;
1571 minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : cl.time - s->qw_entertime) / 60.0);
1573 if((s - cl.scores) == cl.playerentity - 1)
1575 if((s - teams) >= 0 && (s - teams) < MAX_SCOREBOARD)
1576 if((s->colors & 15) == (cl.scores[cl.playerentity - 1].colors & 15))
1579 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1581 if (s->qw_spectator)
1583 if (s->qw_ping || s->qw_packetloss)
1584 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 );
1586 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 );
1590 // draw colors behind score
1591 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1592 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);
1593 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1594 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);
1596 //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);
1597 if (s->qw_ping || s->qw_packetloss)
1598 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 );
1600 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 );
1605 if (s->qw_spectator)
1607 if (s->qw_ping || s->qw_packetloss)
1608 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 );
1610 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 );
1614 // draw colors behind score
1615 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1616 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);
1617 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1618 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);
1620 //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);
1621 if (s->qw_ping || s->qw_packetloss)
1622 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 );
1624 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 );
1630 void Sbar_DeathmatchOverlay (void)
1634 // request new ping times every two second
1635 if (cl.last_ping_request < realtime - 2 && cls.netcon)
1637 cl.last_ping_request = realtime;
1638 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1640 MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
1641 MSG_WriteString(&cls.netcon->message, "pings");
1643 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*/)
1645 // 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
1646 static int ping_anyway_counter = 0;
1647 if(cl.parsingtextexpectingpingforscores == 1)
1649 Con_DPrintf("want to send ping, but still waiting for other reply\n");
1650 if(++ping_anyway_counter >= 5)
1651 cl.parsingtextexpectingpingforscores = 0;
1653 if(cl.parsingtextexpectingpingforscores != 1)
1655 ping_anyway_counter = 0;
1656 cl.parsingtextexpectingpingforscores = 1; // hide the output of the next ping report
1657 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1658 MSG_WriteString(&cls.netcon->message, "ping");
1663 // 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
1664 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1665 MSG_WriteString(&cls.netcon->message, "pings");
1669 DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1675 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1677 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)
1678 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 );
1682 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)
1683 DrawQ_String(x, y, va("ping pl%% frags name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1687 if (Sbar_IsTeammatch ())
1689 // show team scores first
1690 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1691 y += (int)Sbar_PrintScoreboardItem((teams + teamsort[i]), x, y);
1695 for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1696 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1701 Sbar_MiniDeathmatchOverlay
1705 void Sbar_MiniDeathmatchOverlay (int x, int y)
1707 int i, j, numlines, range_begin, range_end, myteam, teamsep;
1712 // decide where to print
1713 if (gamemode == GAME_TRANSFUSION)
1714 numlines = (vid_conwidth.integer - x + 127) / 128;
1716 numlines = (vid_conheight.integer - y + 7) / 8;
1718 // give up if there isn't room
1719 if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1723 for (i = 0; i < scoreboardlines; i++)
1724 if (fragsort[i] == cl.playerentity - 1)
1728 range_end = scoreboardlines;
1731 if (gamemode != GAME_TRANSFUSION)
1732 if (Sbar_IsTeammatch ())
1734 // reserve space for the team scores
1735 numlines -= teamlines;
1737 // find first and last player of my team (only draw the team totals and my own team)
1738 range_begin = range_end = i;
1739 myteam = cl.scores[fragsort[i]].colors & 15;
1740 while(range_begin > 0 && (cl.scores[fragsort[range_begin-1]].colors & 15) == myteam)
1742 while(range_end < scoreboardlines && (cl.scores[fragsort[range_end]].colors & 15) == myteam)
1745 // looks better than two players
1755 i = min(i, range_end - numlines);
1756 i = max(i, range_begin);
1758 if (gamemode == GAME_TRANSFUSION)
1760 for (;i < range_end && x < vid_conwidth.integer;i++)
1761 x += 128 + (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1765 if(range_end - i < numlines) // won't draw to bottom?
1766 y += 8 * (numlines - (range_end - i)); // bottom align
1767 // show team scores first
1768 for (j = 0;j < teamlines && y < vid_conheight.integer;j++)
1769 y += (int)Sbar_PrintScoreboardItem((teams + teamsort[j]), x, y);
1771 for (;i < range_end && y < vid_conheight.integer;i++)
1772 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1776 void Sbar_Score (void)
1778 int i, me, score, otherleader, place, distribution, minutes, seconds;
1781 sbar_y = vid_conheight.value - (32+12);
1782 me = cl.playerentity - 1;
1783 if (me >= 0 && me < cl.maxclients)
1785 // find leading score other than ourselves, to calculate distribution
1786 // find our place in the scoreboard
1787 score = cl.scores[me].frags;
1788 for (i = 0, otherleader = -1, place = 1;i < cl.maxclients;i++)
1790 if (cl.scores[i].name[0] && i != me)
1792 if (otherleader == -1 || cl.scores[i].frags > cl.scores[otherleader].frags)
1794 if (score < cl.scores[i].frags || (score == cl.scores[i].frags && i < me))
1798 distribution = otherleader >= 0 ? score - cl.scores[otherleader].frags : 0;
1800 Sbar_DrawXNum(-3*12-24, -12, place, 3, 12, 0, 1, 1, 1, 0);
1801 else if (place == 2)
1802 Sbar_DrawXNum(-3*12-24, -12, place, 3, 12, 1, 1, 1, 1, 0);
1803 else if (place == 3)
1804 Sbar_DrawXNum(-3*12-24, -12, place, 3, 12, 1, 1, 0, 1, 0);
1806 Sbar_DrawXNum(-3*12-24, -12, place, 3, 12, 1, 0, 0, 1, 0);
1807 if (otherleader < 0)
1808 Sbar_DrawXNum(-32*4-24, 0, score, 4, 32, 1, 1, 1, 1, 0);
1809 else if (distribution >= 5)
1811 Sbar_DrawXNum(-7*12-24, -12, distribution, 4, 12, 0, 1, 1, 1, 0);
1812 Sbar_DrawXNum(-32*4-24, 0, score, 4, 32, 0, 1, 1, 1, 0);
1814 else if (distribution >= 0)
1816 Sbar_DrawXNum(-7*12-24, -12, distribution, 4, 12, 1, 1, 1, 1, 0);
1817 Sbar_DrawXNum(-32*4-24, 0, score, 4, 32, 1, 1, 1, 1, 0);
1819 else if (distribution >= -5)
1821 Sbar_DrawXNum(-7*12-24, -12, distribution, 4, 12, 1, 1, 0, 1, 0);
1822 Sbar_DrawXNum(-32*4-24, 0, score, 4, 32, 1, 1, 0, 1, 0);
1826 Sbar_DrawXNum(-7*12-24, -12, distribution, 4, 12, 1, 0, 0, 1, 0);
1827 Sbar_DrawXNum(-32*4-24, 0, score, 4, 32, 1, 0, 0, 1, 0);
1831 if (cl.statsf[STAT_TIMELIMIT])
1833 timeleft = max(0, cl.statsf[STAT_TIMELIMIT] * 60 - cl.time);
1834 minutes = (int)floor(timeleft / 60);
1835 seconds = (int)(floor(timeleft) - minutes * 60);
1838 Sbar_DrawXNum(-12*6-24, 32, minutes, 3, 12, 1, 1, 1, 1, 0);
1839 Sbar_DrawXNum(-12*2-24, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
1841 else if (minutes >= 1)
1843 Sbar_DrawXNum(-12*6-24, 32, minutes, 3, 12, 1, 1, 0, 1, 0);
1844 Sbar_DrawXNum(-12*2-24, 32, seconds, -2, 12, 1, 1, 0, 1, 0);
1846 else if ((int)(timeleft * 4) & 1)
1847 Sbar_DrawXNum(-12*2-24, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
1849 Sbar_DrawXNum(-12*2-24, 32, seconds, -2, 12, 1, 0, 0, 1, 0);
1853 minutes = (int)floor(cl.time / 60);
1854 seconds = (int)(floor(cl.time) - minutes * 60);
1855 Sbar_DrawXNum(-12*6-24, 32, minutes, 3, 12, 0, 1, 1, 1, 0);
1856 Sbar_DrawXNum(-12*2-24, 32, seconds, -2, 12, 0, 1, 1, 1, 0);
1862 Sbar_IntermissionOverlay
1866 void Sbar_IntermissionOverlay (void)
1871 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1872 //if (cl.gametype == GAME_DEATHMATCH)
1873 if (!cl.islocalgame)
1875 Sbar_DeathmatchOverlay ();
1879 sbar_x = (vid_conwidth.integer - 320) >> 1;
1880 sbar_y = (vid_conheight.integer - 200) >> 1;
1882 DrawQ_Pic (sbar_x + 64, sbar_y + 24, sb_complete, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1883 DrawQ_Pic (sbar_x + 0, sbar_y + 56, sb_inter, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1886 dig = (int)cl.completed_time / 60;
1887 Sbar_DrawNum (160, 64, dig, 3, 0);
1888 num = (int)cl.completed_time - dig*60;
1889 if (gamemode != GAME_NEXUIZ)
1890 Sbar_DrawPic (234,64,sb_colon);
1891 Sbar_DrawPic (246,64,sb_nums[0][num/10]);
1892 Sbar_DrawPic (266,64,sb_nums[0][num%10]);
1894 Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
1895 if (gamemode != GAME_NEXUIZ)
1896 Sbar_DrawPic (232, 104, sb_slash);
1897 Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1899 Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1900 if (gamemode != GAME_NEXUIZ)
1901 Sbar_DrawPic (232, 144, sb_slash);
1902 Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1913 void Sbar_FinaleOverlay (void)
1915 DrawQ_Pic((vid_conwidth.integer - sb_finale->width)/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);