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 const char* teamname;
558 color = cl.scores[fragsort[i]].colors & 15;
564 teamname = "^1Red Team";
567 teamname = "^4Blue Team";
570 teamname = "^6Pink Team";
573 teamname = "^3Yellow Team";
576 teamname = "Total Team Score";
579 strlcpy(teams[teamlines-1].name, teamname, sizeof(teams[teamlines-1].name));
581 teams[teamlines-1].frags = 0;
582 teams[teamlines-1].colors = color + 16 * color;
585 if (cl.scores[fragsort[i]].frags != -666)
587 // do not add spedcators
588 // (ugly hack for nexuiz)
589 teams[teamlines-1].frags += cl.scores[fragsort[i]].frags;
593 // now sort teams by scores.
594 for (i=0 ; i<teamlines ; i++)
596 for (i=0 ; i<teamlines ; i++)
598 for (j=0 ; j<teamlines-1-i ; j++)
600 if (teams[teamsort[j]].frags < teams[teamsort[j+1]].frags)
603 teamsort[j] = teamsort[j+1];
616 void Sbar_SoloScoreboard (void)
619 int minutes, seconds, tens, units;
622 if (gamemode != GAME_NEXUIZ) {
623 sprintf (str,"Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
624 Sbar_DrawString (8, 4, str);
626 sprintf (str,"Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
627 Sbar_DrawString (8, 12, str);
631 minutes = (int)(cl.time / 60);
632 seconds = (int)(cl.time - 60*minutes);
634 units = seconds - 10*tens;
635 sprintf (str,"Time :%3i:%i%i", minutes, tens, units);
636 Sbar_DrawString (184, 4, str);
639 if (gamemode == GAME_NEXUIZ) {
640 l = (int) strlen (cl.worldmodel->name);
641 Sbar_DrawString (232 - l*4, 12, cl.worldmodel->name);
643 l = (int) strlen (cl.levelname);
644 Sbar_DrawString (232 - l*4, 12, cl.levelname);
653 void Sbar_DrawScoreboard (void)
655 Sbar_SoloScoreboard ();
656 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
657 //if (cl.gametype == GAME_DEATHMATCH)
659 Sbar_DeathmatchOverlay ();
662 //=============================================================================
664 // AK to make DrawInventory smaller
665 static void Sbar_DrawWeapon(int nr, float fade, int active)
667 // width = 300, height = 100
668 const int w_width = 300, w_height = 100, w_space = 10;
669 const float w_scale = 0.4;
671 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);
672 //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);
675 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);
683 void Sbar_DrawInventory (void)
690 if (gamemode == GAME_ROGUE)
692 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
693 Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], sbar_alpha_bg.value);
695 Sbar_DrawAlphaPic (0, -24, rsb_invbar[1], sbar_alpha_bg.value);
698 Sbar_DrawAlphaPic (0, -24, sb_ibar, sbar_alpha_bg.value);
701 for (i=0 ; i<7 ; i++)
703 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<i) )
705 time = cl.item_gettime[i];
706 flashon = (int)((cl.time - time)*10);
709 if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i) )
715 flashon = (flashon%5) + 2;
717 Sbar_DrawAlphaPic (i*24, -16, sb_weapons[flashon][i], sbar_alpha_bg.value);
723 if (gamemode == GAME_HIPNOTIC)
725 int grenadeflashing=0;
726 for (i=0 ; i<4 ; i++)
728 if (cl.stats[STAT_ITEMS] & (1<<hipweapons[i]) )
730 time = cl.item_gettime[hipweapons[i]];
731 flashon = (int)((cl.time - time)*10);
734 if ( cl.stats[STAT_ACTIVEWEAPON] == (1<<hipweapons[i]) )
740 flashon = (flashon%5) + 2;
742 // check grenade launcher
745 if (cl.stats[STAT_ITEMS] & HIT_PROXIMITY_GUN)
750 Sbar_DrawPic (96, -16, hsb_weapons[flashon][2]);
756 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<4))
758 if (!grenadeflashing)
759 Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
762 Sbar_DrawPic (96, -16, hsb_weapons[flashon][4]);
765 Sbar_DrawPic (176 + (i*24), -16, hsb_weapons[flashon][i]);
770 if (gamemode == GAME_ROGUE)
772 // check for powered up weapon.
773 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
775 if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i))
776 Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]);
780 for (i=0 ; i<4 ; i++)
782 sprintf (num, "%3i",cl.stats[STAT_SHELLS+i] );
784 Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[0] - '0');
786 Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[1] - '0');
788 Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0');
792 for (i=0 ; i<6 ; i++)
793 if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
795 //MED 01/04/97 changed keys
796 if (gamemode != GAME_HIPNOTIC || (i>1))
797 Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
800 //MED 01/04/97 added hipnotic items
802 if (gamemode == GAME_HIPNOTIC)
804 for (i=0 ; i<2 ; i++)
805 if (cl.stats[STAT_ITEMS] & (1<<(24+i)))
806 Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
809 if (gamemode == GAME_ROGUE)
812 for (i=0 ; i<2 ; i++)
813 if (cl.stats[STAT_ITEMS] & (1<<(29+i)))
814 Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
819 for (i=0 ; i<4 ; i++)
820 if (cl.stats[STAT_ITEMS] & (1<<(28+i)))
821 Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
825 //=============================================================================
832 void Sbar_DrawFrags (void)
842 l = min(scoreboardlines, 4);
846 for (i = 0;i < l;i++)
852 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
853 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);
854 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
855 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);
859 sprintf (num, "%3i",f);
861 if (k == cl.viewentity - 1)
863 Sbar_DrawCharacter ( x + 2, -24, 16);
864 Sbar_DrawCharacter ( x + 32 - 4, -24, 17);
866 Sbar_DrawCharacter (x + 8, -24, num[0]);
867 Sbar_DrawCharacter (x + 16, -24, num[1]);
868 Sbar_DrawCharacter (x + 24, -24, num[2]);
873 //=============================================================================
881 void Sbar_DrawFace (void)
885 // PGM 01/19/97 - team color drawing
886 // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
887 if (gamemode == GAME_ROGUE && !cl.islocalgame && (teamplay.integer > 3) && (teamplay.integer < 7))
893 s = &cl.scores[cl.viewentity - 1];
895 Sbar_DrawPic (112, 0, rsb_teambord);
896 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
897 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);
898 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
899 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);
903 sprintf (num, "%3i",f);
905 if ((s->colors & 0xf0)==0)
908 Sbar_DrawCharacter(109, 3, 18 + num[0] - '0');
910 Sbar_DrawCharacter(116, 3, 18 + num[1] - '0');
912 Sbar_DrawCharacter(123, 3, 18 + num[2] - '0');
916 Sbar_DrawCharacter ( 109, 3, num[0]);
917 Sbar_DrawCharacter ( 116, 3, num[1]);
918 Sbar_DrawCharacter ( 123, 3, num[2]);
923 // PGM 01/19/97 - team color drawing
925 if ( (cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
926 Sbar_DrawPic (112, 0, sb_face_invis_invuln);
927 else if (cl.stats[STAT_ITEMS] & IT_QUAD)
928 Sbar_DrawPic (112, 0, sb_face_quad );
929 else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
930 Sbar_DrawPic (112, 0, sb_face_invis );
931 else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
932 Sbar_DrawPic (112, 0, sb_face_invuln);
935 f = cl.stats[STAT_HEALTH] / 20;
937 Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]);
941 void Sbar_ShowFPS(void)
943 float fps_x, fps_y, fps_scalex, fps_scaley, fps_height;
947 qboolean red = false;
954 static double nexttime = 0, lasttime = 0;
955 static double framerate = 0;
956 static int framecount = 0;
958 newtime = Sys_DoubleTime();
959 if (newtime >= nexttime)
961 framerate = framecount / (newtime - lasttime);
963 nexttime = max(nexttime + 1, lasttime - 1);
969 if ((red = (calc < 1.0f)))
970 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0f / calc + 0.5));
972 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(calc + 0.5));
974 if (showtime.integer)
975 strlcpy(timestring, Sys_TimeString(showtime_format.string), sizeof(timestring));
976 if (showdate.integer)
977 strlcpy(datestring, Sys_TimeString(showdate_format.string), sizeof(datestring));
978 if (fpsstring[0] || timestring[0])
982 fps_height = fps_scaley * ((fpsstring[0] != 0) + (timestring[0] != 0) + (datestring[0] != 0));
983 //fps_y = vid_conheight.integer - sb_lines; // yes this may draw over the sbar
984 //fps_y = bound(0, fps_y, vid_conheight.integer - fps_height);
985 fps_y = vid_conheight.integer - fps_height;
988 fps_x = vid_conwidth.integer - fps_scalex * strlen(fpsstring);
989 DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(fpsstring), fps_scaley, 0, 0, 0, 0.5, 0);
991 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 0, 0, 1, 0);
993 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
998 fps_x = vid_conwidth.integer - fps_scalex * strlen(timestring);
999 DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(timestring), fps_scaley, 0, 0, 0, 0.5, 0);
1000 DrawQ_String(fps_x, fps_y, timestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
1001 fps_y += fps_scaley;
1005 fps_x = vid_conwidth.integer - fps_scalex * strlen(datestring);
1006 DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(datestring), fps_scaley, 0, 0, 0, 0.5, 0);
1007 DrawQ_String(fps_x, fps_y, datestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
1008 fps_y += fps_scaley;
1013 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)
1016 c2 = bound(0, c2, 1);
1017 c1 = bound(0, c1, 1 - c2);
1019 r[1] = rangey + rangeheight * (c2 + c1);
1020 r[2] = rangey + rangeheight * (c2);
1024 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);
1026 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);
1028 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);
1030 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);
1038 extern float v_dmg_time, v_dmg_roll, v_dmg_pitch;
1039 extern cvar_t v_kicktime;
1040 void Sbar_Draw (void)
1044 if(cl.csqc_vidvars.drawenginesbar) //[515]: csqc drawsbar
1046 if (cl.intermission == 1)
1048 Sbar_IntermissionOverlay();
1051 else if (cl.intermission == 2)
1053 Sbar_FinaleOverlay();
1057 if (gamemode == GAME_NETHERWORLD)
1060 else if (gamemode == GAME_SOM)
1062 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1063 Sbar_DrawScoreboard ();
1066 // this is the top left of the sbar area
1068 sbar_y = vid_conheight.integer - 24*3;
1071 if (cl.stats[STAT_ARMOR])
1073 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1074 Sbar_DrawPic(0, 0, somsb_armor[2]);
1075 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1076 Sbar_DrawPic(0, 0, somsb_armor[1]);
1077 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1078 Sbar_DrawPic(0, 0, somsb_armor[0]);
1079 Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1083 Sbar_DrawPic(0, 24, somsb_health);
1084 Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1087 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1088 Sbar_DrawPic(0, 48, somsb_ammo[0]);
1089 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1090 Sbar_DrawPic(0, 48, somsb_ammo[1]);
1091 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1092 Sbar_DrawPic(0, 48, somsb_ammo[2]);
1093 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1094 Sbar_DrawPic(0, 48, somsb_ammo[3]);
1095 Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
1096 if (cl.stats[STAT_SHELLS])
1097 Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
1100 else if (gamemode == GAME_NEXUIZ)
1102 sbar_y = vid_conheight.integer - 47;
1103 sbar_x = (vid_conwidth.integer - 640)/2;
1105 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1107 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1108 Sbar_DrawScoreboard ();
1116 // we have a max time 2s (min time = 0)
1117 if ((time = cl.time - cl.weapontime) < 2)
1119 fade = (1.0 - 0.5 * time);
1121 for (i = 0; i < 8;i++)
1122 if (cl.stats[STAT_ITEMS] & (1 << i))
1123 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1125 if((cl.stats[STAT_ITEMS] & (1<<12)))
1126 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1129 //if (!cl.islocalgame)
1130 // Sbar_DrawFrags ();
1133 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1135 Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1138 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1140 // Nexuiz has no anum pics
1141 //Sbar_DrawNum (36, 0, 666, 3, 1);
1142 // Nexuiz has no disc pic
1143 //Sbar_DrawPic (0, 0, sb_disc);
1147 Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1150 if(cl.stats[STAT_HEALTH] > 100)
1151 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1152 else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1153 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1155 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1157 // AK dont draw ammo for the laser
1158 if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1160 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1161 Sbar_DrawPic (519, 0, sb_ammo[0]);
1162 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1163 Sbar_DrawPic (519, 0, sb_ammo[1]);
1164 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1165 Sbar_DrawPic (519, 0, sb_ammo[2]);
1166 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1167 Sbar_DrawPic (519, 0, sb_ammo[3]);
1169 if(cl.stats[STAT_AMMO] <= 10)
1170 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1172 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1177 DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1180 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1181 // Sbar_MiniDeathmatchOverlay (0, 17);
1183 else if (gamemode == GAME_ZYMOTIC)
1186 float scale = 64.0f / 256.0f;
1187 float kickoffset[3];
1188 VectorClear(kickoffset);
1191 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1192 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1194 sbar_x = (int)((vid_conwidth.integer - 256 * scale)/2 + kickoffset[0]);
1195 sbar_y = (int)((vid_conheight.integer - 256 * scale)/2 + kickoffset[1]);
1196 // left1 16, 48 : 126 -66
1197 // left2 16, 128 : 196 -66
1198 // right 176, 48 : 196 -136
1199 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);
1200 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);
1201 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);
1202 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1204 float scale = 128.0f / 256.0f;
1205 float healthstart, healthheight, healthstarttc, healthendtc;
1206 float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1207 float ammostart, ammoheight, ammostarttc, ammoendtc;
1208 float clipstart, clipheight, clipstarttc, clipendtc;
1209 float kickoffset[3], offset;
1210 VectorClear(kickoffset);
1213 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1214 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1216 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1217 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1218 offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1219 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);
1220 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);
1221 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);
1222 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);
1223 healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1224 shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1225 healthstart = 204 - healthheight;
1226 shieldstart = healthstart - shieldheight;
1227 healthstarttc = healthstart * (1.0f / 256.0f);
1228 healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1229 shieldstarttc = shieldstart * (1.0f / 256.0f);
1230 shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1231 ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1232 ammostart = 114 - ammoheight;
1233 ammostarttc = ammostart * (1.0f / 256.0f);
1234 ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1235 clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1236 clipstart = 190 - clipheight;
1237 clipstarttc = clipstart * (1.0f / 256.0f);
1238 clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1239 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);
1240 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);
1241 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);
1242 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);
1243 DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1244 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1247 else // Quake and others
1249 sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1250 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1251 //if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1252 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1255 sbar_x = (vid_conwidth.integer - 320)/2;
1259 if (gamemode != GAME_GOODVSBAD2)
1260 Sbar_DrawInventory ();
1261 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1265 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1267 if (gamemode != GAME_GOODVSBAD2)
1268 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1269 Sbar_DrawScoreboard ();
1273 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1275 // keys (hipnotic only)
1276 //MED 01/04/97 moved keys here so they would not be overwritten
1277 if (gamemode == GAME_HIPNOTIC)
1279 if (cl.stats[STAT_ITEMS] & IT_KEY1)
1280 Sbar_DrawPic (209, 3, sb_items[0]);
1281 if (cl.stats[STAT_ITEMS] & IT_KEY2)
1282 Sbar_DrawPic (209, 12, sb_items[1]);
1285 if (gamemode != GAME_GOODVSBAD2)
1287 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1289 Sbar_DrawNum (24, 0, 666, 3, 1);
1290 Sbar_DrawPic (0, 0, sb_disc);
1294 if (gamemode == GAME_ROGUE)
1296 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1297 if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1298 Sbar_DrawPic (0, 0, sb_armor[2]);
1299 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1300 Sbar_DrawPic (0, 0, sb_armor[1]);
1301 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1302 Sbar_DrawPic (0, 0, sb_armor[0]);
1306 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1307 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1308 Sbar_DrawPic (0, 0, sb_armor[2]);
1309 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1310 Sbar_DrawPic (0, 0, sb_armor[1]);
1311 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1312 Sbar_DrawPic (0, 0, sb_armor[0]);
1321 Sbar_DrawNum (154, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1324 if (gamemode == GAME_ROGUE)
1326 if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1327 Sbar_DrawPic (224, 0, sb_ammo[0]);
1328 else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1329 Sbar_DrawPic (224, 0, sb_ammo[1]);
1330 else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1331 Sbar_DrawPic (224, 0, sb_ammo[2]);
1332 else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1333 Sbar_DrawPic (224, 0, sb_ammo[3]);
1334 else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1335 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1336 else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1337 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1338 else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1339 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1343 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1344 Sbar_DrawPic (224, 0, sb_ammo[0]);
1345 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1346 Sbar_DrawPic (224, 0, sb_ammo[1]);
1347 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1348 Sbar_DrawPic (224, 0, sb_ammo[2]);
1349 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1350 Sbar_DrawPic (224, 0, sb_ammo[3]);
1353 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1357 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1358 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1359 if (!cl.islocalgame && vid_conwidth.integer > 320)
1361 if (gamemode == GAME_TRANSFUSION)
1362 Sbar_MiniDeathmatchOverlay (0, 0);
1364 Sbar_MiniDeathmatchOverlay (324, vid_conheight.integer - sb_lines);
1371 if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && crosshair.integer <= NUMCROSSHAIRS && !cl.intermission && !r_letterbox.value && (pic = r_crosshairs[crosshair.integer]))
1372 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);
1374 if (cl_prydoncursor.integer)
1375 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);
1378 //=============================================================================
1382 Sbar_DeathmatchOverlay
1386 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1390 minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : cl.time - s->qw_entertime) / 60.0);
1391 if (s->qw_spectator)
1393 if (s->qw_ping || s->qw_packetloss)
1394 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 );
1396 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 );
1400 // draw colors behind score
1401 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1402 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);
1403 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1404 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);
1406 //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);
1407 if (s->qw_ping || s->qw_packetloss)
1408 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 );
1410 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 );
1415 void Sbar_DeathmatchOverlay (void)
1419 // request new ping times every two second
1420 if (cl.last_ping_request < realtime - 2 && cls.netcon)
1422 cl.last_ping_request = realtime;
1423 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1425 MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
1426 MSG_WriteString(&cls.netcon->message, "pings");
1428 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)
1430 // 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
1431 cl.parsingtextexpectingpingforscores = true; // hide the output of the next ping report
1432 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1433 MSG_WriteString(&cls.netcon->message, "ping");
1437 // newer server definitely has pings command, so use it for more efficiency
1438 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1439 MSG_WriteString(&cls.netcon->message, "pings");
1443 DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1448 x = (vid_conwidth.integer - (6 + 18 + 15) * 8) / 2;
1450 DrawQ_ColoredString(x, y, va("ping pl%% time frags team name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1453 if (Sbar_IsTeammatch ())
1455 // show team scores first
1456 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1457 y += (int)Sbar_PrintScoreboardItem((teams + teamsort[i]), x, y);
1461 for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1462 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1467 Sbar_DeathmatchOverlay
1471 void Sbar_MiniDeathmatchOverlay (int x, int y)
1475 // decide where to print
1476 if (gamemode == GAME_TRANSFUSION)
1477 numlines = (vid_conwidth.integer - x + 127) / 128;
1479 numlines = (vid_conheight.integer - y + 7) / 8;
1481 // give up if there isn't room
1482 if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1489 for (i = 0; i < scoreboardlines; i++)
1490 if (fragsort[i] == cl.playerentity - 1)
1495 i = min(i, scoreboardlines - numlines);
1498 if (gamemode == GAME_TRANSFUSION)
1500 for (;i < scoreboardlines && x < vid_conwidth.integer;i++)
1501 x += 128 + (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1505 for (;i < scoreboardlines && y < vid_conheight.integer;i++)
1506 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1512 Sbar_IntermissionOverlay
1516 void Sbar_IntermissionOverlay (void)
1521 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1522 //if (cl.gametype == GAME_DEATHMATCH)
1523 if (!cl.islocalgame)
1525 Sbar_DeathmatchOverlay ();
1529 sbar_x = (vid_conwidth.integer - 320) >> 1;
1530 sbar_y = (vid_conheight.integer - 200) >> 1;
1532 DrawQ_Pic (sbar_x + 64, sbar_y + 24, sb_complete, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1533 DrawQ_Pic (sbar_x + 0, sbar_y + 56, sb_inter, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1536 dig = (int)cl.completed_time / 60;
1537 Sbar_DrawNum (160, 64, dig, 3, 0);
1538 num = (int)cl.completed_time - dig*60;
1539 if (gamemode != GAME_NEXUIZ)
1540 Sbar_DrawPic (234,64,sb_colon);
1541 Sbar_DrawPic (246,64,sb_nums[0][num/10]);
1542 Sbar_DrawPic (266,64,sb_nums[0][num%10]);
1544 Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
1545 if (gamemode != GAME_NEXUIZ)
1546 Sbar_DrawPic (232, 104, sb_slash);
1547 Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1549 Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1550 if (gamemode != GAME_NEXUIZ)
1551 Sbar_DrawPic (232, 144, sb_slash);
1552 Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1563 void Sbar_FinaleOverlay (void)
1565 DrawQ_Pic((vid_conwidth.integer - sb_finale->width)/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);