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"};
103 cvar_t showtime = {CVAR_SAVE, "showtime", "0"};
104 cvar_t showtime_format = {CVAR_SAVE, "showtime_format", "%H:%M:%S"};
105 cvar_t showdate = {CVAR_SAVE, "showdate", "0"};
106 cvar_t showdate_format = {CVAR_SAVE, "showdate_format", "%Y-%m-%d"};
107 cvar_t sbar_alpha_bg = {CVAR_SAVE, "sbar_alpha_bg", "0.4"};
108 cvar_t sbar_alpha_fg = {CVAR_SAVE, "sbar_alpha_fg", "1"};
110 cvar_t cl_deathscoreboard = {0, "cl_deathscoreboard", "1"};
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);
351 Cmd_AddCommand ("-showscores", Sbar_DontShowScores);
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;
488 static scoreboard_t teams[MAX_SCOREBOARD];
489 static int teamsort[MAX_SCOREBOARD];
490 static int teamlines;
491 void Sbar_SortFrags (void)
497 for (i=0 ; i<cl.maxclients ; i++)
499 if (cl.scores[i].name[0])
501 fragsort[scoreboardlines] = i;
506 for (i=0 ; i<scoreboardlines ; i++)
507 for (j=0 ; j<scoreboardlines-1-i ; j++)
508 if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j+1]].frags)
511 fragsort[j] = fragsort[j+1];
516 if (Sbar_IsTeammatch ())
518 // now sort players by teams.
519 for (i=0 ; i<scoreboardlines ; i++)
521 for (j=0 ; j<scoreboardlines-1-i ; j++)
523 if (cl.scores[fragsort[j]].colors < cl.scores[fragsort[j+1]].colors)
526 fragsort[j] = fragsort[j+1];
532 // calculate team scores
534 for (i=0 ; i<scoreboardlines ; i++)
536 if (color != cl.scores[fragsort[i]].colors)
538 color = cl.scores[fragsort[i]].colors;
540 strcpy(teams[teamlines-1].name, "Total Team Score");
541 teams[teamlines-1].frags = 0;
542 teams[teamlines-1].colors = cl.scores[fragsort[i]].colors;
545 if (cl.scores[fragsort[i]].frags != -666)
547 // do not add spedcators
548 // (ugly hack for nexuiz)
549 teams[teamlines-1].frags += cl.scores[fragsort[i]].frags;
553 // now sort teams by scores.
554 for (i=0 ; i<teamlines ; i++)
556 for (i=0 ; i<teamlines ; i++)
558 for (j=0 ; j<teamlines-1-i ; j++)
560 if (teams[teamsort[j]].frags < teams[teamsort[j+1]].frags)
563 teamsort[j] = teamsort[j+1];
576 void Sbar_SoloScoreboard (void)
579 int minutes, seconds, tens, units;
582 if (gamemode != GAME_NEXUIZ) {
583 sprintf (str,"Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
584 Sbar_DrawString (8, 4, str);
586 sprintf (str,"Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
587 Sbar_DrawString (8, 12, str);
591 minutes = cl.time / 60;
592 seconds = cl.time - 60*minutes;
594 units = seconds - 10*tens;
595 sprintf (str,"Time :%3i:%i%i", minutes, tens, units);
596 Sbar_DrawString (184, 4, str);
599 if (gamemode == GAME_NEXUIZ) {
600 l = (int) strlen (cl.worldmodel->name);
601 Sbar_DrawString (232 - l*4, 12, cl.worldmodel->name);
603 l = (int) strlen (cl.levelname);
604 Sbar_DrawString (232 - l*4, 12, cl.levelname);
613 void Sbar_DrawScoreboard (void)
615 Sbar_SoloScoreboard ();
616 if (cl.gametype == GAME_DEATHMATCH)
617 Sbar_DeathmatchOverlay ();
620 //=============================================================================
622 // AK to make DrawInventory smaller
623 static void Sbar_DrawWeapon(int nr, float fade, int active)
625 // width = 300, height = 100
626 const int w_width = 300, w_height = 100, w_space = 10;
627 const float w_scale = 0.4;
629 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);
630 //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);
633 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);
641 void Sbar_DrawInventory (void)
648 if (gamemode == GAME_ROGUE)
650 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
651 Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], sbar_alpha_bg.value);
653 Sbar_DrawAlphaPic (0, -24, rsb_invbar[1], sbar_alpha_bg.value);
656 Sbar_DrawAlphaPic (0, -24, sb_ibar, sbar_alpha_bg.value);
659 for (i=0 ; i<7 ; i++)
661 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<i) )
663 time = cl.item_gettime[i];
664 flashon = (int)((cl.time - time)*10);
667 if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i) )
673 flashon = (flashon%5) + 2;
675 Sbar_DrawAlphaPic (i*24, -16, sb_weapons[flashon][i], sbar_alpha_bg.value);
681 if (gamemode == GAME_HIPNOTIC)
683 int grenadeflashing=0;
684 for (i=0 ; i<4 ; i++)
686 if (cl.stats[STAT_ITEMS] & (1<<hipweapons[i]) )
688 time = cl.item_gettime[hipweapons[i]];
689 flashon = (int)((cl.time - time)*10);
692 if ( cl.stats[STAT_ACTIVEWEAPON] == (1<<hipweapons[i]) )
698 flashon = (flashon%5) + 2;
700 // check grenade launcher
703 if (cl.stats[STAT_ITEMS] & HIT_PROXIMITY_GUN)
708 Sbar_DrawPic (96, -16, hsb_weapons[flashon][2]);
714 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<4))
716 if (!grenadeflashing)
717 Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
720 Sbar_DrawPic (96, -16, hsb_weapons[flashon][4]);
723 Sbar_DrawPic (176 + (i*24), -16, hsb_weapons[flashon][i]);
728 if (gamemode == GAME_ROGUE)
730 // check for powered up weapon.
731 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
733 if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i))
734 Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]);
738 for (i=0 ; i<4 ; i++)
740 sprintf (num, "%3i",cl.stats[STAT_SHELLS+i] );
742 Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[0] - '0');
744 Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[1] - '0');
746 Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0');
750 for (i=0 ; i<6 ; i++)
751 if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
753 //MED 01/04/97 changed keys
754 if (gamemode != GAME_HIPNOTIC || (i>1))
755 Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
758 //MED 01/04/97 added hipnotic items
760 if (gamemode == GAME_HIPNOTIC)
762 for (i=0 ; i<2 ; i++)
763 if (cl.stats[STAT_ITEMS] & (1<<(24+i)))
764 Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
767 if (gamemode == GAME_ROGUE)
770 for (i=0 ; i<2 ; i++)
771 if (cl.stats[STAT_ITEMS] & (1<<(29+i)))
772 Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
777 for (i=0 ; i<4 ; i++)
778 if (cl.stats[STAT_ITEMS] & (1<<(28+i)))
779 Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
783 //=============================================================================
790 void Sbar_DrawFrags (void)
800 l = min(scoreboardlines, 4);
804 for (i = 0;i < l;i++)
810 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
811 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);
812 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
813 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);
817 sprintf (num, "%3i",f);
819 if (k == cl.viewentity - 1)
821 Sbar_DrawCharacter ( x + 2, -24, 16);
822 Sbar_DrawCharacter ( x + 32 - 4, -24, 17);
824 Sbar_DrawCharacter (x + 8, -24, num[0]);
825 Sbar_DrawCharacter (x + 16, -24, num[1]);
826 Sbar_DrawCharacter (x + 24, -24, num[2]);
831 //=============================================================================
839 void Sbar_DrawFace (void)
843 // PGM 01/19/97 - team color drawing
844 // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
845 if (gamemode == GAME_ROGUE && !cl.islocalgame && (teamplay.integer > 3) && (teamplay.integer < 7))
851 s = &cl.scores[cl.viewentity - 1];
853 Sbar_DrawPic (112, 0, rsb_teambord);
854 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
855 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);
856 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
857 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);
861 sprintf (num, "%3i",f);
863 if ((s->colors & 0xf0)==0)
866 Sbar_DrawCharacter(109, 3, 18 + num[0] - '0');
868 Sbar_DrawCharacter(116, 3, 18 + num[1] - '0');
870 Sbar_DrawCharacter(123, 3, 18 + num[2] - '0');
874 Sbar_DrawCharacter ( 109, 3, num[0]);
875 Sbar_DrawCharacter ( 116, 3, num[1]);
876 Sbar_DrawCharacter ( 123, 3, num[2]);
881 // PGM 01/19/97 - team color drawing
883 if ( (cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
884 Sbar_DrawPic (112, 0, sb_face_invis_invuln);
885 else if (cl.stats[STAT_ITEMS] & IT_QUAD)
886 Sbar_DrawPic (112, 0, sb_face_quad );
887 else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
888 Sbar_DrawPic (112, 0, sb_face_invis );
889 else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
890 Sbar_DrawPic (112, 0, sb_face_invuln);
893 f = cl.stats[STAT_HEALTH] / 20;
895 Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]);
899 void Sbar_ShowFPS(void)
901 float fps_x, fps_y, fps_scalex, fps_scaley, fps_height;
905 qboolean red = false;
912 if (showfps.integer > 1)
914 static double currtime, frametimes[32];
915 double newtime, total;
917 static int framecycle = 0;
919 newtime = Sys_DoubleTime();
920 frametimes[framecycle] = newtime - currtime;
923 while(total < 0.2 && count < 32 && frametimes[i = (framecycle - count) & 31])
925 total += frametimes[i];
930 if (showfps.integer == 2)
931 calc = (((double)count / total) + 0.5);
932 else // showfps 3, rapid update
933 calc = ((1.0 / (newtime - currtime)) + 0.5);
938 static double nexttime = 0, lasttime = 0;
939 static float framerate = 0;
940 static int framecount = 0;
942 newtime = Sys_DoubleTime();
943 if (newtime >= nexttime)
945 framerate = ((float)framecount / (newtime - lasttime) + 0.5);
947 nexttime = max(nexttime + 1, lasttime - 1);
954 if ((red = (calc < 1.0f)))
955 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0f / calc + 0.5));
957 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(calc + 0.5));
959 if (showtime.integer)
960 strlcpy(timestring, Sys_TimeString(showtime_format.string), sizeof(timestring));
961 if (showdate.integer)
962 strlcpy(datestring, Sys_TimeString(showdate_format.string), sizeof(datestring));
963 if (fpsstring[0] || timestring[0])
967 fps_height = fps_scaley * ((fpsstring[0] != 0) + (timestring[0] != 0) + (datestring[0] != 0));
968 //fps_y = vid_conheight.integer - sb_lines; // yes this may draw over the sbar
969 //fps_y = bound(0, fps_y, vid_conheight.integer - fps_height);
970 fps_y = vid_conheight.integer - fps_height;
973 fps_x = vid_conwidth.integer - fps_scalex * strlen(fpsstring);
974 DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(fpsstring), fps_scaley, 0, 0, 0, 0.5, 0);
976 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 0, 0, 1, 0);
978 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
983 fps_x = vid_conwidth.integer - fps_scalex * strlen(timestring);
984 DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(timestring), fps_scaley, 0, 0, 0, 0.5, 0);
985 DrawQ_String(fps_x, fps_y, timestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
990 fps_x = vid_conwidth.integer - fps_scalex * strlen(datestring);
991 DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(datestring), fps_scaley, 0, 0, 0, 0.5, 0);
992 DrawQ_String(fps_x, fps_y, datestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
998 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)
1001 c2 = bound(0, c2, 1);
1002 c1 = bound(0, c1, 1 - c2);
1004 r[1] = rangey + rangeheight * (c2 + c1);
1005 r[2] = rangey + rangeheight * (c2);
1009 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);
1011 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);
1013 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);
1015 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);
1023 extern float v_dmg_time, v_dmg_roll, v_dmg_pitch;
1024 extern cvar_t v_kicktime;
1025 void Sbar_Draw (void)
1027 if (cl.intermission == 1)
1029 Sbar_IntermissionOverlay();
1032 else if (cl.intermission == 2)
1034 Sbar_FinaleOverlay();
1038 if (gamemode == GAME_NETHERWORLD)
1041 else if (gamemode == GAME_SOM)
1043 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1044 Sbar_DrawScoreboard ();
1047 // this is the top left of the sbar area
1049 sbar_y = vid_conheight.integer - 24*3;
1052 if (cl.stats[STAT_ARMOR])
1054 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1055 Sbar_DrawPic(0, 0, somsb_armor[2]);
1056 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1057 Sbar_DrawPic(0, 0, somsb_armor[1]);
1058 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1059 Sbar_DrawPic(0, 0, somsb_armor[0]);
1060 Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1064 Sbar_DrawPic(0, 24, somsb_health);
1065 Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1068 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1069 Sbar_DrawPic(0, 48, somsb_ammo[0]);
1070 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1071 Sbar_DrawPic(0, 48, somsb_ammo[1]);
1072 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1073 Sbar_DrawPic(0, 48, somsb_ammo[2]);
1074 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1075 Sbar_DrawPic(0, 48, somsb_ammo[3]);
1076 Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
1077 if (cl.stats[STAT_SHELLS])
1078 Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
1081 else if (gamemode == GAME_NEXUIZ)
1083 sbar_y = vid_conheight.integer - 47;
1084 sbar_x = (vid_conwidth.integer - 640)/2;
1086 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1088 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1089 Sbar_DrawScoreboard ();
1097 // we have a max time 2s (min time = 0)
1098 if ((time = cl.time - cl.weapontime) < 2)
1100 fade = (1.0 - 0.5 * time);
1102 for (i = 0; i < 8;i++)
1103 if (cl.stats[STAT_ITEMS] & (1 << i))
1104 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1106 if((cl.stats[STAT_ITEMS] & (1<<12)))
1107 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1110 //if (!cl.islocalgame)
1111 // Sbar_DrawFrags ();
1114 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1116 Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1119 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1121 // Nexuiz has no anum pics
1122 //Sbar_DrawNum (36, 0, 666, 3, 1);
1123 // Nexuiz has no disc pic
1124 //Sbar_DrawPic (0, 0, sb_disc);
1128 Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1131 if(cl.stats[STAT_HEALTH] > 100)
1132 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1133 else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1134 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1136 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1138 // AK dont draw ammo for the laser
1139 if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1141 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1142 Sbar_DrawPic (519, 0, sb_ammo[0]);
1143 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1144 Sbar_DrawPic (519, 0, sb_ammo[1]);
1145 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1146 Sbar_DrawPic (519, 0, sb_ammo[2]);
1147 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1148 Sbar_DrawPic (519, 0, sb_ammo[3]);
1150 if(cl.stats[STAT_AMMO] <= 10)
1151 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1153 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1158 DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay->name,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1161 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1162 // Sbar_MiniDeathmatchOverlay (0, 17);
1164 else if (gamemode == GAME_ZYMOTIC)
1167 float scale = 64.0f / 256.0f;
1168 float kickoffset[3];
1169 VectorClear(kickoffset);
1172 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1173 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1175 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1176 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1177 // left1 16, 48 : 126 -66
1178 // left2 16, 128 : 196 -66
1179 // right 176, 48 : 196 -136
1180 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);
1181 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);
1182 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);
1183 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center->name, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1185 float scale = 128.0f / 256.0f;
1186 float healthstart, healthheight, healthstarttc, healthendtc;
1187 float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1188 float ammostart, ammoheight, ammostarttc, ammoendtc;
1189 float clipstart, clipheight, clipstarttc, clipendtc;
1190 float kickoffset[3], offset;
1191 VectorClear(kickoffset);
1194 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1195 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1197 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1198 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1199 offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1200 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);
1201 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);
1202 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);
1203 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);
1204 healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1205 shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1206 healthstart = 204 - healthheight;
1207 shieldstart = healthstart - shieldheight;
1208 healthstarttc = healthstart * (1.0f / 256.0f);
1209 healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1210 shieldstarttc = shieldstart * (1.0f / 256.0f);
1211 shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1212 ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1213 ammostart = 114 - ammoheight;
1214 ammostarttc = ammostart * (1.0f / 256.0f);
1215 ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1216 clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1217 clipstart = 190 - clipheight;
1218 clipstarttc = clipstart * (1.0f / 256.0f);
1219 clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1220 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);
1221 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);
1222 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);
1223 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);
1224 DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background->name, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1225 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center->name, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1228 else // Quake and others
1230 sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1231 if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1234 sbar_x = (vid_conwidth.integer - 320)/2;
1238 if (gamemode != GAME_GOODVSBAD2)
1239 Sbar_DrawInventory ();
1240 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1244 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1246 if (gamemode != GAME_GOODVSBAD2)
1247 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1248 Sbar_DrawScoreboard ();
1252 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1254 // keys (hipnotic only)
1255 //MED 01/04/97 moved keys here so they would not be overwritten
1256 if (gamemode == GAME_HIPNOTIC)
1258 if (cl.stats[STAT_ITEMS] & IT_KEY1)
1259 Sbar_DrawPic (209, 3, sb_items[0]);
1260 if (cl.stats[STAT_ITEMS] & IT_KEY2)
1261 Sbar_DrawPic (209, 12, sb_items[1]);
1264 if (gamemode != GAME_GOODVSBAD2)
1266 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1268 Sbar_DrawNum (24, 0, 666, 3, 1);
1269 Sbar_DrawPic (0, 0, sb_disc);
1273 if (gamemode == GAME_ROGUE)
1275 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1276 if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1277 Sbar_DrawPic (0, 0, sb_armor[2]);
1278 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1279 Sbar_DrawPic (0, 0, sb_armor[1]);
1280 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1281 Sbar_DrawPic (0, 0, sb_armor[0]);
1285 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1286 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1287 Sbar_DrawPic (0, 0, sb_armor[2]);
1288 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1289 Sbar_DrawPic (0, 0, sb_armor[1]);
1290 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1291 Sbar_DrawPic (0, 0, sb_armor[0]);
1300 Sbar_DrawNum (154, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1303 if (gamemode == GAME_ROGUE)
1305 if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1306 Sbar_DrawPic (224, 0, sb_ammo[0]);
1307 else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1308 Sbar_DrawPic (224, 0, sb_ammo[1]);
1309 else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1310 Sbar_DrawPic (224, 0, sb_ammo[2]);
1311 else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1312 Sbar_DrawPic (224, 0, sb_ammo[3]);
1313 else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1314 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1315 else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1316 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1317 else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1318 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1322 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1323 Sbar_DrawPic (224, 0, sb_ammo[0]);
1324 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1325 Sbar_DrawPic (224, 0, sb_ammo[1]);
1326 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1327 Sbar_DrawPic (224, 0, sb_ammo[2]);
1328 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1329 Sbar_DrawPic (224, 0, sb_ammo[3]);
1332 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1336 if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1338 if (gamemode == GAME_TRANSFUSION)
1339 Sbar_MiniDeathmatchOverlay (0, 0);
1341 Sbar_MiniDeathmatchOverlay (324, vid_conheight.integer - sb_lines);
1347 R_Draw2DCrosshair();
1349 if (cl_prydoncursor.integer)
1350 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);
1353 //=============================================================================
1357 Sbar_DeathmatchOverlay
1361 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1364 // draw colors behind score
1365 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1366 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);
1367 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1368 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);
1370 //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);
1371 // FIXME: use a constant for this color tag instead
1372 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 );
1376 void Sbar_DeathmatchOverlay (void)
1381 pic = Draw_CachePic ("gfx/ranking", true);
1382 DrawQ_Pic ((vid_conwidth.integer - pic->width)/2, 8, "gfx/ranking", 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1387 x = (vid_conwidth.integer - (6 + 15) * 8) / 2;
1390 if (Sbar_IsTeammatch ())
1392 // show team scores first
1393 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1394 y += Sbar_PrintScoreboardItem((teams + teamsort[i]), x, y);
1398 for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1399 y += Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1404 Sbar_DeathmatchOverlay
1408 void Sbar_MiniDeathmatchOverlay (int x, int y)
1412 // decide where to print
1413 if (gamemode == GAME_TRANSFUSION)
1414 numlines = (vid_conwidth.integer - x + 127) / 128;
1416 numlines = (vid_conheight.integer - y + 7) / 8;
1418 // give up if there isn't room
1419 if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1426 for (i = 0; i < scoreboardlines; i++)
1427 if (fragsort[i] == cl.playerentity - 1)
1432 i = min(i, scoreboardlines - numlines);
1435 if (gamemode == GAME_TRANSFUSION)
1437 for (;i < scoreboardlines && x < vid_conwidth.integer;i++)
1438 x += 128 + Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1442 for (;i < scoreboardlines && y < vid_conheight.integer;i++)
1443 y += Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1449 Sbar_IntermissionOverlay
1453 void Sbar_IntermissionOverlay (void)
1458 if (cl.gametype == GAME_DEATHMATCH)
1460 Sbar_DeathmatchOverlay ();
1464 sbar_x = (vid_conwidth.integer - 320) >> 1;
1465 sbar_y = (vid_conheight.integer - 200) >> 1;
1467 DrawQ_Pic (sbar_x + 64, sbar_y + 24, "gfx/complete", 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1468 DrawQ_Pic (sbar_x + 0, sbar_y + 56, "gfx/inter", 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1471 dig = cl.completed_time/60;
1472 Sbar_DrawNum (160, 64, dig, 3, 0);
1473 num = cl.completed_time - dig*60;
1474 if (gamemode != GAME_NEXUIZ)
1475 Sbar_DrawPic (234,64,sb_colon);
1476 Sbar_DrawPic (246,64,sb_nums[0][num/10]);
1477 Sbar_DrawPic (266,64,sb_nums[0][num%10]);
1479 Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
1480 if (gamemode != GAME_NEXUIZ)
1481 Sbar_DrawPic (232, 104, sb_slash);
1482 Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1484 Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1485 if (gamemode != GAME_NEXUIZ)
1486 Sbar_DrawPic (232, 144, sb_slash);
1487 Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1498 void Sbar_FinaleOverlay (void)
1502 pic = Draw_CachePic ("gfx/finale", true);
1503 DrawQ_Pic((vid_conwidth.integer - pic->width)/2, 16, "gfx/finale", 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);