2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 // sbar.c -- status bar code
26 #define STAT_MINUS 10 // num frame for '-' stats digit
27 cachepic_t *sb_nums[2][11];
28 cachepic_t *sb_colon, *sb_slash;
31 cachepic_t *sb_scorebar;
32 // AK only used by NEX
33 cachepic_t *sb_sbar_minimal;
34 cachepic_t *sb_sbar_overlay;
36 // AK changed the bound to 9
37 cachepic_t *sb_weapons[7][9]; // 0 is active, 1 is owned, 2-5 are flashes
38 cachepic_t *sb_ammo[4];
39 cachepic_t *sb_sigil[4];
40 cachepic_t *sb_armor[3];
41 cachepic_t *sb_items[32];
43 // 0-4 are based on health (in 20 increments)
44 // 0 is static, 1 is temporary animation
45 cachepic_t *sb_faces[5][2];
47 cachepic_t *sb_face_invis;
48 cachepic_t *sb_face_quad;
49 cachepic_t *sb_face_invuln;
50 cachepic_t *sb_face_invis_invuln;
52 qboolean sb_showscores;
54 int sb_lines; // scan lines to draw
56 cachepic_t *rsb_invbar[2];
57 cachepic_t *rsb_weapons[5];
58 cachepic_t *rsb_items[2];
59 cachepic_t *rsb_ammo[3];
60 cachepic_t *rsb_teambord; // PGM 01/19/97 - team color border
62 //MED 01/04/97 added two more weapons + 3 alternates for grenade launcher
63 cachepic_t *hsb_weapons[7][5]; // 0 is active, 1 is owned, 2-5 are flashes
64 //MED 01/04/97 added array to simplify weapon parsing
65 int hipweapons[4] = {HIT_LASER_CANNON_BIT,HIT_MJOLNIR_BIT,4,HIT_PROXIMITY_GUN_BIT};
66 //MED 01/04/97 added hipnotic items array
67 cachepic_t *hsb_items[2];
70 cachepic_t *somsb_health;
71 cachepic_t *somsb_ammo[4];
72 cachepic_t *somsb_armor[3];
74 cachepic_t *zymsb_crosshair_center;
75 cachepic_t *zymsb_crosshair_line;
76 cachepic_t *zymsb_crosshair_health;
77 cachepic_t *zymsb_crosshair_ammo;
78 cachepic_t *zymsb_crosshair_clip;
79 cachepic_t *zymsb_crosshair_background;
80 cachepic_t *zymsb_crosshair_left1;
81 cachepic_t *zymsb_crosshair_left2;
82 cachepic_t *zymsb_crosshair_right;
84 cachepic_t *sb_ranking;
85 cachepic_t *sb_complete;
87 cachepic_t *sb_finale;
89 cvar_t showfps = {CVAR_SAVE, "showfps", "0", "shows your rendered fps (frames per second)"};
90 cvar_t showtime = {CVAR_SAVE, "showtime", "0", "shows current time of day (useful on screenshots)"};
91 cvar_t showtime_format = {CVAR_SAVE, "showtime_format", "%H:%M:%S", "format string for time of day"};
92 cvar_t showdate = {CVAR_SAVE, "showdate", "0", "shows current date (useful on screenshots)"};
93 cvar_t showdate_format = {CVAR_SAVE, "showdate_format", "%Y-%m-%d", "format string for date"};
94 cvar_t sbar_alpha_bg = {CVAR_SAVE, "sbar_alpha_bg", "0.4", "opacity value of the statusbar background image"};
95 cvar_t sbar_alpha_fg = {CVAR_SAVE, "sbar_alpha_fg", "1", "opacity value of the statusbar weapon/item icons and numbers"};
97 cvar_t cl_deathscoreboard = {0, "cl_deathscoreboard", "1", "shows scoreboard (+showscores) while dead"};
99 cvar_t crosshair_color_red = {CVAR_SAVE, "crosshair_color_red", "1", "customizable crosshair color"};
100 cvar_t crosshair_color_green = {CVAR_SAVE, "crosshair_color_green", "0", "customizable crosshair color"};
101 cvar_t crosshair_color_blue = {CVAR_SAVE, "crosshair_color_blue", "0", "customizable crosshair color"};
102 cvar_t crosshair_color_alpha = {CVAR_SAVE, "crosshair_color_alpha", "1", "how opaque the crosshair should be"};
103 cvar_t crosshair_size = {CVAR_SAVE, "crosshair_size", "1", "adjusts size of the crosshair on the screen"};
105 void Sbar_MiniDeathmatchOverlay (int x, int y);
106 void Sbar_DeathmatchOverlay (void);
107 void Sbar_IntermissionOverlay (void);
108 void Sbar_FinaleOverlay (void);
118 void Sbar_ShowScores (void)
122 sb_showscores = true;
132 void Sbar_DontShowScores (void)
134 sb_showscores = false;
137 void sbar_start(void)
141 if (gamemode == GAME_NETHERWORLD)
144 else if (gamemode == GAME_SOM)
146 sb_disc = Draw_CachePic("gfx/disc", true);
148 for (i = 0;i < 10;i++)
149 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
151 somsb_health = Draw_CachePic("gfx/hud_health", true);
152 somsb_ammo[0] = Draw_CachePic("gfx/sb_shells", true);
153 somsb_ammo[1] = Draw_CachePic("gfx/sb_nails", true);
154 somsb_ammo[2] = Draw_CachePic("gfx/sb_rocket", true);
155 somsb_ammo[3] = Draw_CachePic("gfx/sb_cells", true);
156 somsb_armor[0] = Draw_CachePic("gfx/sb_armor1", true);
157 somsb_armor[1] = Draw_CachePic("gfx/sb_armor2", true);
158 somsb_armor[2] = Draw_CachePic("gfx/sb_armor3", true);
160 else if (gamemode == GAME_NEXUIZ)
162 for (i = 0;i < 10;i++)
163 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
164 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus", true);
166 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells", true);
167 sb_ammo[1] = Draw_CachePic ("gfx/sb_bullets", true);
168 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket", true);
169 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells", true);
171 sb_items[2] = Draw_CachePic ("gfx/sb_slowmo", true);
172 sb_items[3] = Draw_CachePic ("gfx/sb_invinc", true);
173 sb_items[4] = Draw_CachePic ("gfx/sb_energy", true);
174 sb_items[5] = Draw_CachePic ("gfx/sb_str", true);
176 sb_sbar = Draw_CachePic("gfx/sbar", true);
177 sb_sbar_minimal = Draw_CachePic("gfx/sbar_minimal", true);
178 sb_sbar_overlay = Draw_CachePic("gfx/sbar_overlay", true);
180 for(i = 0; i < 9;i++)
181 sb_weapons[0][i] = Draw_CachePic(va("gfx/inv_weapon%i",i), true);
183 else if (gamemode == GAME_ZYMOTIC)
185 zymsb_crosshair_center = Draw_CachePic ("gfx/hud/crosshair_center", true);
186 zymsb_crosshair_line = Draw_CachePic ("gfx/hud/crosshair_line", true);
187 zymsb_crosshair_health = Draw_CachePic ("gfx/hud/crosshair_health", true);
188 zymsb_crosshair_clip = Draw_CachePic ("gfx/hud/crosshair_clip", true);
189 zymsb_crosshair_ammo = Draw_CachePic ("gfx/hud/crosshair_ammo", true);
190 zymsb_crosshair_background = Draw_CachePic ("gfx/hud/crosshair_background", true);
191 zymsb_crosshair_left1 = Draw_CachePic ("gfx/hud/crosshair_left1", true);
192 zymsb_crosshair_left2 = Draw_CachePic ("gfx/hud/crosshair_left2", true);
193 zymsb_crosshair_right = Draw_CachePic ("gfx/hud/crosshair_right", true);
197 sb_disc = Draw_CachePic("gfx/disc", true);
199 for (i = 0;i < 10;i++)
201 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
202 sb_nums[1][i] = Draw_CachePic (va("gfx/anum_%i",i), true);
205 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus", true);
206 sb_nums[1][10] = Draw_CachePic ("gfx/anum_minus", true);
208 sb_colon = Draw_CachePic ("gfx/num_colon", true);
209 sb_slash = Draw_CachePic ("gfx/num_slash", true);
211 sb_weapons[0][0] = Draw_CachePic ("gfx/inv_shotgun", true);
212 sb_weapons[0][1] = Draw_CachePic ("gfx/inv_sshotgun", true);
213 sb_weapons[0][2] = Draw_CachePic ("gfx/inv_nailgun", true);
214 sb_weapons[0][3] = Draw_CachePic ("gfx/inv_snailgun", true);
215 sb_weapons[0][4] = Draw_CachePic ("gfx/inv_rlaunch", true);
216 sb_weapons[0][5] = Draw_CachePic ("gfx/inv_srlaunch", true);
217 sb_weapons[0][6] = Draw_CachePic ("gfx/inv_lightng", true);
219 sb_weapons[1][0] = Draw_CachePic ("gfx/inv2_shotgun", true);
220 sb_weapons[1][1] = Draw_CachePic ("gfx/inv2_sshotgun", true);
221 sb_weapons[1][2] = Draw_CachePic ("gfx/inv2_nailgun", true);
222 sb_weapons[1][3] = Draw_CachePic ("gfx/inv2_snailgun", true);
223 sb_weapons[1][4] = Draw_CachePic ("gfx/inv2_rlaunch", true);
224 sb_weapons[1][5] = Draw_CachePic ("gfx/inv2_srlaunch", true);
225 sb_weapons[1][6] = Draw_CachePic ("gfx/inv2_lightng", true);
227 for (i = 0;i < 5;i++)
229 sb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_shotgun",i+1), true);
230 sb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_sshotgun",i+1), true);
231 sb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_nailgun",i+1), true);
232 sb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_snailgun",i+1), true);
233 sb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_rlaunch",i+1), true);
234 sb_weapons[2+i][5] = Draw_CachePic (va("gfx/inva%i_srlaunch",i+1), true);
235 sb_weapons[2+i][6] = Draw_CachePic (va("gfx/inva%i_lightng",i+1), true);
238 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells", true);
239 sb_ammo[1] = Draw_CachePic ("gfx/sb_nails", true);
240 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket", true);
241 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells", true);
243 sb_armor[0] = Draw_CachePic ("gfx/sb_armor1", true);
244 sb_armor[1] = Draw_CachePic ("gfx/sb_armor2", true);
245 sb_armor[2] = Draw_CachePic ("gfx/sb_armor3", true);
247 sb_items[0] = Draw_CachePic ("gfx/sb_key1", true);
248 sb_items[1] = Draw_CachePic ("gfx/sb_key2", true);
249 sb_items[2] = Draw_CachePic ("gfx/sb_invis", true);
250 sb_items[3] = Draw_CachePic ("gfx/sb_invuln", true);
251 sb_items[4] = Draw_CachePic ("gfx/sb_suit", true);
252 sb_items[5] = Draw_CachePic ("gfx/sb_quad", true);
254 sb_sigil[0] = Draw_CachePic ("gfx/sb_sigil1", true);
255 sb_sigil[1] = Draw_CachePic ("gfx/sb_sigil2", true);
256 sb_sigil[2] = Draw_CachePic ("gfx/sb_sigil3", true);
257 sb_sigil[3] = Draw_CachePic ("gfx/sb_sigil4", true);
259 sb_faces[4][0] = Draw_CachePic ("gfx/face1", true);
260 sb_faces[4][1] = Draw_CachePic ("gfx/face_p1", true);
261 sb_faces[3][0] = Draw_CachePic ("gfx/face2", true);
262 sb_faces[3][1] = Draw_CachePic ("gfx/face_p2", true);
263 sb_faces[2][0] = Draw_CachePic ("gfx/face3", true);
264 sb_faces[2][1] = Draw_CachePic ("gfx/face_p3", true);
265 sb_faces[1][0] = Draw_CachePic ("gfx/face4", true);
266 sb_faces[1][1] = Draw_CachePic ("gfx/face_p4", true);
267 sb_faces[0][0] = Draw_CachePic ("gfx/face5", true);
268 sb_faces[0][1] = Draw_CachePic ("gfx/face_p5", true);
270 sb_face_invis = Draw_CachePic ("gfx/face_invis", true);
271 sb_face_invuln = Draw_CachePic ("gfx/face_invul2", true);
272 sb_face_invis_invuln = Draw_CachePic ("gfx/face_inv2", true);
273 sb_face_quad = Draw_CachePic ("gfx/face_quad", true);
275 sb_sbar = Draw_CachePic ("gfx/sbar", true);
276 sb_ibar = Draw_CachePic ("gfx/ibar", true);
277 sb_scorebar = Draw_CachePic ("gfx/scorebar", true);
279 //MED 01/04/97 added new hipnotic weapons
280 if (gamemode == GAME_HIPNOTIC)
282 hsb_weapons[0][0] = Draw_CachePic ("gfx/inv_laser", true);
283 hsb_weapons[0][1] = Draw_CachePic ("gfx/inv_mjolnir", true);
284 hsb_weapons[0][2] = Draw_CachePic ("gfx/inv_gren_prox", true);
285 hsb_weapons[0][3] = Draw_CachePic ("gfx/inv_prox_gren", true);
286 hsb_weapons[0][4] = Draw_CachePic ("gfx/inv_prox", true);
288 hsb_weapons[1][0] = Draw_CachePic ("gfx/inv2_laser", true);
289 hsb_weapons[1][1] = Draw_CachePic ("gfx/inv2_mjolnir", true);
290 hsb_weapons[1][2] = Draw_CachePic ("gfx/inv2_gren_prox", true);
291 hsb_weapons[1][3] = Draw_CachePic ("gfx/inv2_prox_gren", true);
292 hsb_weapons[1][4] = Draw_CachePic ("gfx/inv2_prox", true);
294 for (i = 0;i < 5;i++)
296 hsb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_laser",i+1), true);
297 hsb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_mjolnir",i+1), true);
298 hsb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_gren_prox",i+1), true);
299 hsb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_prox_gren",i+1), true);
300 hsb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_prox",i+1), true);
303 hsb_items[0] = Draw_CachePic ("gfx/sb_wsuit", true);
304 hsb_items[1] = Draw_CachePic ("gfx/sb_eshld", true);
306 else if (gamemode == GAME_ROGUE)
308 rsb_invbar[0] = Draw_CachePic ("gfx/r_invbar1", true);
309 rsb_invbar[1] = Draw_CachePic ("gfx/r_invbar2", true);
311 rsb_weapons[0] = Draw_CachePic ("gfx/r_lava", true);
312 rsb_weapons[1] = Draw_CachePic ("gfx/r_superlava", true);
313 rsb_weapons[2] = Draw_CachePic ("gfx/r_gren", true);
314 rsb_weapons[3] = Draw_CachePic ("gfx/r_multirock", true);
315 rsb_weapons[4] = Draw_CachePic ("gfx/r_plasma", true);
317 rsb_items[0] = Draw_CachePic ("gfx/r_shield1", true);
318 rsb_items[1] = Draw_CachePic ("gfx/r_agrav1", true);
320 // PGM 01/19/97 - team color border
321 rsb_teambord = Draw_CachePic ("gfx/r_teambord", true);
322 // PGM 01/19/97 - team color border
324 rsb_ammo[0] = Draw_CachePic ("gfx/r_ammolava", true);
325 rsb_ammo[1] = Draw_CachePic ("gfx/r_ammomulti", true);
326 rsb_ammo[2] = Draw_CachePic ("gfx/r_ammoplasma", true);
330 sb_ranking = Draw_CachePic ("gfx/ranking", true);
331 sb_complete = Draw_CachePic ("gfx/complete", true);
332 sb_inter = Draw_CachePic ("gfx/inter", true);
333 sb_finale = Draw_CachePic ("gfx/finale", true);
336 void sbar_shutdown(void)
340 void sbar_newmap(void)
344 void Sbar_Init (void)
346 Cmd_AddCommand("+showscores", Sbar_ShowScores, "show scoreboard");
347 Cmd_AddCommand("-showscores", Sbar_DontShowScores, "hide scoreboard");
348 Cvar_RegisterVariable(&showfps);
349 Cvar_RegisterVariable(&showtime);
350 Cvar_RegisterVariable(&showtime_format);
351 Cvar_RegisterVariable(&showdate);
352 Cvar_RegisterVariable(&showdate_format);
353 Cvar_RegisterVariable(&sbar_alpha_bg);
354 Cvar_RegisterVariable(&sbar_alpha_fg);
355 Cvar_RegisterVariable(&cl_deathscoreboard);
357 Cvar_RegisterVariable(&crosshair_color_red);
358 Cvar_RegisterVariable(&crosshair_color_green);
359 Cvar_RegisterVariable(&crosshair_color_blue);
360 Cvar_RegisterVariable(&crosshair_color_alpha);
361 Cvar_RegisterVariable(&crosshair_size);
363 R_RegisterModule("sbar", sbar_start, sbar_shutdown, sbar_newmap);
367 //=============================================================================
369 // drawing routines are relative to the status bar location
378 void Sbar_DrawPic (int x, int y, cachepic_t *pic)
380 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, sbar_alpha_fg.value, 0);
383 void Sbar_DrawAlphaPic (int x, int y, cachepic_t *pic, float alpha)
385 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, alpha, 0);
392 Draws one solid graphics character
395 void Sbar_DrawCharacter (int x, int y, int num)
397 DrawQ_String (sbar_x + x + 4 , sbar_y + y, va("%c", num), 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0);
405 void Sbar_DrawString (int x, int y, char *str)
407 DrawQ_String (sbar_x + x, sbar_y + y, str, 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0);
415 void Sbar_DrawNum (int x, int y, int num, int digits, int color)
420 l = sprintf(str, "%i", num);
434 Sbar_DrawPic (x, y, sb_nums[color][frame]);
447 void Sbar_DrawXNum (int x, int y, int num, int digits, int lettersize, float r, float g, float b, float a, int flags)
452 l = sprintf(str, "%i", num);
457 x += (digits-l) * lettersize;
466 DrawQ_Pic (sbar_x + x, sbar_y + y, sb_nums[0][frame],lettersize,lettersize,r,g,b,a * sbar_alpha_fg.value,flags);
473 //=============================================================================
476 int Sbar_IsTeammatch()
478 // currently only nexuiz uses the team score board
479 return ((gamemode == GAME_NEXUIZ)
480 && (teamplay.integer > 0));
488 static int fragsort[MAX_SCOREBOARD];
489 static int scoreboardlines;
491 //[515]: Sbar_GetPlayer for csqc "getplayerkey" func
492 int Sbar_GetPlayer (int index)
497 if(index >= scoreboardlines)
499 index = fragsort[index];
501 if(index >= scoreboardlines)
506 static scoreboard_t teams[MAX_SCOREBOARD];
507 static int teamsort[MAX_SCOREBOARD];
508 static int teamlines;
509 void Sbar_SortFrags (void)
515 for (i=0 ; i<cl.maxclients ; i++)
517 if (cl.scores[i].name[0])
519 fragsort[scoreboardlines] = i;
524 for (i=0 ; i<scoreboardlines ; i++)
525 for (j=0 ; j<scoreboardlines-1-i ; j++)
526 if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j+1]].frags)
529 fragsort[j] = fragsort[j+1];
534 if (Sbar_IsTeammatch ())
536 // now sort players by teams.
537 for (i=0 ; i<scoreboardlines ; i++)
539 for (j=0 ; j<scoreboardlines-1-i ; j++)
541 if (cl.scores[fragsort[j]].colors < cl.scores[fragsort[j+1]].colors)
544 fragsort[j] = fragsort[j+1];
550 // calculate team scores
552 for (i=0 ; i<scoreboardlines ; i++)
554 if (color != (cl.scores[fragsort[i]].colors & 15))
556 color = cl.scores[fragsort[i]].colors & 15;
560 strcpy(teams[teamlines-1].name, "^1Red Team");
561 else if (color == 13)
562 strcpy(teams[teamlines-1].name, "^4Blue Team");
564 strcpy(teams[teamlines-1].name, "^6Pink Team");
565 else if (color == 12)
566 strcpy(teams[teamlines-1].name, "^3Yellow Team");
568 strcpy(teams[teamlines-1].name, "Total Team Score");
570 teams[teamlines-1].frags = 0;
571 teams[teamlines-1].colors = color + 16 * color;
574 if (cl.scores[fragsort[i]].frags != -666)
576 // do not add spedcators
577 // (ugly hack for nexuiz)
578 teams[teamlines-1].frags += cl.scores[fragsort[i]].frags;
582 // now sort teams by scores.
583 for (i=0 ; i<teamlines ; i++)
585 for (i=0 ; i<teamlines ; i++)
587 for (j=0 ; j<teamlines-1-i ; j++)
589 if (teams[teamsort[j]].frags < teams[teamsort[j+1]].frags)
592 teamsort[j] = teamsort[j+1];
605 void Sbar_SoloScoreboard (void)
608 int minutes, seconds, tens, units;
611 if (gamemode != GAME_NEXUIZ) {
612 sprintf (str,"Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
613 Sbar_DrawString (8, 4, str);
615 sprintf (str,"Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
616 Sbar_DrawString (8, 12, str);
620 minutes = (int)(cl.time / 60);
621 seconds = (int)(cl.time - 60*minutes);
623 units = seconds - 10*tens;
624 sprintf (str,"Time :%3i:%i%i", minutes, tens, units);
625 Sbar_DrawString (184, 4, str);
628 if (gamemode == GAME_NEXUIZ) {
629 l = (int) strlen (cl.worldmodel->name);
630 Sbar_DrawString (232 - l*4, 12, cl.worldmodel->name);
632 l = (int) strlen (cl.levelname);
633 Sbar_DrawString (232 - l*4, 12, cl.levelname);
642 void Sbar_DrawScoreboard (void)
644 Sbar_SoloScoreboard ();
645 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
646 //if (cl.gametype == GAME_DEATHMATCH)
648 Sbar_DeathmatchOverlay ();
651 //=============================================================================
653 // AK to make DrawInventory smaller
654 static void Sbar_DrawWeapon(int nr, float fade, int active)
656 // width = 300, height = 100
657 const int w_width = 300, w_height = 100, w_space = 10;
658 const float w_scale = 0.4;
660 DrawQ_Pic(vid_conwidth.integer - (w_width + w_space) * w_scale, (w_height + w_space) * w_scale * nr + w_space, sb_weapons[0][nr], w_width * w_scale, w_height * w_scale, (active) ? 1 : 0.6, active ? 1 : 0.6, active ? 1 : 1, fade * sbar_alpha_fg.value, DRAWFLAG_ADDITIVE);
661 //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);
664 DrawQ_Pic(vid_conwidth.integer - (w_width + w_space) * w_scale, (w_height + w_space) * w_scale * nr + w_space, NULL, w_width * w_scale, w_height * w_scale, 0.3, 0.3, 0.3, fade * sbar_alpha_fg.value, DRAWFLAG_ADDITIVE);
672 void Sbar_DrawInventory (void)
679 if (gamemode == GAME_ROGUE)
681 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
682 Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], sbar_alpha_bg.value);
684 Sbar_DrawAlphaPic (0, -24, rsb_invbar[1], sbar_alpha_bg.value);
687 Sbar_DrawAlphaPic (0, -24, sb_ibar, sbar_alpha_bg.value);
690 for (i=0 ; i<7 ; i++)
692 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<i) )
694 time = cl.item_gettime[i];
695 flashon = (int)((cl.time - time)*10);
698 if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i) )
704 flashon = (flashon%5) + 2;
706 Sbar_DrawAlphaPic (i*24, -16, sb_weapons[flashon][i], sbar_alpha_bg.value);
712 if (gamemode == GAME_HIPNOTIC)
714 int grenadeflashing=0;
715 for (i=0 ; i<4 ; i++)
717 if (cl.stats[STAT_ITEMS] & (1<<hipweapons[i]) )
719 time = cl.item_gettime[hipweapons[i]];
720 flashon = (int)((cl.time - time)*10);
723 if ( cl.stats[STAT_ACTIVEWEAPON] == (1<<hipweapons[i]) )
729 flashon = (flashon%5) + 2;
731 // check grenade launcher
734 if (cl.stats[STAT_ITEMS] & HIT_PROXIMITY_GUN)
739 Sbar_DrawPic (96, -16, hsb_weapons[flashon][2]);
745 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<4))
747 if (!grenadeflashing)
748 Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
751 Sbar_DrawPic (96, -16, hsb_weapons[flashon][4]);
754 Sbar_DrawPic (176 + (i*24), -16, hsb_weapons[flashon][i]);
759 if (gamemode == GAME_ROGUE)
761 // check for powered up weapon.
762 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
764 if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i))
765 Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]);
769 for (i=0 ; i<4 ; i++)
771 sprintf (num, "%3i",cl.stats[STAT_SHELLS+i] );
773 Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[0] - '0');
775 Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[1] - '0');
777 Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0');
781 for (i=0 ; i<6 ; i++)
782 if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
784 //MED 01/04/97 changed keys
785 if (gamemode != GAME_HIPNOTIC || (i>1))
786 Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
789 //MED 01/04/97 added hipnotic items
791 if (gamemode == GAME_HIPNOTIC)
793 for (i=0 ; i<2 ; i++)
794 if (cl.stats[STAT_ITEMS] & (1<<(24+i)))
795 Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
798 if (gamemode == GAME_ROGUE)
801 for (i=0 ; i<2 ; i++)
802 if (cl.stats[STAT_ITEMS] & (1<<(29+i)))
803 Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
808 for (i=0 ; i<4 ; i++)
809 if (cl.stats[STAT_ITEMS] & (1<<(28+i)))
810 Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
814 //=============================================================================
821 void Sbar_DrawFrags (void)
831 l = min(scoreboardlines, 4);
835 for (i = 0;i < l;i++)
841 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
842 DrawQ_Pic (sbar_x + x + 10, sbar_y - 23, NULL, 28, 4, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
843 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
844 DrawQ_Pic (sbar_x + x + 10, sbar_y + 4 - 23, NULL, 28, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
848 sprintf (num, "%3i",f);
850 if (k == cl.viewentity - 1)
852 Sbar_DrawCharacter ( x + 2, -24, 16);
853 Sbar_DrawCharacter ( x + 32 - 4, -24, 17);
855 Sbar_DrawCharacter (x + 8, -24, num[0]);
856 Sbar_DrawCharacter (x + 16, -24, num[1]);
857 Sbar_DrawCharacter (x + 24, -24, num[2]);
862 //=============================================================================
870 void Sbar_DrawFace (void)
874 // PGM 01/19/97 - team color drawing
875 // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
876 if (gamemode == GAME_ROGUE && !cl.islocalgame && (teamplay.integer > 3) && (teamplay.integer < 7))
882 s = &cl.scores[cl.viewentity - 1];
884 Sbar_DrawPic (112, 0, rsb_teambord);
885 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
886 DrawQ_Pic (sbar_x + 113, vid_conheight.integer-SBAR_HEIGHT+3, NULL, 22, 9, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
887 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
888 DrawQ_Pic (sbar_x + 113, vid_conheight.integer-SBAR_HEIGHT+12, NULL, 22, 9, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
892 sprintf (num, "%3i",f);
894 if ((s->colors & 0xf0)==0)
897 Sbar_DrawCharacter(109, 3, 18 + num[0] - '0');
899 Sbar_DrawCharacter(116, 3, 18 + num[1] - '0');
901 Sbar_DrawCharacter(123, 3, 18 + num[2] - '0');
905 Sbar_DrawCharacter ( 109, 3, num[0]);
906 Sbar_DrawCharacter ( 116, 3, num[1]);
907 Sbar_DrawCharacter ( 123, 3, num[2]);
912 // PGM 01/19/97 - team color drawing
914 if ( (cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
915 Sbar_DrawPic (112, 0, sb_face_invis_invuln);
916 else if (cl.stats[STAT_ITEMS] & IT_QUAD)
917 Sbar_DrawPic (112, 0, sb_face_quad );
918 else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
919 Sbar_DrawPic (112, 0, sb_face_invis );
920 else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
921 Sbar_DrawPic (112, 0, sb_face_invuln);
924 f = cl.stats[STAT_HEALTH] / 20;
926 Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]);
930 void Sbar_ShowFPS(void)
932 float fps_x, fps_y, fps_scalex, fps_scaley, fps_height;
936 qboolean red = false;
943 static double nexttime = 0, lasttime = 0;
944 static double framerate = 0;
945 static int framecount = 0;
947 newtime = Sys_DoubleTime();
948 if (newtime >= nexttime)
950 framerate = framecount / (newtime - lasttime);
952 nexttime = max(nexttime + 1, lasttime - 1);
958 if ((red = (calc < 1.0f)))
959 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0f / calc + 0.5));
961 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(calc + 0.5));
963 if (showtime.integer)
964 strlcpy(timestring, Sys_TimeString(showtime_format.string), sizeof(timestring));
965 if (showdate.integer)
966 strlcpy(datestring, Sys_TimeString(showdate_format.string), sizeof(datestring));
967 if (fpsstring[0] || timestring[0])
971 fps_height = fps_scaley * ((fpsstring[0] != 0) + (timestring[0] != 0) + (datestring[0] != 0));
972 //fps_y = vid_conheight.integer - sb_lines; // yes this may draw over the sbar
973 //fps_y = bound(0, fps_y, vid_conheight.integer - fps_height);
974 fps_y = vid_conheight.integer - fps_height;
977 fps_x = vid_conwidth.integer - fps_scalex * strlen(fpsstring);
978 DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(fpsstring), fps_scaley, 0, 0, 0, 0.5, 0);
980 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 0, 0, 1, 0);
982 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
987 fps_x = vid_conwidth.integer - fps_scalex * strlen(timestring);
988 DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(timestring), fps_scaley, 0, 0, 0, 0.5, 0);
989 DrawQ_String(fps_x, fps_y, timestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
994 fps_x = vid_conwidth.integer - fps_scalex * strlen(datestring);
995 DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(datestring), fps_scaley, 0, 0, 0, 0.5, 0);
996 DrawQ_String(fps_x, fps_y, datestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
1002 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)
1005 c2 = bound(0, c2, 1);
1006 c1 = bound(0, c1, 1 - c2);
1008 r[1] = rangey + rangeheight * (c2 + c1);
1009 r[2] = rangey + rangeheight * (c2);
1013 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);
1015 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);
1017 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);
1019 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);
1027 extern float v_dmg_time, v_dmg_roll, v_dmg_pitch;
1028 extern cvar_t v_kicktime;
1029 void Sbar_Draw (void)
1033 if(cl.csqc_vidvars.drawenginesbar) //[515]: csqc drawsbar
1035 if (cl.intermission == 1)
1037 Sbar_IntermissionOverlay();
1040 else if (cl.intermission == 2)
1042 Sbar_FinaleOverlay();
1046 if (gamemode == GAME_NETHERWORLD)
1049 else if (gamemode == GAME_SOM)
1051 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1052 Sbar_DrawScoreboard ();
1055 // this is the top left of the sbar area
1057 sbar_y = vid_conheight.integer - 24*3;
1060 if (cl.stats[STAT_ARMOR])
1062 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1063 Sbar_DrawPic(0, 0, somsb_armor[2]);
1064 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1065 Sbar_DrawPic(0, 0, somsb_armor[1]);
1066 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1067 Sbar_DrawPic(0, 0, somsb_armor[0]);
1068 Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1072 Sbar_DrawPic(0, 24, somsb_health);
1073 Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1076 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1077 Sbar_DrawPic(0, 48, somsb_ammo[0]);
1078 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1079 Sbar_DrawPic(0, 48, somsb_ammo[1]);
1080 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1081 Sbar_DrawPic(0, 48, somsb_ammo[2]);
1082 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1083 Sbar_DrawPic(0, 48, somsb_ammo[3]);
1084 Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
1085 if (cl.stats[STAT_SHELLS])
1086 Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
1089 else if (gamemode == GAME_NEXUIZ)
1091 sbar_y = vid_conheight.integer - 47;
1092 sbar_x = (vid_conwidth.integer - 640)/2;
1094 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1096 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1097 Sbar_DrawScoreboard ();
1105 // we have a max time 2s (min time = 0)
1106 if ((time = cl.time - cl.weapontime) < 2)
1108 fade = (1.0 - 0.5 * time);
1110 for (i = 0; i < 8;i++)
1111 if (cl.stats[STAT_ITEMS] & (1 << i))
1112 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1114 if((cl.stats[STAT_ITEMS] & (1<<12)))
1115 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1118 //if (!cl.islocalgame)
1119 // Sbar_DrawFrags ();
1122 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1124 Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1127 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1129 // Nexuiz has no anum pics
1130 //Sbar_DrawNum (36, 0, 666, 3, 1);
1131 // Nexuiz has no disc pic
1132 //Sbar_DrawPic (0, 0, sb_disc);
1136 Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1139 if(cl.stats[STAT_HEALTH] > 100)
1140 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1141 else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1142 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1144 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1146 // AK dont draw ammo for the laser
1147 if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1149 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1150 Sbar_DrawPic (519, 0, sb_ammo[0]);
1151 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1152 Sbar_DrawPic (519, 0, sb_ammo[1]);
1153 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1154 Sbar_DrawPic (519, 0, sb_ammo[2]);
1155 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1156 Sbar_DrawPic (519, 0, sb_ammo[3]);
1158 if(cl.stats[STAT_AMMO] <= 10)
1159 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1161 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1166 DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1169 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1170 // Sbar_MiniDeathmatchOverlay (0, 17);
1172 else if (gamemode == GAME_ZYMOTIC)
1175 float scale = 64.0f / 256.0f;
1176 float kickoffset[3];
1177 VectorClear(kickoffset);
1180 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1181 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1183 sbar_x = (int)((vid_conwidth.integer - 256 * scale)/2 + kickoffset[0]);
1184 sbar_y = (int)((vid_conheight.integer - 256 * scale)/2 + kickoffset[1]);
1185 // left1 16, 48 : 126 -66
1186 // left2 16, 128 : 196 -66
1187 // right 176, 48 : 196 -136
1188 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);
1189 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);
1190 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);
1191 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1193 float scale = 128.0f / 256.0f;
1194 float healthstart, healthheight, healthstarttc, healthendtc;
1195 float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1196 float ammostart, ammoheight, ammostarttc, ammoendtc;
1197 float clipstart, clipheight, clipstarttc, clipendtc;
1198 float kickoffset[3], offset;
1199 VectorClear(kickoffset);
1202 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1203 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1205 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1206 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1207 offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1208 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);
1209 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);
1210 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);
1211 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);
1212 healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1213 shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1214 healthstart = 204 - healthheight;
1215 shieldstart = healthstart - shieldheight;
1216 healthstarttc = healthstart * (1.0f / 256.0f);
1217 healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1218 shieldstarttc = shieldstart * (1.0f / 256.0f);
1219 shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1220 ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1221 ammostart = 114 - ammoheight;
1222 ammostarttc = ammostart * (1.0f / 256.0f);
1223 ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1224 clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1225 clipstart = 190 - clipheight;
1226 clipstarttc = clipstart * (1.0f / 256.0f);
1227 clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1228 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);
1229 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);
1230 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);
1231 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);
1232 DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1233 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1236 else // Quake and others
1238 sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1239 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1240 //if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1241 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1244 sbar_x = (vid_conwidth.integer - 320)/2;
1248 if (gamemode != GAME_GOODVSBAD2)
1249 Sbar_DrawInventory ();
1250 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1254 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1256 if (gamemode != GAME_GOODVSBAD2)
1257 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1258 Sbar_DrawScoreboard ();
1262 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1264 // keys (hipnotic only)
1265 //MED 01/04/97 moved keys here so they would not be overwritten
1266 if (gamemode == GAME_HIPNOTIC)
1268 if (cl.stats[STAT_ITEMS] & IT_KEY1)
1269 Sbar_DrawPic (209, 3, sb_items[0]);
1270 if (cl.stats[STAT_ITEMS] & IT_KEY2)
1271 Sbar_DrawPic (209, 12, sb_items[1]);
1274 if (gamemode != GAME_GOODVSBAD2)
1276 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1278 Sbar_DrawNum (24, 0, 666, 3, 1);
1279 Sbar_DrawPic (0, 0, sb_disc);
1283 if (gamemode == GAME_ROGUE)
1285 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1286 if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1287 Sbar_DrawPic (0, 0, sb_armor[2]);
1288 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1289 Sbar_DrawPic (0, 0, sb_armor[1]);
1290 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1291 Sbar_DrawPic (0, 0, sb_armor[0]);
1295 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1296 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1297 Sbar_DrawPic (0, 0, sb_armor[2]);
1298 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1299 Sbar_DrawPic (0, 0, sb_armor[1]);
1300 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1301 Sbar_DrawPic (0, 0, sb_armor[0]);
1310 Sbar_DrawNum (154, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1313 if (gamemode == GAME_ROGUE)
1315 if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1316 Sbar_DrawPic (224, 0, sb_ammo[0]);
1317 else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1318 Sbar_DrawPic (224, 0, sb_ammo[1]);
1319 else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1320 Sbar_DrawPic (224, 0, sb_ammo[2]);
1321 else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1322 Sbar_DrawPic (224, 0, sb_ammo[3]);
1323 else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1324 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1325 else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1326 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1327 else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1328 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1332 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1333 Sbar_DrawPic (224, 0, sb_ammo[0]);
1334 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1335 Sbar_DrawPic (224, 0, sb_ammo[1]);
1336 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1337 Sbar_DrawPic (224, 0, sb_ammo[2]);
1338 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1339 Sbar_DrawPic (224, 0, sb_ammo[3]);
1342 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1346 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1347 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1348 if (!cl.islocalgame && vid_conwidth.integer > 320)
1350 if (gamemode == GAME_TRANSFUSION)
1351 Sbar_MiniDeathmatchOverlay (0, 0);
1353 Sbar_MiniDeathmatchOverlay (324, vid_conheight.integer - sb_lines);
1360 if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && crosshair.integer <= NUMCROSSHAIRS && !cl.intermission && !r_letterbox.value && (pic = r_crosshairs[crosshair.integer]))
1361 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);
1363 if (cl_prydoncursor.integer)
1364 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);
1367 //=============================================================================
1371 Sbar_DeathmatchOverlay
1375 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1379 minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : cl.time - s->qw_entertime) / 60.0);
1380 if (s->qw_spectator)
1382 if (s->qw_ping || s->qw_packetloss)
1383 DrawQ_ColoredString(x, y, va("%4i %3i %4i spect %-4s %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1385 DrawQ_ColoredString(x, y, va(" %4i spect %-4s %c%s", minutes, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1389 // draw colors behind score
1390 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1391 DrawQ_Pic(x + 14*8, y+1, NULL, 40, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
1392 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1393 DrawQ_Pic(x + 14*8, y+4, NULL, 40, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
1395 //DrawQ_String(x, y, va("%c%4i %s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1396 if (s->qw_ping || s->qw_packetloss)
1397 DrawQ_ColoredString(x, y, va("%4i %3i %4i %5i %-4s %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1399 DrawQ_ColoredString(x, y, va(" %4i %5i %-4s %c%s", minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1404 void Sbar_DeathmatchOverlay (void)
1408 // request new ping times every two second
1409 if (cl.last_ping_request < realtime - 2 && cls.netcon)
1411 cl.last_ping_request = realtime;
1412 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1414 MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
1415 MSG_WriteString(&cls.netcon->message, "pings");
1417 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)
1419 // 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
1420 cl.parsingtextexpectingpingforscores = true; // hide the output of the next ping report
1421 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1422 MSG_WriteString(&cls.netcon->message, "ping");
1426 // newer server definitely has pings command, so use it for more efficiency
1427 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1428 MSG_WriteString(&cls.netcon->message, "pings");
1432 DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1437 x = (vid_conwidth.integer - (6 + 18 + 15) * 8) / 2;
1439 DrawQ_ColoredString(x, y, va("ping pl%% time frags team name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1442 if (Sbar_IsTeammatch ())
1444 // show team scores first
1445 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1446 y += (int)Sbar_PrintScoreboardItem((teams + teamsort[i]), x, y);
1450 for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1451 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1456 Sbar_DeathmatchOverlay
1460 void Sbar_MiniDeathmatchOverlay (int x, int y)
1464 // decide where to print
1465 if (gamemode == GAME_TRANSFUSION)
1466 numlines = (vid_conwidth.integer - x + 127) / 128;
1468 numlines = (vid_conheight.integer - y + 7) / 8;
1470 // give up if there isn't room
1471 if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1478 for (i = 0; i < scoreboardlines; i++)
1479 if (fragsort[i] == cl.playerentity - 1)
1484 i = min(i, scoreboardlines - numlines);
1487 if (gamemode == GAME_TRANSFUSION)
1489 for (;i < scoreboardlines && x < vid_conwidth.integer;i++)
1490 x += 128 + (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1494 for (;i < scoreboardlines && y < vid_conheight.integer;i++)
1495 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1501 Sbar_IntermissionOverlay
1505 void Sbar_IntermissionOverlay (void)
1510 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1511 //if (cl.gametype == GAME_DEATHMATCH)
1512 if (!cl.islocalgame)
1514 Sbar_DeathmatchOverlay ();
1518 sbar_x = (vid_conwidth.integer - 320) >> 1;
1519 sbar_y = (vid_conheight.integer - 200) >> 1;
1521 DrawQ_Pic (sbar_x + 64, sbar_y + 24, sb_complete, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1522 DrawQ_Pic (sbar_x + 0, sbar_y + 56, sb_inter, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1525 dig = (int)cl.completed_time / 60;
1526 Sbar_DrawNum (160, 64, dig, 3, 0);
1527 num = (int)cl.completed_time - dig*60;
1528 if (gamemode != GAME_NEXUIZ)
1529 Sbar_DrawPic (234,64,sb_colon);
1530 Sbar_DrawPic (246,64,sb_nums[0][num/10]);
1531 Sbar_DrawPic (266,64,sb_nums[0][num%10]);
1533 Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
1534 if (gamemode != GAME_NEXUIZ)
1535 Sbar_DrawPic (232, 104, sb_slash);
1536 Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1538 Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1539 if (gamemode != GAME_NEXUIZ)
1540 Sbar_DrawPic (232, 144, sb_slash);
1541 Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1552 void Sbar_FinaleOverlay (void)
1554 DrawQ_Pic((vid_conwidth.integer - sb_finale->width)/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);