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
24 typedef struct sbarpic_s
30 static sbarpic_t sbarpics[256];
31 static int numsbarpics;
33 static sbarpic_t *Sbar_NewPic(const char *name)
35 strcpy(sbarpics[numsbarpics].name, name);
37 // FIXME: precache on every renderer restart (or move this to client)
38 Draw_CachePic(sbarpics[numsbarpics].name, true);
39 return sbarpics + (numsbarpics++);
44 #define STAT_MINUS 10 // num frame for '-' stats digit
45 sbarpic_t *sb_nums[2][11];
46 sbarpic_t *sb_colon, *sb_slash;
49 sbarpic_t *sb_scorebar;
50 // AK only used by NEX
51 sbarpic_t *sb_sbar_minimal;
52 sbarpic_t *sb_sbar_overlay;
54 // AK changed the bound to 9
55 sbarpic_t *sb_weapons[7][9]; // 0 is active, 1 is owned, 2-5 are flashes
56 sbarpic_t *sb_ammo[4];
57 sbarpic_t *sb_sigil[4];
58 sbarpic_t *sb_armor[3];
59 sbarpic_t *sb_items[32];
61 // 0-4 are based on health (in 20 increments)
62 // 0 is static, 1 is temporary animation
63 sbarpic_t *sb_faces[5][2];
65 sbarpic_t *sb_face_invis;
66 sbarpic_t *sb_face_quad;
67 sbarpic_t *sb_face_invuln;
68 sbarpic_t *sb_face_invis_invuln;
70 qboolean sb_showscores;
72 int sb_lines; // scan lines to draw
74 sbarpic_t *rsb_invbar[2];
75 sbarpic_t *rsb_weapons[5];
76 sbarpic_t *rsb_items[2];
77 sbarpic_t *rsb_ammo[3];
78 sbarpic_t *rsb_teambord; // PGM 01/19/97 - team color border
80 //MED 01/04/97 added two more weapons + 3 alternates for grenade launcher
81 sbarpic_t *hsb_weapons[7][5]; // 0 is active, 1 is owned, 2-5 are flashes
82 //MED 01/04/97 added array to simplify weapon parsing
83 int hipweapons[4] = {HIT_LASER_CANNON_BIT,HIT_MJOLNIR_BIT,4,HIT_PROXIMITY_GUN_BIT};
84 //MED 01/04/97 added hipnotic items array
85 sbarpic_t *hsb_items[2];
88 sbarpic_t *somsb_health;
89 sbarpic_t *somsb_ammo[4];
90 sbarpic_t *somsb_armor[3];
92 sbarpic_t *zymsb_crosshair_center;
93 sbarpic_t *zymsb_crosshair_line;
94 sbarpic_t *zymsb_crosshair_health;
95 sbarpic_t *zymsb_crosshair_ammo;
96 sbarpic_t *zymsb_crosshair_clip;
97 sbarpic_t *zymsb_crosshair_background;
98 sbarpic_t *zymsb_crosshair_left1;
99 sbarpic_t *zymsb_crosshair_left2;
100 sbarpic_t *zymsb_crosshair_right;
102 cvar_t showfps = {CVAR_SAVE, "showfps", "0", "shows your rendered fps (frames per second)"};
103 cvar_t showtime = {CVAR_SAVE, "showtime", "0", "shows current time of day (useful on screenshots)"};
104 cvar_t showtime_format = {CVAR_SAVE, "showtime_format", "%H:%M:%S", "format string for time of day"};
105 cvar_t showdate = {CVAR_SAVE, "showdate", "0", "shows current date (useful on screenshots)"};
106 cvar_t showdate_format = {CVAR_SAVE, "showdate_format", "%Y-%m-%d", "format string for date"};
107 cvar_t sbar_alpha_bg = {CVAR_SAVE, "sbar_alpha_bg", "0.4", "opacity value of the statusbar background image"};
108 cvar_t sbar_alpha_fg = {CVAR_SAVE, "sbar_alpha_fg", "1", "opacity value of the statusbar weapon/item icons and numbers"};
110 cvar_t cl_deathscoreboard = {0, "cl_deathscoreboard", "1", "shows scoreboard (+showscores) while dead"};
112 void Sbar_MiniDeathmatchOverlay (int x, int y);
113 void Sbar_DeathmatchOverlay (void);
114 void Sbar_IntermissionOverlay (void);
115 void Sbar_FinaleOverlay (void);
125 void Sbar_ShowScores (void)
129 sb_showscores = true;
139 void Sbar_DontShowScores (void)
141 sb_showscores = false;
144 void sbar_start(void)
150 if (gamemode == GAME_NETHERWORLD)
153 else if (gamemode == GAME_SOM)
155 sb_disc = Sbar_NewPic("gfx/disc");
157 for (i = 0;i < 10;i++)
158 sb_nums[0][i] = Sbar_NewPic (va("gfx/num_%i",i));
160 somsb_health = Sbar_NewPic("gfx/hud_health");
161 somsb_ammo[0] = Sbar_NewPic("gfx/sb_shells");
162 somsb_ammo[1] = Sbar_NewPic("gfx/sb_nails");
163 somsb_ammo[2] = Sbar_NewPic("gfx/sb_rocket");
164 somsb_ammo[3] = Sbar_NewPic("gfx/sb_cells");
165 somsb_armor[0] = Sbar_NewPic("gfx/sb_armor1");
166 somsb_armor[1] = Sbar_NewPic("gfx/sb_armor2");
167 somsb_armor[2] = Sbar_NewPic("gfx/sb_armor3");
169 else if (gamemode == GAME_NEXUIZ)
171 for (i = 0;i < 10;i++)
172 sb_nums[0][i] = Sbar_NewPic (va("gfx/num_%i",i));
173 sb_nums[0][10] = Sbar_NewPic ("gfx/num_minus");
175 sb_ammo[0] = Sbar_NewPic ("gfx/sb_shells");
176 sb_ammo[1] = Sbar_NewPic ("gfx/sb_bullets");
177 sb_ammo[2] = Sbar_NewPic ("gfx/sb_rocket");
178 sb_ammo[3] = Sbar_NewPic ("gfx/sb_cells");
180 sb_items[2] = Sbar_NewPic ("gfx/sb_slowmo");
181 sb_items[3] = Sbar_NewPic ("gfx/sb_invinc");
182 sb_items[4] = Sbar_NewPic ("gfx/sb_energy");
183 sb_items[5] = Sbar_NewPic ("gfx/sb_str");
185 sb_sbar = Sbar_NewPic("gfx/sbar");
186 sb_sbar_minimal = Sbar_NewPic("gfx/sbar_minimal");
187 sb_sbar_overlay = Sbar_NewPic("gfx/sbar_overlay");
189 for(i = 0; i < 9;i++)
190 sb_weapons[0][i] = Sbar_NewPic(va("gfx/inv_weapon%i",i));
192 else if (gamemode == GAME_ZYMOTIC)
194 zymsb_crosshair_center = Sbar_NewPic ("gfx/hud/crosshair_center");
195 zymsb_crosshair_line = Sbar_NewPic ("gfx/hud/crosshair_line");
196 zymsb_crosshair_health = Sbar_NewPic ("gfx/hud/crosshair_health");
197 zymsb_crosshair_clip = Sbar_NewPic ("gfx/hud/crosshair_clip");
198 zymsb_crosshair_ammo = Sbar_NewPic ("gfx/hud/crosshair_ammo");
199 zymsb_crosshair_background = Sbar_NewPic ("gfx/hud/crosshair_background");
200 zymsb_crosshair_left1 = Sbar_NewPic ("gfx/hud/crosshair_left1");
201 zymsb_crosshair_left2 = Sbar_NewPic ("gfx/hud/crosshair_left2");
202 zymsb_crosshair_right = Sbar_NewPic ("gfx/hud/crosshair_right");
206 sb_disc = Sbar_NewPic("gfx/disc");
208 for (i = 0;i < 10;i++)
210 sb_nums[0][i] = Sbar_NewPic (va("gfx/num_%i",i));
211 sb_nums[1][i] = Sbar_NewPic (va("gfx/anum_%i",i));
214 sb_nums[0][10] = Sbar_NewPic ("gfx/num_minus");
215 sb_nums[1][10] = Sbar_NewPic ("gfx/anum_minus");
217 sb_colon = Sbar_NewPic ("gfx/num_colon");
218 sb_slash = Sbar_NewPic ("gfx/num_slash");
220 sb_weapons[0][0] = Sbar_NewPic ("gfx/inv_shotgun");
221 sb_weapons[0][1] = Sbar_NewPic ("gfx/inv_sshotgun");
222 sb_weapons[0][2] = Sbar_NewPic ("gfx/inv_nailgun");
223 sb_weapons[0][3] = Sbar_NewPic ("gfx/inv_snailgun");
224 sb_weapons[0][4] = Sbar_NewPic ("gfx/inv_rlaunch");
225 sb_weapons[0][5] = Sbar_NewPic ("gfx/inv_srlaunch");
226 sb_weapons[0][6] = Sbar_NewPic ("gfx/inv_lightng");
228 sb_weapons[1][0] = Sbar_NewPic ("gfx/inv2_shotgun");
229 sb_weapons[1][1] = Sbar_NewPic ("gfx/inv2_sshotgun");
230 sb_weapons[1][2] = Sbar_NewPic ("gfx/inv2_nailgun");
231 sb_weapons[1][3] = Sbar_NewPic ("gfx/inv2_snailgun");
232 sb_weapons[1][4] = Sbar_NewPic ("gfx/inv2_rlaunch");
233 sb_weapons[1][5] = Sbar_NewPic ("gfx/inv2_srlaunch");
234 sb_weapons[1][6] = Sbar_NewPic ("gfx/inv2_lightng");
236 for (i = 0;i < 5;i++)
238 sb_weapons[2+i][0] = Sbar_NewPic (va("gfx/inva%i_shotgun",i+1));
239 sb_weapons[2+i][1] = Sbar_NewPic (va("gfx/inva%i_sshotgun",i+1));
240 sb_weapons[2+i][2] = Sbar_NewPic (va("gfx/inva%i_nailgun",i+1));
241 sb_weapons[2+i][3] = Sbar_NewPic (va("gfx/inva%i_snailgun",i+1));
242 sb_weapons[2+i][4] = Sbar_NewPic (va("gfx/inva%i_rlaunch",i+1));
243 sb_weapons[2+i][5] = Sbar_NewPic (va("gfx/inva%i_srlaunch",i+1));
244 sb_weapons[2+i][6] = Sbar_NewPic (va("gfx/inva%i_lightng",i+1));
247 sb_ammo[0] = Sbar_NewPic ("gfx/sb_shells");
248 sb_ammo[1] = Sbar_NewPic ("gfx/sb_nails");
249 sb_ammo[2] = Sbar_NewPic ("gfx/sb_rocket");
250 sb_ammo[3] = Sbar_NewPic ("gfx/sb_cells");
252 sb_armor[0] = Sbar_NewPic ("gfx/sb_armor1");
253 sb_armor[1] = Sbar_NewPic ("gfx/sb_armor2");
254 sb_armor[2] = Sbar_NewPic ("gfx/sb_armor3");
256 sb_items[0] = Sbar_NewPic ("gfx/sb_key1");
257 sb_items[1] = Sbar_NewPic ("gfx/sb_key2");
258 sb_items[2] = Sbar_NewPic ("gfx/sb_invis");
259 sb_items[3] = Sbar_NewPic ("gfx/sb_invuln");
260 sb_items[4] = Sbar_NewPic ("gfx/sb_suit");
261 sb_items[5] = Sbar_NewPic ("gfx/sb_quad");
263 sb_sigil[0] = Sbar_NewPic ("gfx/sb_sigil1");
264 sb_sigil[1] = Sbar_NewPic ("gfx/sb_sigil2");
265 sb_sigil[2] = Sbar_NewPic ("gfx/sb_sigil3");
266 sb_sigil[3] = Sbar_NewPic ("gfx/sb_sigil4");
268 sb_faces[4][0] = Sbar_NewPic ("gfx/face1");
269 sb_faces[4][1] = Sbar_NewPic ("gfx/face_p1");
270 sb_faces[3][0] = Sbar_NewPic ("gfx/face2");
271 sb_faces[3][1] = Sbar_NewPic ("gfx/face_p2");
272 sb_faces[2][0] = Sbar_NewPic ("gfx/face3");
273 sb_faces[2][1] = Sbar_NewPic ("gfx/face_p3");
274 sb_faces[1][0] = Sbar_NewPic ("gfx/face4");
275 sb_faces[1][1] = Sbar_NewPic ("gfx/face_p4");
276 sb_faces[0][0] = Sbar_NewPic ("gfx/face5");
277 sb_faces[0][1] = Sbar_NewPic ("gfx/face_p5");
279 sb_face_invis = Sbar_NewPic ("gfx/face_invis");
280 sb_face_invuln = Sbar_NewPic ("gfx/face_invul2");
281 sb_face_invis_invuln = Sbar_NewPic ("gfx/face_inv2");
282 sb_face_quad = Sbar_NewPic ("gfx/face_quad");
284 sb_sbar = Sbar_NewPic ("gfx/sbar");
285 sb_ibar = Sbar_NewPic ("gfx/ibar");
286 sb_scorebar = Sbar_NewPic ("gfx/scorebar");
288 //MED 01/04/97 added new hipnotic weapons
289 if (gamemode == GAME_HIPNOTIC)
291 hsb_weapons[0][0] = Sbar_NewPic ("gfx/inv_laser");
292 hsb_weapons[0][1] = Sbar_NewPic ("gfx/inv_mjolnir");
293 hsb_weapons[0][2] = Sbar_NewPic ("gfx/inv_gren_prox");
294 hsb_weapons[0][3] = Sbar_NewPic ("gfx/inv_prox_gren");
295 hsb_weapons[0][4] = Sbar_NewPic ("gfx/inv_prox");
297 hsb_weapons[1][0] = Sbar_NewPic ("gfx/inv2_laser");
298 hsb_weapons[1][1] = Sbar_NewPic ("gfx/inv2_mjolnir");
299 hsb_weapons[1][2] = Sbar_NewPic ("gfx/inv2_gren_prox");
300 hsb_weapons[1][3] = Sbar_NewPic ("gfx/inv2_prox_gren");
301 hsb_weapons[1][4] = Sbar_NewPic ("gfx/inv2_prox");
303 for (i = 0;i < 5;i++)
305 hsb_weapons[2+i][0] = Sbar_NewPic (va("gfx/inva%i_laser",i+1));
306 hsb_weapons[2+i][1] = Sbar_NewPic (va("gfx/inva%i_mjolnir",i+1));
307 hsb_weapons[2+i][2] = Sbar_NewPic (va("gfx/inva%i_gren_prox",i+1));
308 hsb_weapons[2+i][3] = Sbar_NewPic (va("gfx/inva%i_prox_gren",i+1));
309 hsb_weapons[2+i][4] = Sbar_NewPic (va("gfx/inva%i_prox",i+1));
312 hsb_items[0] = Sbar_NewPic ("gfx/sb_wsuit");
313 hsb_items[1] = Sbar_NewPic ("gfx/sb_eshld");
315 else if (gamemode == GAME_ROGUE)
317 rsb_invbar[0] = Sbar_NewPic ("gfx/r_invbar1");
318 rsb_invbar[1] = Sbar_NewPic ("gfx/r_invbar2");
320 rsb_weapons[0] = Sbar_NewPic ("gfx/r_lava");
321 rsb_weapons[1] = Sbar_NewPic ("gfx/r_superlava");
322 rsb_weapons[2] = Sbar_NewPic ("gfx/r_gren");
323 rsb_weapons[3] = Sbar_NewPic ("gfx/r_multirock");
324 rsb_weapons[4] = Sbar_NewPic ("gfx/r_plasma");
326 rsb_items[0] = Sbar_NewPic ("gfx/r_shield1");
327 rsb_items[1] = Sbar_NewPic ("gfx/r_agrav1");
329 // PGM 01/19/97 - team color border
330 rsb_teambord = Sbar_NewPic ("gfx/r_teambord");
331 // PGM 01/19/97 - team color border
333 rsb_ammo[0] = Sbar_NewPic ("gfx/r_ammolava");
334 rsb_ammo[1] = Sbar_NewPic ("gfx/r_ammomulti");
335 rsb_ammo[2] = Sbar_NewPic ("gfx/r_ammoplasma");
340 void sbar_shutdown(void)
344 void sbar_newmap(void)
348 void Sbar_Init (void)
350 Cmd_AddCommand ("+showscores", Sbar_ShowScores, "show scoreboard");
351 Cmd_AddCommand ("-showscores", Sbar_DontShowScores, "hide scoreboard");
352 Cvar_RegisterVariable (&showfps);
353 Cvar_RegisterVariable (&showtime);
354 Cvar_RegisterVariable (&showtime_format);
355 Cvar_RegisterVariable (&showdate);
356 Cvar_RegisterVariable (&showdate_format);
357 Cvar_RegisterVariable (&sbar_alpha_bg);
358 Cvar_RegisterVariable (&sbar_alpha_fg);
359 Cvar_RegisterVariable (&cl_deathscoreboard);
361 R_RegisterModule("sbar", sbar_start, sbar_shutdown, sbar_newmap);
365 //=============================================================================
367 // drawing routines are relative to the status bar location
376 void Sbar_DrawPic (int x, int y, sbarpic_t *sbarpic)
378 DrawQ_Pic (sbar_x + x, sbar_y + y, sbarpic->name, 0, 0, 1, 1, 1, sbar_alpha_fg.value, 0);
381 void Sbar_DrawAlphaPic (int x, int y, sbarpic_t *sbarpic, float alpha)
383 DrawQ_Pic (sbar_x + x, sbar_y + y, sbarpic->name, 0, 0, 1, 1, 1, alpha, 0);
390 Draws one solid graphics character
393 void Sbar_DrawCharacter (int x, int y, int num)
395 DrawQ_String (sbar_x + x + 4 , sbar_y + y, va("%c", num), 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0);
403 void Sbar_DrawString (int x, int y, char *str)
405 DrawQ_String (sbar_x + x, sbar_y + y, str, 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0);
413 void Sbar_DrawNum (int x, int y, int num, int digits, int color)
418 l = sprintf(str, "%i", num);
432 Sbar_DrawPic (x, y, sb_nums[color][frame]);
445 void Sbar_DrawXNum (int x, int y, int num, int digits, int lettersize, float r, float g, float b, float a, int flags)
450 l = sprintf(str, "%i", num);
455 x += (digits-l) * lettersize;
464 DrawQ_Pic (sbar_x + x, sbar_y + y, sb_nums[0][frame]->name,lettersize,lettersize,r,g,b,a * sbar_alpha_fg.value,flags);
471 //=============================================================================
474 int Sbar_IsTeammatch()
476 // currently only nexuiz uses the team score board
477 return ((gamemode == GAME_NEXUIZ)
478 && (teamplay.integer > 0));
486 static int fragsort[MAX_SCOREBOARD];
487 static int scoreboardlines;
489 //[515]: Sbar_GetPlayer for csqc "getplayerkey" func
490 int Sbar_GetPlayer (int index)
495 if(index >= scoreboardlines)
497 index = fragsort[index];
499 if(index >= scoreboardlines)
504 static scoreboard_t teams[MAX_SCOREBOARD];
505 static int teamsort[MAX_SCOREBOARD];
506 static int teamlines;
507 void Sbar_SortFrags (void)
513 for (i=0 ; i<cl.maxclients ; i++)
515 if (cl.scores[i].name[0])
517 fragsort[scoreboardlines] = i;
522 for (i=0 ; i<scoreboardlines ; i++)
523 for (j=0 ; j<scoreboardlines-1-i ; j++)
524 if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j+1]].frags)
527 fragsort[j] = fragsort[j+1];
532 if (Sbar_IsTeammatch ())
534 // now sort players by teams.
535 for (i=0 ; i<scoreboardlines ; i++)
537 for (j=0 ; j<scoreboardlines-1-i ; j++)
539 if (cl.scores[fragsort[j]].colors < cl.scores[fragsort[j+1]].colors)
542 fragsort[j] = fragsort[j+1];
548 // calculate team scores
550 for (i=0 ; i<scoreboardlines ; i++)
552 if (color != cl.scores[fragsort[i]].colors)
554 color = cl.scores[fragsort[i]].colors;
556 strcpy(teams[teamlines-1].name, "Total Team Score");
557 teams[teamlines-1].frags = 0;
558 teams[teamlines-1].colors = cl.scores[fragsort[i]].colors;
561 if (cl.scores[fragsort[i]].frags != -666)
563 // do not add spedcators
564 // (ugly hack for nexuiz)
565 teams[teamlines-1].frags += cl.scores[fragsort[i]].frags;
569 // now sort teams by scores.
570 for (i=0 ; i<teamlines ; i++)
572 for (i=0 ; i<teamlines ; i++)
574 for (j=0 ; j<teamlines-1-i ; j++)
576 if (teams[teamsort[j]].frags < teams[teamsort[j+1]].frags)
579 teamsort[j] = teamsort[j+1];
592 void Sbar_SoloScoreboard (void)
595 int minutes, seconds, tens, units;
598 if (gamemode != GAME_NEXUIZ) {
599 sprintf (str,"Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
600 Sbar_DrawString (8, 4, str);
602 sprintf (str,"Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
603 Sbar_DrawString (8, 12, str);
607 minutes = cl.time / 60;
608 seconds = cl.time - 60*minutes;
610 units = seconds - 10*tens;
611 sprintf (str,"Time :%3i:%i%i", minutes, tens, units);
612 Sbar_DrawString (184, 4, str);
615 if (gamemode == GAME_NEXUIZ) {
616 l = (int) strlen (cl.worldmodel->name);
617 Sbar_DrawString (232 - l*4, 12, cl.worldmodel->name);
619 l = (int) strlen (cl.levelname);
620 Sbar_DrawString (232 - l*4, 12, cl.levelname);
629 void Sbar_DrawScoreboard (void)
631 Sbar_SoloScoreboard ();
632 if (cl.gametype == GAME_DEATHMATCH)
633 Sbar_DeathmatchOverlay ();
636 //=============================================================================
638 // AK to make DrawInventory smaller
639 static void Sbar_DrawWeapon(int nr, float fade, int active)
641 // width = 300, height = 100
642 const int w_width = 300, w_height = 100, w_space = 10;
643 const float w_scale = 0.4;
645 DrawQ_Pic(vid_conwidth.integer - (w_width + w_space) * w_scale, (w_height + w_space) * w_scale * nr + w_space, sb_weapons[0][nr]->name, 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);
646 //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);
649 DrawQ_Fill(vid_conwidth.integer - (w_width + w_space) * w_scale, (w_height + w_space) * w_scale * nr + w_space, w_width * w_scale, w_height * w_scale, 0.3, 0.3, 0.3, fade * sbar_alpha_fg.value, DRAWFLAG_ADDITIVE);
657 void Sbar_DrawInventory (void)
664 if (gamemode == GAME_ROGUE)
666 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
667 Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], sbar_alpha_bg.value);
669 Sbar_DrawAlphaPic (0, -24, rsb_invbar[1], sbar_alpha_bg.value);
672 Sbar_DrawAlphaPic (0, -24, sb_ibar, sbar_alpha_bg.value);
675 for (i=0 ; i<7 ; i++)
677 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<i) )
679 time = cl.item_gettime[i];
680 flashon = (int)((cl.time - time)*10);
683 if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i) )
689 flashon = (flashon%5) + 2;
691 Sbar_DrawAlphaPic (i*24, -16, sb_weapons[flashon][i], sbar_alpha_bg.value);
697 if (gamemode == GAME_HIPNOTIC)
699 int grenadeflashing=0;
700 for (i=0 ; i<4 ; i++)
702 if (cl.stats[STAT_ITEMS] & (1<<hipweapons[i]) )
704 time = cl.item_gettime[hipweapons[i]];
705 flashon = (int)((cl.time - time)*10);
708 if ( cl.stats[STAT_ACTIVEWEAPON] == (1<<hipweapons[i]) )
714 flashon = (flashon%5) + 2;
716 // check grenade launcher
719 if (cl.stats[STAT_ITEMS] & HIT_PROXIMITY_GUN)
724 Sbar_DrawPic (96, -16, hsb_weapons[flashon][2]);
730 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<4))
732 if (!grenadeflashing)
733 Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
736 Sbar_DrawPic (96, -16, hsb_weapons[flashon][4]);
739 Sbar_DrawPic (176 + (i*24), -16, hsb_weapons[flashon][i]);
744 if (gamemode == GAME_ROGUE)
746 // check for powered up weapon.
747 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
749 if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i))
750 Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]);
754 for (i=0 ; i<4 ; i++)
756 sprintf (num, "%3i",cl.stats[STAT_SHELLS+i] );
758 Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[0] - '0');
760 Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[1] - '0');
762 Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0');
766 for (i=0 ; i<6 ; i++)
767 if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
769 //MED 01/04/97 changed keys
770 if (gamemode != GAME_HIPNOTIC || (i>1))
771 Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
774 //MED 01/04/97 added hipnotic items
776 if (gamemode == GAME_HIPNOTIC)
778 for (i=0 ; i<2 ; i++)
779 if (cl.stats[STAT_ITEMS] & (1<<(24+i)))
780 Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
783 if (gamemode == GAME_ROGUE)
786 for (i=0 ; i<2 ; i++)
787 if (cl.stats[STAT_ITEMS] & (1<<(29+i)))
788 Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
793 for (i=0 ; i<4 ; i++)
794 if (cl.stats[STAT_ITEMS] & (1<<(28+i)))
795 Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
799 //=============================================================================
806 void Sbar_DrawFrags (void)
816 l = min(scoreboardlines, 4);
820 for (i = 0;i < l;i++)
826 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
827 DrawQ_Fill (sbar_x + x + 10, sbar_y - 23, 28, 4, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
828 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
829 DrawQ_Fill (sbar_x + x + 10, sbar_y + 4 - 23, 28, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
833 sprintf (num, "%3i",f);
835 if (k == cl.viewentity - 1)
837 Sbar_DrawCharacter ( x + 2, -24, 16);
838 Sbar_DrawCharacter ( x + 32 - 4, -24, 17);
840 Sbar_DrawCharacter (x + 8, -24, num[0]);
841 Sbar_DrawCharacter (x + 16, -24, num[1]);
842 Sbar_DrawCharacter (x + 24, -24, num[2]);
847 //=============================================================================
855 void Sbar_DrawFace (void)
859 // PGM 01/19/97 - team color drawing
860 // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
861 if (gamemode == GAME_ROGUE && !cl.islocalgame && (teamplay.integer > 3) && (teamplay.integer < 7))
867 s = &cl.scores[cl.viewentity - 1];
869 Sbar_DrawPic (112, 0, rsb_teambord);
870 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
871 DrawQ_Fill (sbar_x + 113, vid_conheight.integer-SBAR_HEIGHT+3, 22, 9, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
872 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
873 DrawQ_Fill (sbar_x + 113, vid_conheight.integer-SBAR_HEIGHT+12, 22, 9, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
877 sprintf (num, "%3i",f);
879 if ((s->colors & 0xf0)==0)
882 Sbar_DrawCharacter(109, 3, 18 + num[0] - '0');
884 Sbar_DrawCharacter(116, 3, 18 + num[1] - '0');
886 Sbar_DrawCharacter(123, 3, 18 + num[2] - '0');
890 Sbar_DrawCharacter ( 109, 3, num[0]);
891 Sbar_DrawCharacter ( 116, 3, num[1]);
892 Sbar_DrawCharacter ( 123, 3, num[2]);
897 // PGM 01/19/97 - team color drawing
899 if ( (cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
900 Sbar_DrawPic (112, 0, sb_face_invis_invuln);
901 else if (cl.stats[STAT_ITEMS] & IT_QUAD)
902 Sbar_DrawPic (112, 0, sb_face_quad );
903 else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
904 Sbar_DrawPic (112, 0, sb_face_invis );
905 else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
906 Sbar_DrawPic (112, 0, sb_face_invuln);
909 f = cl.stats[STAT_HEALTH] / 20;
911 Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]);
915 void Sbar_ShowFPS(void)
917 float fps_x, fps_y, fps_scalex, fps_scaley, fps_height;
921 qboolean red = false;
928 if (showfps.integer > 1)
930 static double currtime, frametimes[32];
931 double newtime, total;
933 static int framecycle = 0;
935 newtime = Sys_DoubleTime();
936 frametimes[framecycle] = newtime - currtime;
939 while(total < 0.2 && count < 32 && frametimes[i = (framecycle - count) & 31])
941 total += frametimes[i];
946 if (showfps.integer == 2)
947 calc = (((double)count / total) + 0.5);
948 else // showfps 3, rapid update
949 calc = ((1.0 / (newtime - currtime)) + 0.5);
954 static double nexttime = 0, lasttime = 0;
955 static float framerate = 0;
956 static int framecount = 0;
958 newtime = Sys_DoubleTime();
959 if (newtime >= nexttime)
961 framerate = ((float)framecount / (newtime - lasttime) + 0.5);
963 nexttime = max(nexttime + 1, lasttime - 1);
970 if ((red = (calc < 1.0f)))
971 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0f / calc + 0.5));
973 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(calc + 0.5));
975 if (showtime.integer)
976 strlcpy(timestring, Sys_TimeString(showtime_format.string), sizeof(timestring));
977 if (showdate.integer)
978 strlcpy(datestring, Sys_TimeString(showdate_format.string), sizeof(datestring));
979 if (fpsstring[0] || timestring[0])
983 fps_height = fps_scaley * ((fpsstring[0] != 0) + (timestring[0] != 0) + (datestring[0] != 0));
984 //fps_y = vid_conheight.integer - sb_lines; // yes this may draw over the sbar
985 //fps_y = bound(0, fps_y, vid_conheight.integer - fps_height);
986 fps_y = vid_conheight.integer - fps_height;
989 fps_x = vid_conwidth.integer - fps_scalex * strlen(fpsstring);
990 DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(fpsstring), fps_scaley, 0, 0, 0, 0.5, 0);
992 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 0, 0, 1, 0);
994 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
999 fps_x = vid_conwidth.integer - fps_scalex * strlen(timestring);
1000 DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(timestring), fps_scaley, 0, 0, 0, 0.5, 0);
1001 DrawQ_String(fps_x, fps_y, timestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
1002 fps_y += fps_scaley;
1006 fps_x = vid_conwidth.integer - fps_scalex * strlen(datestring);
1007 DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(datestring), fps_scaley, 0, 0, 0, 0.5, 0);
1008 DrawQ_String(fps_x, fps_y, datestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
1009 fps_y += fps_scaley;
1014 void Sbar_DrawGauge(float x, float y, const char *picname, 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)
1017 c2 = bound(0, c2, 1);
1018 c1 = bound(0, c1, 1 - c2);
1020 r[1] = rangey + rangeheight * (c2 + c1);
1021 r[2] = rangey + rangeheight * (c2);
1025 DrawQ_SuperPic(x, y + r[0], picname, 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);
1027 DrawQ_SuperPic(x, y + r[1], picname, 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);
1029 DrawQ_SuperPic(x, y + r[2], picname, 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);
1031 DrawQ_SuperPic(x, y + r[3], picname, 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);
1039 extern float v_dmg_time, v_dmg_roll, v_dmg_pitch;
1040 extern cvar_t v_kicktime;
1041 void Sbar_Draw (void)
1043 if(cl.csqc_vidvars.drawenginesbar) //[515]: csqc drawsbar
1045 if (cl.intermission == 1)
1047 Sbar_IntermissionOverlay();
1050 else if (cl.intermission == 2)
1052 Sbar_FinaleOverlay();
1056 if (gamemode == GAME_NETHERWORLD)
1059 else if (gamemode == GAME_SOM)
1061 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1062 Sbar_DrawScoreboard ();
1065 // this is the top left of the sbar area
1067 sbar_y = vid_conheight.integer - 24*3;
1070 if (cl.stats[STAT_ARMOR])
1072 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1073 Sbar_DrawPic(0, 0, somsb_armor[2]);
1074 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1075 Sbar_DrawPic(0, 0, somsb_armor[1]);
1076 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1077 Sbar_DrawPic(0, 0, somsb_armor[0]);
1078 Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1082 Sbar_DrawPic(0, 24, somsb_health);
1083 Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1086 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1087 Sbar_DrawPic(0, 48, somsb_ammo[0]);
1088 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1089 Sbar_DrawPic(0, 48, somsb_ammo[1]);
1090 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1091 Sbar_DrawPic(0, 48, somsb_ammo[2]);
1092 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1093 Sbar_DrawPic(0, 48, somsb_ammo[3]);
1094 Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
1095 if (cl.stats[STAT_SHELLS])
1096 Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
1099 else if (gamemode == GAME_NEXUIZ)
1101 sbar_y = vid_conheight.integer - 47;
1102 sbar_x = (vid_conwidth.integer - 640)/2;
1104 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1106 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1107 Sbar_DrawScoreboard ();
1115 // we have a max time 2s (min time = 0)
1116 if ((time = cl.time - cl.weapontime) < 2)
1118 fade = (1.0 - 0.5 * time);
1120 for (i = 0; i < 8;i++)
1121 if (cl.stats[STAT_ITEMS] & (1 << i))
1122 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1124 if((cl.stats[STAT_ITEMS] & (1<<12)))
1125 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1128 //if (!cl.islocalgame)
1129 // Sbar_DrawFrags ();
1132 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1134 Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1137 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1139 // Nexuiz has no anum pics
1140 //Sbar_DrawNum (36, 0, 666, 3, 1);
1141 // Nexuiz has no disc pic
1142 //Sbar_DrawPic (0, 0, sb_disc);
1146 Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1149 if(cl.stats[STAT_HEALTH] > 100)
1150 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1151 else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1152 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1154 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1156 // AK dont draw ammo for the laser
1157 if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1159 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1160 Sbar_DrawPic (519, 0, sb_ammo[0]);
1161 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1162 Sbar_DrawPic (519, 0, sb_ammo[1]);
1163 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1164 Sbar_DrawPic (519, 0, sb_ammo[2]);
1165 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1166 Sbar_DrawPic (519, 0, sb_ammo[3]);
1168 if(cl.stats[STAT_AMMO] <= 10)
1169 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1171 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1176 DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay->name,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1179 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1180 // Sbar_MiniDeathmatchOverlay (0, 17);
1182 else if (gamemode == GAME_ZYMOTIC)
1185 float scale = 64.0f / 256.0f;
1186 float kickoffset[3];
1187 VectorClear(kickoffset);
1190 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1191 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1193 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1194 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1195 // left1 16, 48 : 126 -66
1196 // left2 16, 128 : 196 -66
1197 // right 176, 48 : 196 -136
1198 Sbar_DrawGauge(sbar_x + 16 * scale, sbar_y + 48 * scale, zymsb_crosshair_left1->name, 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);
1199 Sbar_DrawGauge(sbar_x + 16 * scale, sbar_y + 128 * scale, zymsb_crosshair_left2->name, 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);
1200 Sbar_DrawGauge(sbar_x + 176 * scale, sbar_y + 48 * scale, zymsb_crosshair_right->name, 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);
1201 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center->name, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1203 float scale = 128.0f / 256.0f;
1204 float healthstart, healthheight, healthstarttc, healthendtc;
1205 float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1206 float ammostart, ammoheight, ammostarttc, ammoendtc;
1207 float clipstart, clipheight, clipstarttc, clipendtc;
1208 float kickoffset[3], offset;
1209 VectorClear(kickoffset);
1212 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1213 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1215 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1216 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1217 offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1218 DrawQ_SuperPic(sbar_x + 120 * scale, sbar_y + ( 88 - offset) * scale, zymsb_crosshair_line->name, 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);
1219 DrawQ_SuperPic(sbar_x + (132 + offset) * scale, sbar_y + 120 * scale, zymsb_crosshair_line->name, 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);
1220 DrawQ_SuperPic(sbar_x + 120 * scale, sbar_y + (132 + offset) * scale, zymsb_crosshair_line->name, 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);
1221 DrawQ_SuperPic(sbar_x + ( 88 - offset) * scale, sbar_y + 120 * scale, zymsb_crosshair_line->name, 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);
1222 healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1223 shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1224 healthstart = 204 - healthheight;
1225 shieldstart = healthstart - shieldheight;
1226 healthstarttc = healthstart * (1.0f / 256.0f);
1227 healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1228 shieldstarttc = shieldstart * (1.0f / 256.0f);
1229 shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1230 ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1231 ammostart = 114 - ammoheight;
1232 ammostarttc = ammostart * (1.0f / 256.0f);
1233 ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1234 clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1235 clipstart = 190 - clipheight;
1236 clipstarttc = clipstart * (1.0f / 256.0f);
1237 clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1238 if (healthheight > 0) DrawQ_SuperPic(sbar_x + 0 * scale, sbar_y + healthstart * scale, zymsb_crosshair_health->name, 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);
1239 if (shieldheight > 0) DrawQ_SuperPic(sbar_x + 0 * scale, sbar_y + shieldstart * scale, zymsb_crosshair_health->name, 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);
1240 if (ammoheight > 0) DrawQ_SuperPic(sbar_x + 0 * scale, sbar_y + ammostart * scale, zymsb_crosshair_ammo->name, 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);
1241 if (clipheight > 0) DrawQ_SuperPic(sbar_x + 0 * scale, sbar_y + clipstart * scale, zymsb_crosshair_clip->name, 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);
1242 DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background->name, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1243 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center->name, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1246 else // Quake and others
1248 sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1249 if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1252 sbar_x = (vid_conwidth.integer - 320)/2;
1256 if (gamemode != GAME_GOODVSBAD2)
1257 Sbar_DrawInventory ();
1258 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1262 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1264 if (gamemode != GAME_GOODVSBAD2)
1265 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1266 Sbar_DrawScoreboard ();
1270 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1272 // keys (hipnotic only)
1273 //MED 01/04/97 moved keys here so they would not be overwritten
1274 if (gamemode == GAME_HIPNOTIC)
1276 if (cl.stats[STAT_ITEMS] & IT_KEY1)
1277 Sbar_DrawPic (209, 3, sb_items[0]);
1278 if (cl.stats[STAT_ITEMS] & IT_KEY2)
1279 Sbar_DrawPic (209, 12, sb_items[1]);
1282 if (gamemode != GAME_GOODVSBAD2)
1284 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1286 Sbar_DrawNum (24, 0, 666, 3, 1);
1287 Sbar_DrawPic (0, 0, sb_disc);
1291 if (gamemode == GAME_ROGUE)
1293 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1294 if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1295 Sbar_DrawPic (0, 0, sb_armor[2]);
1296 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1297 Sbar_DrawPic (0, 0, sb_armor[1]);
1298 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1299 Sbar_DrawPic (0, 0, sb_armor[0]);
1303 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1304 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1305 Sbar_DrawPic (0, 0, sb_armor[2]);
1306 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1307 Sbar_DrawPic (0, 0, sb_armor[1]);
1308 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1309 Sbar_DrawPic (0, 0, sb_armor[0]);
1318 Sbar_DrawNum (154, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1321 if (gamemode == GAME_ROGUE)
1323 if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1324 Sbar_DrawPic (224, 0, sb_ammo[0]);
1325 else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1326 Sbar_DrawPic (224, 0, sb_ammo[1]);
1327 else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1328 Sbar_DrawPic (224, 0, sb_ammo[2]);
1329 else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1330 Sbar_DrawPic (224, 0, sb_ammo[3]);
1331 else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1332 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1333 else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1334 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1335 else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1336 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1340 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1341 Sbar_DrawPic (224, 0, sb_ammo[0]);
1342 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1343 Sbar_DrawPic (224, 0, sb_ammo[1]);
1344 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1345 Sbar_DrawPic (224, 0, sb_ammo[2]);
1346 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1347 Sbar_DrawPic (224, 0, sb_ammo[3]);
1350 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1354 if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1356 if (gamemode == GAME_TRANSFUSION)
1357 Sbar_MiniDeathmatchOverlay (0, 0);
1359 Sbar_MiniDeathmatchOverlay (324, vid_conheight.integer - sb_lines);
1366 if(cl.csqc_vidvars.drawcrosshair)
1367 R_Draw2DCrosshair();
1369 if (cl_prydoncursor.integer)
1370 DrawQ_Pic((cl.cmd.cursor_screen[0] + 1) * 0.5 * vid_conwidth.integer, (cl.cmd.cursor_screen[1] + 1) * 0.5 * vid_conheight.integer, va("gfx/prydoncursor%03i", cl_prydoncursor.integer), 0, 0, 1, 1, 1, 1, 0);
1373 //=============================================================================
1377 Sbar_DeathmatchOverlay
1381 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1384 // draw colors behind score
1385 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1386 DrawQ_Fill(x + 8, y+1, 32, 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);
1387 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1388 DrawQ_Fill(x + 8, y+4, 32, 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);
1390 //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);
1391 // FIXME: use a constant for this color tag instead
1392 DrawQ_ColoredString(x, y, va("%c%4i %s" STRING_COLOR_DEFAULT_STR, (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1396 void Sbar_DeathmatchOverlay (void)
1401 pic = Draw_CachePic ("gfx/ranking", true);
1402 DrawQ_Pic ((vid_conwidth.integer - pic->width)/2, 8, "gfx/ranking", 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1407 x = (vid_conwidth.integer - (6 + 15) * 8) / 2;
1410 if (Sbar_IsTeammatch ())
1412 // show team scores first
1413 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1414 y += Sbar_PrintScoreboardItem((teams + teamsort[i]), x, y);
1418 for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1419 y += Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1424 Sbar_DeathmatchOverlay
1428 void Sbar_MiniDeathmatchOverlay (int x, int y)
1432 // decide where to print
1433 if (gamemode == GAME_TRANSFUSION)
1434 numlines = (vid_conwidth.integer - x + 127) / 128;
1436 numlines = (vid_conheight.integer - y + 7) / 8;
1438 // give up if there isn't room
1439 if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1446 for (i = 0; i < scoreboardlines; i++)
1447 if (fragsort[i] == cl.playerentity - 1)
1452 i = min(i, scoreboardlines - numlines);
1455 if (gamemode == GAME_TRANSFUSION)
1457 for (;i < scoreboardlines && x < vid_conwidth.integer;i++)
1458 x += 128 + Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1462 for (;i < scoreboardlines && y < vid_conheight.integer;i++)
1463 y += Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1469 Sbar_IntermissionOverlay
1473 void Sbar_IntermissionOverlay (void)
1478 if (cl.gametype == GAME_DEATHMATCH)
1480 Sbar_DeathmatchOverlay ();
1484 sbar_x = (vid_conwidth.integer - 320) >> 1;
1485 sbar_y = (vid_conheight.integer - 200) >> 1;
1487 DrawQ_Pic (sbar_x + 64, sbar_y + 24, "gfx/complete", 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1488 DrawQ_Pic (sbar_x + 0, sbar_y + 56, "gfx/inter", 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1491 dig = cl.completed_time/60;
1492 Sbar_DrawNum (160, 64, dig, 3, 0);
1493 num = cl.completed_time - dig*60;
1494 if (gamemode != GAME_NEXUIZ)
1495 Sbar_DrawPic (234,64,sb_colon);
1496 Sbar_DrawPic (246,64,sb_nums[0][num/10]);
1497 Sbar_DrawPic (266,64,sb_nums[0][num%10]);
1499 Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
1500 if (gamemode != GAME_NEXUIZ)
1501 Sbar_DrawPic (232, 104, sb_slash);
1502 Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1504 Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1505 if (gamemode != GAME_NEXUIZ)
1506 Sbar_DrawPic (232, 144, sb_slash);
1507 Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1518 void Sbar_FinaleOverlay (void)
1522 pic = Draw_CachePic ("gfx/finale", true);
1523 DrawQ_Pic((vid_conwidth.integer - pic->width)/2, 16, "gfx/finale", 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);