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_SOM)
152 sb_disc = Sbar_NewPic("gfx/disc");
154 for (i = 0;i < 10;i++)
155 sb_nums[0][i] = Sbar_NewPic (va("gfx/num_%i",i));
157 somsb_health = Sbar_NewPic("gfx/hud_health");
158 somsb_ammo[0] = Sbar_NewPic("gfx/sb_shells");
159 somsb_ammo[1] = Sbar_NewPic("gfx/sb_nails");
160 somsb_ammo[2] = Sbar_NewPic("gfx/sb_rocket");
161 somsb_ammo[3] = Sbar_NewPic("gfx/sb_cells");
162 somsb_armor[0] = Sbar_NewPic("gfx/sb_armor1");
163 somsb_armor[1] = Sbar_NewPic("gfx/sb_armor2");
164 somsb_armor[2] = Sbar_NewPic("gfx/sb_armor3");
166 else if (gamemode == GAME_NEXUIZ)
168 for (i = 0;i < 10;i++)
169 sb_nums[0][i] = Sbar_NewPic (va("gfx/num_%i",i));
170 sb_nums[0][10] = Sbar_NewPic ("gfx/num_minus");
172 sb_ammo[0] = Sbar_NewPic ("gfx/sb_shells");
173 sb_ammo[1] = Sbar_NewPic ("gfx/sb_bullets");
174 sb_ammo[2] = Sbar_NewPic ("gfx/sb_rocket");
175 sb_ammo[3] = Sbar_NewPic ("gfx/sb_cells");
177 sb_items[2] = Sbar_NewPic ("gfx/sb_slowmo");
178 sb_items[3] = Sbar_NewPic ("gfx/sb_invinc");
179 sb_items[4] = Sbar_NewPic ("gfx/sb_energy");
180 sb_items[5] = Sbar_NewPic ("gfx/sb_str");
182 sb_sbar = Sbar_NewPic("gfx/sbar");
183 sb_sbar_minimal = Sbar_NewPic("gfx/sbar_minimal");
184 sb_sbar_overlay = Sbar_NewPic("gfx/sbar_overlay");
186 for(i = 0; i < 9;i++)
187 sb_weapons[0][i] = Sbar_NewPic(va("gfx/inv_weapon%i",i));
189 else if (gamemode == GAME_ZYMOTIC)
191 zymsb_crosshair_center = Sbar_NewPic ("gfx/hud/crosshair_center");
192 zymsb_crosshair_line = Sbar_NewPic ("gfx/hud/crosshair_line");
193 zymsb_crosshair_health = Sbar_NewPic ("gfx/hud/crosshair_health");
194 zymsb_crosshair_clip = Sbar_NewPic ("gfx/hud/crosshair_clip");
195 zymsb_crosshair_ammo = Sbar_NewPic ("gfx/hud/crosshair_ammo");
196 zymsb_crosshair_background = Sbar_NewPic ("gfx/hud/crosshair_background");
197 zymsb_crosshair_left1 = Sbar_NewPic ("gfx/hud/crosshair_left1");
198 zymsb_crosshair_left2 = Sbar_NewPic ("gfx/hud/crosshair_left2");
199 zymsb_crosshair_right = Sbar_NewPic ("gfx/hud/crosshair_right");
203 sb_disc = Sbar_NewPic("gfx/disc");
205 for (i = 0;i < 10;i++)
207 sb_nums[0][i] = Sbar_NewPic (va("gfx/num_%i",i));
208 sb_nums[1][i] = Sbar_NewPic (va("gfx/anum_%i",i));
211 sb_nums[0][10] = Sbar_NewPic ("gfx/num_minus");
212 sb_nums[1][10] = Sbar_NewPic ("gfx/anum_minus");
214 sb_colon = Sbar_NewPic ("gfx/num_colon");
215 sb_slash = Sbar_NewPic ("gfx/num_slash");
217 sb_weapons[0][0] = Sbar_NewPic ("gfx/inv_shotgun");
218 sb_weapons[0][1] = Sbar_NewPic ("gfx/inv_sshotgun");
219 sb_weapons[0][2] = Sbar_NewPic ("gfx/inv_nailgun");
220 sb_weapons[0][3] = Sbar_NewPic ("gfx/inv_snailgun");
221 sb_weapons[0][4] = Sbar_NewPic ("gfx/inv_rlaunch");
222 sb_weapons[0][5] = Sbar_NewPic ("gfx/inv_srlaunch");
223 sb_weapons[0][6] = Sbar_NewPic ("gfx/inv_lightng");
225 sb_weapons[1][0] = Sbar_NewPic ("gfx/inv2_shotgun");
226 sb_weapons[1][1] = Sbar_NewPic ("gfx/inv2_sshotgun");
227 sb_weapons[1][2] = Sbar_NewPic ("gfx/inv2_nailgun");
228 sb_weapons[1][3] = Sbar_NewPic ("gfx/inv2_snailgun");
229 sb_weapons[1][4] = Sbar_NewPic ("gfx/inv2_rlaunch");
230 sb_weapons[1][5] = Sbar_NewPic ("gfx/inv2_srlaunch");
231 sb_weapons[1][6] = Sbar_NewPic ("gfx/inv2_lightng");
233 for (i = 0;i < 5;i++)
235 sb_weapons[2+i][0] = Sbar_NewPic (va("gfx/inva%i_shotgun",i+1));
236 sb_weapons[2+i][1] = Sbar_NewPic (va("gfx/inva%i_sshotgun",i+1));
237 sb_weapons[2+i][2] = Sbar_NewPic (va("gfx/inva%i_nailgun",i+1));
238 sb_weapons[2+i][3] = Sbar_NewPic (va("gfx/inva%i_snailgun",i+1));
239 sb_weapons[2+i][4] = Sbar_NewPic (va("gfx/inva%i_rlaunch",i+1));
240 sb_weapons[2+i][5] = Sbar_NewPic (va("gfx/inva%i_srlaunch",i+1));
241 sb_weapons[2+i][6] = Sbar_NewPic (va("gfx/inva%i_lightng",i+1));
244 sb_ammo[0] = Sbar_NewPic ("gfx/sb_shells");
245 sb_ammo[1] = Sbar_NewPic ("gfx/sb_nails");
246 sb_ammo[2] = Sbar_NewPic ("gfx/sb_rocket");
247 sb_ammo[3] = Sbar_NewPic ("gfx/sb_cells");
249 sb_armor[0] = Sbar_NewPic ("gfx/sb_armor1");
250 sb_armor[1] = Sbar_NewPic ("gfx/sb_armor2");
251 sb_armor[2] = Sbar_NewPic ("gfx/sb_armor3");
253 sb_items[0] = Sbar_NewPic ("gfx/sb_key1");
254 sb_items[1] = Sbar_NewPic ("gfx/sb_key2");
255 sb_items[2] = Sbar_NewPic ("gfx/sb_invis");
256 sb_items[3] = Sbar_NewPic ("gfx/sb_invuln");
257 sb_items[4] = Sbar_NewPic ("gfx/sb_suit");
258 sb_items[5] = Sbar_NewPic ("gfx/sb_quad");
260 sb_sigil[0] = Sbar_NewPic ("gfx/sb_sigil1");
261 sb_sigil[1] = Sbar_NewPic ("gfx/sb_sigil2");
262 sb_sigil[2] = Sbar_NewPic ("gfx/sb_sigil3");
263 sb_sigil[3] = Sbar_NewPic ("gfx/sb_sigil4");
265 sb_faces[4][0] = Sbar_NewPic ("gfx/face1");
266 sb_faces[4][1] = Sbar_NewPic ("gfx/face_p1");
267 sb_faces[3][0] = Sbar_NewPic ("gfx/face2");
268 sb_faces[3][1] = Sbar_NewPic ("gfx/face_p2");
269 sb_faces[2][0] = Sbar_NewPic ("gfx/face3");
270 sb_faces[2][1] = Sbar_NewPic ("gfx/face_p3");
271 sb_faces[1][0] = Sbar_NewPic ("gfx/face4");
272 sb_faces[1][1] = Sbar_NewPic ("gfx/face_p4");
273 sb_faces[0][0] = Sbar_NewPic ("gfx/face5");
274 sb_faces[0][1] = Sbar_NewPic ("gfx/face_p5");
276 sb_face_invis = Sbar_NewPic ("gfx/face_invis");
277 sb_face_invuln = Sbar_NewPic ("gfx/face_invul2");
278 sb_face_invis_invuln = Sbar_NewPic ("gfx/face_inv2");
279 sb_face_quad = Sbar_NewPic ("gfx/face_quad");
281 sb_sbar = Sbar_NewPic ("gfx/sbar");
282 sb_ibar = Sbar_NewPic ("gfx/ibar");
283 sb_scorebar = Sbar_NewPic ("gfx/scorebar");
285 //MED 01/04/97 added new hipnotic weapons
286 if (gamemode == GAME_HIPNOTIC)
288 hsb_weapons[0][0] = Sbar_NewPic ("gfx/inv_laser");
289 hsb_weapons[0][1] = Sbar_NewPic ("gfx/inv_mjolnir");
290 hsb_weapons[0][2] = Sbar_NewPic ("gfx/inv_gren_prox");
291 hsb_weapons[0][3] = Sbar_NewPic ("gfx/inv_prox_gren");
292 hsb_weapons[0][4] = Sbar_NewPic ("gfx/inv_prox");
294 hsb_weapons[1][0] = Sbar_NewPic ("gfx/inv2_laser");
295 hsb_weapons[1][1] = Sbar_NewPic ("gfx/inv2_mjolnir");
296 hsb_weapons[1][2] = Sbar_NewPic ("gfx/inv2_gren_prox");
297 hsb_weapons[1][3] = Sbar_NewPic ("gfx/inv2_prox_gren");
298 hsb_weapons[1][4] = Sbar_NewPic ("gfx/inv2_prox");
300 for (i = 0;i < 5;i++)
302 hsb_weapons[2+i][0] = Sbar_NewPic (va("gfx/inva%i_laser",i+1));
303 hsb_weapons[2+i][1] = Sbar_NewPic (va("gfx/inva%i_mjolnir",i+1));
304 hsb_weapons[2+i][2] = Sbar_NewPic (va("gfx/inva%i_gren_prox",i+1));
305 hsb_weapons[2+i][3] = Sbar_NewPic (va("gfx/inva%i_prox_gren",i+1));
306 hsb_weapons[2+i][4] = Sbar_NewPic (va("gfx/inva%i_prox",i+1));
309 hsb_items[0] = Sbar_NewPic ("gfx/sb_wsuit");
310 hsb_items[1] = Sbar_NewPic ("gfx/sb_eshld");
312 else if (gamemode == GAME_ROGUE)
314 rsb_invbar[0] = Sbar_NewPic ("gfx/r_invbar1");
315 rsb_invbar[1] = Sbar_NewPic ("gfx/r_invbar2");
317 rsb_weapons[0] = Sbar_NewPic ("gfx/r_lava");
318 rsb_weapons[1] = Sbar_NewPic ("gfx/r_superlava");
319 rsb_weapons[2] = Sbar_NewPic ("gfx/r_gren");
320 rsb_weapons[3] = Sbar_NewPic ("gfx/r_multirock");
321 rsb_weapons[4] = Sbar_NewPic ("gfx/r_plasma");
323 rsb_items[0] = Sbar_NewPic ("gfx/r_shield1");
324 rsb_items[1] = Sbar_NewPic ("gfx/r_agrav1");
326 // PGM 01/19/97 - team color border
327 rsb_teambord = Sbar_NewPic ("gfx/r_teambord");
328 // PGM 01/19/97 - team color border
330 rsb_ammo[0] = Sbar_NewPic ("gfx/r_ammolava");
331 rsb_ammo[1] = Sbar_NewPic ("gfx/r_ammomulti");
332 rsb_ammo[2] = Sbar_NewPic ("gfx/r_ammoplasma");
337 void sbar_shutdown(void)
341 void sbar_newmap(void)
345 void Sbar_Init (void)
347 Cmd_AddCommand ("+showscores", Sbar_ShowScores);
348 Cmd_AddCommand ("-showscores", Sbar_DontShowScores);
349 Cvar_RegisterVariable (&showfps);
350 Cvar_RegisterVariable (&showtime);
351 Cvar_RegisterVariable (&showtime_format);
352 Cvar_RegisterVariable (&showdate);
353 Cvar_RegisterVariable (&showdate_format);
354 Cvar_RegisterVariable (&sbar_alpha_bg);
355 Cvar_RegisterVariable (&sbar_alpha_fg);
356 Cvar_RegisterVariable (&cl_deathscoreboard);
358 R_RegisterModule("sbar", sbar_start, sbar_shutdown, sbar_newmap);
362 //=============================================================================
364 // drawing routines are relative to the status bar location
373 void Sbar_DrawPic (int x, int y, sbarpic_t *sbarpic)
375 DrawQ_Pic (sbar_x + x, sbar_y + y, sbarpic->name, 0, 0, 1, 1, 1, sbar_alpha_fg.value, 0);
378 void Sbar_DrawAlphaPic (int x, int y, sbarpic_t *sbarpic, float alpha)
380 DrawQ_Pic (sbar_x + x, sbar_y + y, sbarpic->name, 0, 0, 1, 1, 1, alpha, 0);
387 Draws one solid graphics character
390 void Sbar_DrawCharacter (int x, int y, int num)
392 DrawQ_String (sbar_x + x + 4 , sbar_y + y, va("%c", num), 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0);
400 void Sbar_DrawString (int x, int y, char *str)
402 DrawQ_String (sbar_x + x, sbar_y + y, str, 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0);
410 void Sbar_DrawNum (int x, int y, int num, int digits, int color)
415 l = sprintf(str, "%i", num);
429 Sbar_DrawPic (x, y, sb_nums[color][frame]);
442 void Sbar_DrawXNum (int x, int y, int num, int digits, int lettersize, float r, float g, float b, float a, int flags)
447 l = sprintf(str, "%i", num);
452 x += (digits-l) * lettersize;
461 DrawQ_Pic (sbar_x + x, sbar_y + y, sb_nums[0][frame]->name,lettersize,lettersize,r,g,b,a * sbar_alpha_fg.value,flags);
468 //=============================================================================
476 static int fragsort[MAX_SCOREBOARD];
477 static int scoreboardlines;
478 void Sbar_SortFrags (void)
484 for (i=0 ; i<cl.maxclients ; i++)
486 if (cl.scores[i].name[0])
488 fragsort[scoreboardlines] = i;
493 for (i=0 ; i<scoreboardlines ; i++)
494 for (j=0 ; j<scoreboardlines-1-i ; j++)
495 if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j+1]].frags)
498 fragsort[j] = fragsort[j+1];
508 void Sbar_SoloScoreboard (void)
511 int minutes, seconds, tens, units;
514 if (gamemode != GAME_NEXUIZ) {
515 sprintf (str,"Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
516 Sbar_DrawString (8, 4, str);
518 sprintf (str,"Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
519 Sbar_DrawString (8, 12, str);
523 minutes = cl.time / 60;
524 seconds = cl.time - 60*minutes;
526 units = seconds - 10*tens;
527 sprintf (str,"Time :%3i:%i%i", minutes, tens, units);
528 Sbar_DrawString (184, 4, str);
531 if (gamemode == GAME_NEXUIZ) {
532 l = (int) strlen (cl.worldmodel->name);
533 Sbar_DrawString (232 - l*4, 12, cl.worldmodel->name);
535 l = (int) strlen (cl.levelname);
536 Sbar_DrawString (232 - l*4, 12, cl.levelname);
545 void Sbar_DrawScoreboard (void)
547 Sbar_SoloScoreboard ();
548 if (cl.gametype == GAME_DEATHMATCH)
549 Sbar_DeathmatchOverlay ();
552 //=============================================================================
554 // AK to make DrawInventory smaller
555 static void Sbar_DrawWeapon(int nr, float fade, int active)
557 // width = 300, height = 100
558 const int w_width = 300, w_height = 100, w_space = 10;
559 const float w_scale = 0.4;
561 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);
562 //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);
565 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);
573 void Sbar_DrawInventory (void)
580 if (gamemode == GAME_ROGUE)
582 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
583 Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], sbar_alpha_bg.value);
585 Sbar_DrawAlphaPic (0, -24, rsb_invbar[1], sbar_alpha_bg.value);
588 Sbar_DrawAlphaPic (0, -24, sb_ibar, sbar_alpha_bg.value);
591 for (i=0 ; i<7 ; i++)
593 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<i) )
595 time = cl.item_gettime[i];
596 flashon = (int)((cl.time - time)*10);
599 if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i) )
605 flashon = (flashon%5) + 2;
607 Sbar_DrawAlphaPic (i*24, -16, sb_weapons[flashon][i], sbar_alpha_bg.value);
613 if (gamemode == GAME_HIPNOTIC)
615 int grenadeflashing=0;
616 for (i=0 ; i<4 ; i++)
618 if (cl.stats[STAT_ITEMS] & (1<<hipweapons[i]) )
620 time = cl.item_gettime[hipweapons[i]];
621 flashon = (int)((cl.time - time)*10);
624 if ( cl.stats[STAT_ACTIVEWEAPON] == (1<<hipweapons[i]) )
630 flashon = (flashon%5) + 2;
632 // check grenade launcher
635 if (cl.stats[STAT_ITEMS] & HIT_PROXIMITY_GUN)
640 Sbar_DrawPic (96, -16, hsb_weapons[flashon][2]);
646 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<4))
648 if (!grenadeflashing)
649 Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
652 Sbar_DrawPic (96, -16, hsb_weapons[flashon][4]);
655 Sbar_DrawPic (176 + (i*24), -16, hsb_weapons[flashon][i]);
660 if (gamemode == GAME_ROGUE)
662 // check for powered up weapon.
663 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
665 if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i))
666 Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]);
670 for (i=0 ; i<4 ; i++)
672 sprintf (num, "%3i",cl.stats[STAT_SHELLS+i] );
674 Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[0] - '0');
676 Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[1] - '0');
678 Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0');
682 for (i=0 ; i<6 ; i++)
683 if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
685 //MED 01/04/97 changed keys
686 if (gamemode != GAME_HIPNOTIC || (i>1))
687 Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
690 //MED 01/04/97 added hipnotic items
692 if (gamemode == GAME_HIPNOTIC)
694 for (i=0 ; i<2 ; i++)
695 if (cl.stats[STAT_ITEMS] & (1<<(24+i)))
696 Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
699 if (gamemode == GAME_ROGUE)
702 for (i=0 ; i<2 ; i++)
703 if (cl.stats[STAT_ITEMS] & (1<<(29+i)))
704 Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
709 for (i=0 ; i<4 ; i++)
710 if (cl.stats[STAT_ITEMS] & (1<<(28+i)))
711 Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
715 //=============================================================================
722 void Sbar_DrawFrags (void)
732 l = min(scoreboardlines, 4);
736 for (i = 0;i < l;i++)
742 c = (qbyte *)&palette_complete[(s->colors & 0xf0) + 8];
743 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);
744 c = (qbyte *)&palette_complete[((s->colors & 15)<<4) + 8];
745 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);
749 sprintf (num, "%3i",f);
751 if (k == cl.viewentity - 1)
753 Sbar_DrawCharacter ( x + 2, -24, 16);
754 Sbar_DrawCharacter ( x + 32 - 4, -24, 17);
756 Sbar_DrawCharacter (x + 8, -24, num[0]);
757 Sbar_DrawCharacter (x + 16, -24, num[1]);
758 Sbar_DrawCharacter (x + 24, -24, num[2]);
763 //=============================================================================
771 void Sbar_DrawFace (void)
775 // PGM 01/19/97 - team color drawing
776 // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
777 if (gamemode == GAME_ROGUE && !cl.islocalgame && (teamplay.integer > 3) && (teamplay.integer < 7))
783 s = &cl.scores[cl.viewentity - 1];
785 Sbar_DrawPic (112, 0, rsb_teambord);
786 c = (qbyte *)&palette_complete[(s->colors & 0xf0) + 8];
787 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);
788 c = (qbyte *)&palette_complete[((s->colors & 15)<<4) + 8];
789 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);
793 sprintf (num, "%3i",f);
795 if ((s->colors & 0xf0)==0)
798 Sbar_DrawCharacter(109, 3, 18 + num[0] - '0');
800 Sbar_DrawCharacter(116, 3, 18 + num[1] - '0');
802 Sbar_DrawCharacter(123, 3, 18 + num[2] - '0');
806 Sbar_DrawCharacter ( 109, 3, num[0]);
807 Sbar_DrawCharacter ( 116, 3, num[1]);
808 Sbar_DrawCharacter ( 123, 3, num[2]);
813 // PGM 01/19/97 - team color drawing
815 if ( (cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
816 Sbar_DrawPic (112, 0, sb_face_invis_invuln);
817 else if (cl.stats[STAT_ITEMS] & IT_QUAD)
818 Sbar_DrawPic (112, 0, sb_face_quad );
819 else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
820 Sbar_DrawPic (112, 0, sb_face_invis );
821 else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
822 Sbar_DrawPic (112, 0, sb_face_invuln);
825 f = cl.stats[STAT_HEALTH] / 20;
827 Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]);
831 void Sbar_ShowFPS(void)
833 float fps_x, fps_y, fps_scalex, fps_scaley, fps_height;
837 qboolean red = false;
844 if (showfps.integer > 1)
846 static double currtime, frametimes[32];
847 double newtime, total;
849 static int framecycle = 0;
851 newtime = Sys_DoubleTime();
852 frametimes[framecycle] = newtime - currtime;
855 while(total < 0.2 && count < 32 && frametimes[i = (framecycle - count) & 31])
857 total += frametimes[i];
862 if (showfps.integer == 2)
863 calc = (((double)count / total) + 0.5);
864 else // showfps 3, rapid update
865 calc = ((1.0 / (newtime - currtime)) + 0.5);
870 static double nexttime = 0, lasttime = 0;
871 static float framerate = 0;
872 static int framecount = 0;
874 newtime = Sys_DoubleTime();
875 if (newtime >= nexttime)
877 framerate = ((float)framecount / (newtime - lasttime) + 0.5);
879 nexttime = max(nexttime + 1, lasttime - 1);
886 if ((red = (calc < 1.0f)))
887 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0f / calc + 0.5));
889 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(calc + 0.5));
891 if (showtime.integer)
892 strlcpy(timestring, Sys_TimeString(showtime_format.string), sizeof(timestring));
893 if (showdate.integer)
894 strlcpy(datestring, Sys_TimeString(showdate_format.string), sizeof(datestring));
895 if (fpsstring[0] || timestring[0])
899 fps_height = fps_scaley * ((fpsstring[0] != 0) + (timestring[0] != 0) + (datestring[0] != 0));
900 //fps_y = vid_conheight.integer - sb_lines; // yes this may draw over the sbar
901 //fps_y = bound(0, fps_y, vid_conheight.integer - fps_height);
902 fps_y = vid_conheight.integer - fps_height;
905 fps_x = vid_conwidth.integer - fps_scalex * strlen(fpsstring);
906 DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(fpsstring), fps_scaley, 0, 0, 0, 0.5, 0);
908 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 0, 0, 1, 0);
910 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
915 fps_x = vid_conwidth.integer - fps_scalex * strlen(timestring);
916 DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(timestring), fps_scaley, 0, 0, 0, 0.5, 0);
917 DrawQ_String(fps_x, fps_y, timestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
922 fps_x = vid_conwidth.integer - fps_scalex * strlen(datestring);
923 DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(datestring), fps_scaley, 0, 0, 0, 0.5, 0);
924 DrawQ_String(fps_x, fps_y, datestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
930 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)
933 c2 = bound(0, c2, 1);
934 c1 = bound(0, c1, 1 - c2);
936 r[1] = rangey + rangeheight * (c2 + c1);
937 r[2] = rangey + rangeheight * (c2);
941 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);
943 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);
945 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);
947 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);
955 extern float v_dmg_time, v_dmg_roll, v_dmg_pitch;
956 extern cvar_t v_kicktime;
957 void Sbar_Draw (void)
959 if (cl.intermission == 1)
961 Sbar_IntermissionOverlay();
964 else if (cl.intermission == 2)
966 Sbar_FinaleOverlay();
970 if (gamemode == GAME_SOM)
972 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
973 Sbar_DrawScoreboard ();
976 // this is the top left of the sbar area
978 sbar_y = vid_conheight.integer - 24*3;
981 if (cl.stats[STAT_ARMOR])
983 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
984 Sbar_DrawPic(0, 0, somsb_armor[2]);
985 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
986 Sbar_DrawPic(0, 0, somsb_armor[1]);
987 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
988 Sbar_DrawPic(0, 0, somsb_armor[0]);
989 Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
993 Sbar_DrawPic(0, 24, somsb_health);
994 Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
997 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
998 Sbar_DrawPic(0, 48, somsb_ammo[0]);
999 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1000 Sbar_DrawPic(0, 48, somsb_ammo[1]);
1001 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1002 Sbar_DrawPic(0, 48, somsb_ammo[2]);
1003 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1004 Sbar_DrawPic(0, 48, somsb_ammo[3]);
1005 Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
1006 if (cl.stats[STAT_SHELLS])
1007 Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
1010 else if (gamemode == GAME_NEXUIZ)
1012 sbar_y = vid_conheight.integer - 47;
1013 sbar_x = (vid_conwidth.integer - 640)/2;
1015 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1017 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1018 Sbar_DrawScoreboard ();
1026 // we have a max time 2s (min time = 0)
1027 if ((time = cl.time - cl.weapontime) < 2)
1029 fade = (1.0 - 0.5 * time);
1031 for (i = 0; i < 8;i++)
1032 if (cl.stats[STAT_ITEMS] & (1 << i))
1033 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1035 if((cl.stats[STAT_ITEMS] & (1<<12)))
1036 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1039 //if (!cl.islocalgame)
1040 // Sbar_DrawFrags ();
1043 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1045 Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1048 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1050 // Nexuiz has no anum pics
1051 //Sbar_DrawNum (36, 0, 666, 3, 1);
1052 // Nexuiz has no disc pic
1053 //Sbar_DrawPic (0, 0, sb_disc);
1057 Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1060 if(cl.stats[STAT_HEALTH] > 100)
1061 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1062 else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1063 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1065 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1067 // AK dont draw ammo for the laser
1068 if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1070 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1071 Sbar_DrawPic (519, 0, sb_ammo[0]);
1072 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1073 Sbar_DrawPic (519, 0, sb_ammo[1]);
1074 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1075 Sbar_DrawPic (519, 0, sb_ammo[2]);
1076 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1077 Sbar_DrawPic (519, 0, sb_ammo[3]);
1079 if(cl.stats[STAT_AMMO] <= 10)
1080 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1082 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1087 DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay->name,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1090 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1091 // Sbar_MiniDeathmatchOverlay (0, 17);
1093 else if (gamemode == GAME_ZYMOTIC)
1096 float scale = 64.0f / 256.0f;
1097 float kickoffset[3];
1098 VectorClear(kickoffset);
1101 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1102 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1104 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1105 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1106 // left1 16, 48 : 126 -66
1107 // left2 16, 128 : 196 -66
1108 // right 176, 48 : 196 -136
1109 if (cl.stats[STAT_AMMO] > 200)
1110 Con_Printf("cl.stats[STAT_AMMO] == %i\n", cl.stats[STAT_AMMO]);
1111 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);
1112 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);
1113 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);
1114 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center->name, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1116 float scale = 128.0f / 256.0f;
1117 float healthstart, healthheight, healthstarttc, healthendtc;
1118 float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1119 float ammostart, ammoheight, ammostarttc, ammoendtc;
1120 float clipstart, clipheight, clipstarttc, clipendtc;
1121 float kickoffset[3], offset;
1122 VectorClear(kickoffset);
1125 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1126 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1128 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1129 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1130 offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1131 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);
1132 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);
1133 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);
1134 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);
1135 healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1136 shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1137 healthstart = 204 - healthheight;
1138 shieldstart = healthstart - shieldheight;
1139 healthstarttc = healthstart * (1.0f / 256.0f);
1140 healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1141 shieldstarttc = shieldstart * (1.0f / 256.0f);
1142 shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1143 ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1144 ammostart = 114 - ammoheight;
1145 ammostarttc = ammostart * (1.0f / 256.0f);
1146 ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1147 clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1148 clipstart = 190 - clipheight;
1149 clipstarttc = clipstart * (1.0f / 256.0f);
1150 clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1151 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);
1152 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);
1153 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);
1154 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);
1155 DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background->name, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1156 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center->name, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1159 else // Quake and others
1161 sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1162 if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1165 sbar_x = (vid_conwidth.integer - 320)/2;
1169 if (gamemode != GAME_GOODVSBAD2)
1170 Sbar_DrawInventory ();
1171 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1175 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1177 if (gamemode != GAME_GOODVSBAD2)
1178 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1179 Sbar_DrawScoreboard ();
1183 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1185 // keys (hipnotic only)
1186 //MED 01/04/97 moved keys here so they would not be overwritten
1187 if (gamemode == GAME_HIPNOTIC)
1189 if (cl.stats[STAT_ITEMS] & IT_KEY1)
1190 Sbar_DrawPic (209, 3, sb_items[0]);
1191 if (cl.stats[STAT_ITEMS] & IT_KEY2)
1192 Sbar_DrawPic (209, 12, sb_items[1]);
1195 if (gamemode != GAME_GOODVSBAD2)
1197 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1199 Sbar_DrawNum (24, 0, 666, 3, 1);
1200 Sbar_DrawPic (0, 0, sb_disc);
1204 if (gamemode == GAME_ROGUE)
1206 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1207 if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1208 Sbar_DrawPic (0, 0, sb_armor[2]);
1209 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1210 Sbar_DrawPic (0, 0, sb_armor[1]);
1211 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1212 Sbar_DrawPic (0, 0, sb_armor[0]);
1216 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1217 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1218 Sbar_DrawPic (0, 0, sb_armor[2]);
1219 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1220 Sbar_DrawPic (0, 0, sb_armor[1]);
1221 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1222 Sbar_DrawPic (0, 0, sb_armor[0]);
1231 Sbar_DrawNum (154, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1234 if (gamemode == GAME_ROGUE)
1236 if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1237 Sbar_DrawPic (224, 0, sb_ammo[0]);
1238 else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1239 Sbar_DrawPic (224, 0, sb_ammo[1]);
1240 else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1241 Sbar_DrawPic (224, 0, sb_ammo[2]);
1242 else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1243 Sbar_DrawPic (224, 0, sb_ammo[3]);
1244 else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1245 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1246 else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1247 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1248 else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1249 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1253 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1254 Sbar_DrawPic (224, 0, sb_ammo[0]);
1255 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1256 Sbar_DrawPic (224, 0, sb_ammo[1]);
1257 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1258 Sbar_DrawPic (224, 0, sb_ammo[2]);
1259 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1260 Sbar_DrawPic (224, 0, sb_ammo[3]);
1263 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1267 if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1269 if (gamemode == GAME_TRANSFUSION)
1270 Sbar_MiniDeathmatchOverlay (0, 0);
1272 Sbar_MiniDeathmatchOverlay (324, vid_conheight.integer - sb_lines);
1278 R_Draw2DCrosshair();
1280 if (cl_prydoncursor.integer)
1281 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);
1284 //=============================================================================
1288 Sbar_DeathmatchOverlay
1292 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1295 // draw colors behind score
1296 c = (qbyte *)&palette_complete[(s->colors & 0xf0) + 8];
1297 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);
1298 c = (qbyte *)&palette_complete[((s->colors & 15)<<4) + 8];
1299 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);
1301 //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);
1302 // FIXME: use a constant for this color tag instead
1303 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 );
1307 void Sbar_DeathmatchOverlay (void)
1312 pic = Draw_CachePic ("gfx/ranking", true);
1313 DrawQ_Pic ((vid_conwidth.integer - pic->width)/2, 8, "gfx/ranking", 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1318 x = (vid_conwidth.integer - (6 + 15) * 8) / 2;
1320 for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1321 y += Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1326 Sbar_DeathmatchOverlay
1330 void Sbar_MiniDeathmatchOverlay (int x, int y)
1334 // decide where to print
1335 if (gamemode == GAME_TRANSFUSION)
1336 numlines = (vid_conwidth.integer - x + 127) / 128;
1338 numlines = (vid_conheight.integer - y + 7) / 8;
1340 // give up if there isn't room
1341 if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1348 for (i = 0; i < scoreboardlines; i++)
1349 if (fragsort[i] == cl.playerentity - 1)
1354 i = min(i, scoreboardlines - numlines);
1357 if (gamemode == GAME_TRANSFUSION)
1359 for (;i < scoreboardlines && x < vid_conwidth.integer;i++)
1360 x += 128 + Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1364 for (;i < scoreboardlines && y < vid_conheight.integer;i++)
1365 y += Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1371 Sbar_IntermissionOverlay
1375 void Sbar_IntermissionOverlay (void)
1380 if (cl.gametype == GAME_DEATHMATCH)
1382 Sbar_DeathmatchOverlay ();
1386 sbar_x = (vid_conwidth.integer - 320) >> 1;
1387 sbar_y = (vid_conheight.integer - 200) >> 1;
1389 DrawQ_Pic (sbar_x + 64, sbar_y + 24, "gfx/complete", 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1390 DrawQ_Pic (sbar_x + 0, sbar_y + 56, "gfx/inter", 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1393 dig = cl.completed_time/60;
1394 Sbar_DrawNum (160, 64, dig, 3, 0);
1395 num = cl.completed_time - dig*60;
1396 if (gamemode != GAME_NEXUIZ)
1397 Sbar_DrawPic (234,64,sb_colon);
1398 Sbar_DrawPic (246,64,sb_nums[0][num/10]);
1399 Sbar_DrawPic (266,64,sb_nums[0][num%10]);
1401 Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
1402 if (gamemode != GAME_NEXUIZ)
1403 Sbar_DrawPic (232, 104, sb_slash);
1404 Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1406 Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1407 if (gamemode != GAME_NEXUIZ)
1408 Sbar_DrawPic (232, 144, sb_slash);
1409 Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1420 void Sbar_FinaleOverlay (void)
1424 pic = Draw_CachePic ("gfx/finale", true);
1425 DrawQ_Pic((vid_conwidth.integer - pic->width)/2, 16, "gfx/finale", 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);