2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 // sbar.c -- status bar code
26 #define STAT_MINUS 10 // num frame for '-' stats digit
27 cachepic_t *sb_nums[2][11];
28 cachepic_t *sb_colon, *sb_slash;
31 cachepic_t *sb_scorebar;
32 // AK only used by NEX
33 cachepic_t *sb_sbar_minimal;
34 cachepic_t *sb_sbar_overlay;
36 // AK changed the bound to 9
37 cachepic_t *sb_weapons[7][9]; // 0 is active, 1 is owned, 2-5 are flashes
38 cachepic_t *sb_ammo[4];
39 cachepic_t *sb_sigil[4];
40 cachepic_t *sb_armor[3];
41 cachepic_t *sb_items[32];
43 // 0-4 are based on health (in 20 increments)
44 // 0 is static, 1 is temporary animation
45 cachepic_t *sb_faces[5][2];
47 cachepic_t *sb_face_invis;
48 cachepic_t *sb_face_quad;
49 cachepic_t *sb_face_invuln;
50 cachepic_t *sb_face_invis_invuln;
52 qboolean sb_showscores;
54 int sb_lines; // scan lines to draw
56 cachepic_t *rsb_invbar[2];
57 cachepic_t *rsb_weapons[5];
58 cachepic_t *rsb_items[2];
59 cachepic_t *rsb_ammo[3];
60 cachepic_t *rsb_teambord; // PGM 01/19/97 - team color border
62 //MED 01/04/97 added two more weapons + 3 alternates for grenade launcher
63 cachepic_t *hsb_weapons[7][5]; // 0 is active, 1 is owned, 2-5 are flashes
64 //MED 01/04/97 added array to simplify weapon parsing
65 int hipweapons[4] = {HIT_LASER_CANNON_BIT,HIT_MJOLNIR_BIT,4,HIT_PROXIMITY_GUN_BIT};
66 //MED 01/04/97 added hipnotic items array
67 cachepic_t *hsb_items[2];
70 cachepic_t *somsb_health;
71 cachepic_t *somsb_ammo[4];
72 cachepic_t *somsb_armor[3];
74 cachepic_t *zymsb_crosshair_center;
75 cachepic_t *zymsb_crosshair_line;
76 cachepic_t *zymsb_crosshair_health;
77 cachepic_t *zymsb_crosshair_ammo;
78 cachepic_t *zymsb_crosshair_clip;
79 cachepic_t *zymsb_crosshair_background;
80 cachepic_t *zymsb_crosshair_left1;
81 cachepic_t *zymsb_crosshair_left2;
82 cachepic_t *zymsb_crosshair_right;
84 cvar_t showfps = {CVAR_SAVE, "showfps", "0", "shows your rendered fps (frames per second)"};
85 cvar_t showtime = {CVAR_SAVE, "showtime", "0", "shows current time of day (useful on screenshots)"};
86 cvar_t showtime_format = {CVAR_SAVE, "showtime_format", "%H:%M:%S", "format string for time of day"};
87 cvar_t showdate = {CVAR_SAVE, "showdate", "0", "shows current date (useful on screenshots)"};
88 cvar_t showdate_format = {CVAR_SAVE, "showdate_format", "%Y-%m-%d", "format string for date"};
89 cvar_t sbar_alpha_bg = {CVAR_SAVE, "sbar_alpha_bg", "0.4", "opacity value of the statusbar background image"};
90 cvar_t sbar_alpha_fg = {CVAR_SAVE, "sbar_alpha_fg", "1", "opacity value of the statusbar weapon/item icons and numbers"};
92 cvar_t cl_deathscoreboard = {0, "cl_deathscoreboard", "1", "shows scoreboard (+showscores) while dead"};
94 void Sbar_MiniDeathmatchOverlay (int x, int y);
95 void Sbar_DeathmatchOverlay (void);
96 void Sbar_IntermissionOverlay (void);
97 void Sbar_FinaleOverlay (void);
107 void Sbar_ShowScores (void)
111 sb_showscores = true;
121 void Sbar_DontShowScores (void)
123 sb_showscores = false;
126 void sbar_start(void)
130 if (gamemode == GAME_NETHERWORLD)
133 else if (gamemode == GAME_SOM)
135 sb_disc = Draw_CachePic("gfx/disc", true);
137 for (i = 0;i < 10;i++)
138 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
140 somsb_health = Draw_CachePic("gfx/hud_health", true);
141 somsb_ammo[0] = Draw_CachePic("gfx/sb_shells", true);
142 somsb_ammo[1] = Draw_CachePic("gfx/sb_nails", true);
143 somsb_ammo[2] = Draw_CachePic("gfx/sb_rocket", true);
144 somsb_ammo[3] = Draw_CachePic("gfx/sb_cells", true);
145 somsb_armor[0] = Draw_CachePic("gfx/sb_armor1", true);
146 somsb_armor[1] = Draw_CachePic("gfx/sb_armor2", true);
147 somsb_armor[2] = Draw_CachePic("gfx/sb_armor3", true);
149 else if (gamemode == GAME_NEXUIZ)
151 for (i = 0;i < 10;i++)
152 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
153 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus", true);
155 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells", true);
156 sb_ammo[1] = Draw_CachePic ("gfx/sb_bullets", true);
157 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket", true);
158 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells", true);
160 sb_items[2] = Draw_CachePic ("gfx/sb_slowmo", true);
161 sb_items[3] = Draw_CachePic ("gfx/sb_invinc", true);
162 sb_items[4] = Draw_CachePic ("gfx/sb_energy", true);
163 sb_items[5] = Draw_CachePic ("gfx/sb_str", true);
165 sb_sbar = Draw_CachePic("gfx/sbar", true);
166 sb_sbar_minimal = Draw_CachePic("gfx/sbar_minimal", true);
167 sb_sbar_overlay = Draw_CachePic("gfx/sbar_overlay", true);
169 for(i = 0; i < 9;i++)
170 sb_weapons[0][i] = Draw_CachePic(va("gfx/inv_weapon%i",i), true);
172 else if (gamemode == GAME_ZYMOTIC)
174 zymsb_crosshair_center = Draw_CachePic ("gfx/hud/crosshair_center", true);
175 zymsb_crosshair_line = Draw_CachePic ("gfx/hud/crosshair_line", true);
176 zymsb_crosshair_health = Draw_CachePic ("gfx/hud/crosshair_health", true);
177 zymsb_crosshair_clip = Draw_CachePic ("gfx/hud/crosshair_clip", true);
178 zymsb_crosshair_ammo = Draw_CachePic ("gfx/hud/crosshair_ammo", true);
179 zymsb_crosshair_background = Draw_CachePic ("gfx/hud/crosshair_background", true);
180 zymsb_crosshair_left1 = Draw_CachePic ("gfx/hud/crosshair_left1", true);
181 zymsb_crosshair_left2 = Draw_CachePic ("gfx/hud/crosshair_left2", true);
182 zymsb_crosshair_right = Draw_CachePic ("gfx/hud/crosshair_right", true);
186 sb_disc = Draw_CachePic("gfx/disc", true);
188 for (i = 0;i < 10;i++)
190 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
191 sb_nums[1][i] = Draw_CachePic (va("gfx/anum_%i",i), true);
194 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus", true);
195 sb_nums[1][10] = Draw_CachePic ("gfx/anum_minus", true);
197 sb_colon = Draw_CachePic ("gfx/num_colon", true);
198 sb_slash = Draw_CachePic ("gfx/num_slash", true);
200 sb_weapons[0][0] = Draw_CachePic ("gfx/inv_shotgun", true);
201 sb_weapons[0][1] = Draw_CachePic ("gfx/inv_sshotgun", true);
202 sb_weapons[0][2] = Draw_CachePic ("gfx/inv_nailgun", true);
203 sb_weapons[0][3] = Draw_CachePic ("gfx/inv_snailgun", true);
204 sb_weapons[0][4] = Draw_CachePic ("gfx/inv_rlaunch", true);
205 sb_weapons[0][5] = Draw_CachePic ("gfx/inv_srlaunch", true);
206 sb_weapons[0][6] = Draw_CachePic ("gfx/inv_lightng", true);
208 sb_weapons[1][0] = Draw_CachePic ("gfx/inv2_shotgun", true);
209 sb_weapons[1][1] = Draw_CachePic ("gfx/inv2_sshotgun", true);
210 sb_weapons[1][2] = Draw_CachePic ("gfx/inv2_nailgun", true);
211 sb_weapons[1][3] = Draw_CachePic ("gfx/inv2_snailgun", true);
212 sb_weapons[1][4] = Draw_CachePic ("gfx/inv2_rlaunch", true);
213 sb_weapons[1][5] = Draw_CachePic ("gfx/inv2_srlaunch", true);
214 sb_weapons[1][6] = Draw_CachePic ("gfx/inv2_lightng", true);
216 for (i = 0;i < 5;i++)
218 sb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_shotgun",i+1), true);
219 sb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_sshotgun",i+1), true);
220 sb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_nailgun",i+1), true);
221 sb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_snailgun",i+1), true);
222 sb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_rlaunch",i+1), true);
223 sb_weapons[2+i][5] = Draw_CachePic (va("gfx/inva%i_srlaunch",i+1), true);
224 sb_weapons[2+i][6] = Draw_CachePic (va("gfx/inva%i_lightng",i+1), true);
227 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells", true);
228 sb_ammo[1] = Draw_CachePic ("gfx/sb_nails", true);
229 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket", true);
230 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells", true);
232 sb_armor[0] = Draw_CachePic ("gfx/sb_armor1", true);
233 sb_armor[1] = Draw_CachePic ("gfx/sb_armor2", true);
234 sb_armor[2] = Draw_CachePic ("gfx/sb_armor3", true);
236 sb_items[0] = Draw_CachePic ("gfx/sb_key1", true);
237 sb_items[1] = Draw_CachePic ("gfx/sb_key2", true);
238 sb_items[2] = Draw_CachePic ("gfx/sb_invis", true);
239 sb_items[3] = Draw_CachePic ("gfx/sb_invuln", true);
240 sb_items[4] = Draw_CachePic ("gfx/sb_suit", true);
241 sb_items[5] = Draw_CachePic ("gfx/sb_quad", true);
243 sb_sigil[0] = Draw_CachePic ("gfx/sb_sigil1", true);
244 sb_sigil[1] = Draw_CachePic ("gfx/sb_sigil2", true);
245 sb_sigil[2] = Draw_CachePic ("gfx/sb_sigil3", true);
246 sb_sigil[3] = Draw_CachePic ("gfx/sb_sigil4", true);
248 sb_faces[4][0] = Draw_CachePic ("gfx/face1", true);
249 sb_faces[4][1] = Draw_CachePic ("gfx/face_p1", true);
250 sb_faces[3][0] = Draw_CachePic ("gfx/face2", true);
251 sb_faces[3][1] = Draw_CachePic ("gfx/face_p2", true);
252 sb_faces[2][0] = Draw_CachePic ("gfx/face3", true);
253 sb_faces[2][1] = Draw_CachePic ("gfx/face_p3", true);
254 sb_faces[1][0] = Draw_CachePic ("gfx/face4", true);
255 sb_faces[1][1] = Draw_CachePic ("gfx/face_p4", true);
256 sb_faces[0][0] = Draw_CachePic ("gfx/face5", true);
257 sb_faces[0][1] = Draw_CachePic ("gfx/face_p5", true);
259 sb_face_invis = Draw_CachePic ("gfx/face_invis", true);
260 sb_face_invuln = Draw_CachePic ("gfx/face_invul2", true);
261 sb_face_invis_invuln = Draw_CachePic ("gfx/face_inv2", true);
262 sb_face_quad = Draw_CachePic ("gfx/face_quad", true);
264 sb_sbar = Draw_CachePic ("gfx/sbar", true);
265 sb_ibar = Draw_CachePic ("gfx/ibar", true);
266 sb_scorebar = Draw_CachePic ("gfx/scorebar", true);
268 //MED 01/04/97 added new hipnotic weapons
269 if (gamemode == GAME_HIPNOTIC)
271 hsb_weapons[0][0] = Draw_CachePic ("gfx/inv_laser", true);
272 hsb_weapons[0][1] = Draw_CachePic ("gfx/inv_mjolnir", true);
273 hsb_weapons[0][2] = Draw_CachePic ("gfx/inv_gren_prox", true);
274 hsb_weapons[0][3] = Draw_CachePic ("gfx/inv_prox_gren", true);
275 hsb_weapons[0][4] = Draw_CachePic ("gfx/inv_prox", true);
277 hsb_weapons[1][0] = Draw_CachePic ("gfx/inv2_laser", true);
278 hsb_weapons[1][1] = Draw_CachePic ("gfx/inv2_mjolnir", true);
279 hsb_weapons[1][2] = Draw_CachePic ("gfx/inv2_gren_prox", true);
280 hsb_weapons[1][3] = Draw_CachePic ("gfx/inv2_prox_gren", true);
281 hsb_weapons[1][4] = Draw_CachePic ("gfx/inv2_prox", true);
283 for (i = 0;i < 5;i++)
285 hsb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_laser",i+1), true);
286 hsb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_mjolnir",i+1), true);
287 hsb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_gren_prox",i+1), true);
288 hsb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_prox_gren",i+1), true);
289 hsb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_prox",i+1), true);
292 hsb_items[0] = Draw_CachePic ("gfx/sb_wsuit", true);
293 hsb_items[1] = Draw_CachePic ("gfx/sb_eshld", true);
295 else if (gamemode == GAME_ROGUE)
297 rsb_invbar[0] = Draw_CachePic ("gfx/r_invbar1", true);
298 rsb_invbar[1] = Draw_CachePic ("gfx/r_invbar2", true);
300 rsb_weapons[0] = Draw_CachePic ("gfx/r_lava", true);
301 rsb_weapons[1] = Draw_CachePic ("gfx/r_superlava", true);
302 rsb_weapons[2] = Draw_CachePic ("gfx/r_gren", true);
303 rsb_weapons[3] = Draw_CachePic ("gfx/r_multirock", true);
304 rsb_weapons[4] = Draw_CachePic ("gfx/r_plasma", true);
306 rsb_items[0] = Draw_CachePic ("gfx/r_shield1", true);
307 rsb_items[1] = Draw_CachePic ("gfx/r_agrav1", true);
309 // PGM 01/19/97 - team color border
310 rsb_teambord = Draw_CachePic ("gfx/r_teambord", true);
311 // PGM 01/19/97 - team color border
313 rsb_ammo[0] = Draw_CachePic ("gfx/r_ammolava", true);
314 rsb_ammo[1] = Draw_CachePic ("gfx/r_ammomulti", true);
315 rsb_ammo[2] = Draw_CachePic ("gfx/r_ammoplasma", true);
320 void sbar_shutdown(void)
324 void sbar_newmap(void)
328 void Sbar_Init (void)
330 Cmd_AddCommand ("+showscores", Sbar_ShowScores, "show scoreboard");
331 Cmd_AddCommand ("-showscores", Sbar_DontShowScores, "hide scoreboard");
332 Cvar_RegisterVariable (&showfps);
333 Cvar_RegisterVariable (&showtime);
334 Cvar_RegisterVariable (&showtime_format);
335 Cvar_RegisterVariable (&showdate);
336 Cvar_RegisterVariable (&showdate_format);
337 Cvar_RegisterVariable (&sbar_alpha_bg);
338 Cvar_RegisterVariable (&sbar_alpha_fg);
339 Cvar_RegisterVariable (&cl_deathscoreboard);
341 R_RegisterModule("sbar", sbar_start, sbar_shutdown, sbar_newmap);
345 //=============================================================================
347 // drawing routines are relative to the status bar location
356 void Sbar_DrawPic (int x, int y, cachepic_t *pic)
358 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, sbar_alpha_fg.value, 0);
361 void Sbar_DrawAlphaPic (int x, int y, cachepic_t *pic, float alpha)
363 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, alpha, 0);
370 Draws one solid graphics character
373 void Sbar_DrawCharacter (int x, int y, int num)
375 DrawQ_String (sbar_x + x + 4 , sbar_y + y, va("%c", num), 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0);
383 void Sbar_DrawString (int x, int y, char *str)
385 DrawQ_String (sbar_x + x, sbar_y + y, str, 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0);
393 void Sbar_DrawNum (int x, int y, int num, int digits, int color)
398 l = sprintf(str, "%i", num);
412 Sbar_DrawPic (x, y, sb_nums[color][frame]);
425 void Sbar_DrawXNum (int x, int y, int num, int digits, int lettersize, float r, float g, float b, float a, int flags)
430 l = sprintf(str, "%i", num);
435 x += (digits-l) * lettersize;
444 DrawQ_Pic (sbar_x + x, sbar_y + y, sb_nums[0][frame],lettersize,lettersize,r,g,b,a * sbar_alpha_fg.value,flags);
451 //=============================================================================
454 int Sbar_IsTeammatch()
456 // currently only nexuiz uses the team score board
457 return ((gamemode == GAME_NEXUIZ)
458 && (teamplay.integer > 0));
466 static int fragsort[MAX_SCOREBOARD];
467 static int scoreboardlines;
469 //[515]: Sbar_GetPlayer for csqc "getplayerkey" func
470 int Sbar_GetPlayer (int index)
475 if(index >= scoreboardlines)
477 index = fragsort[index];
479 if(index >= scoreboardlines)
484 static scoreboard_t teams[MAX_SCOREBOARD];
485 static int teamsort[MAX_SCOREBOARD];
486 static int teamlines;
487 void Sbar_SortFrags (void)
493 for (i=0 ; i<cl.maxclients ; i++)
495 if (cl.scores[i].name[0])
497 fragsort[scoreboardlines] = i;
502 for (i=0 ; i<scoreboardlines ; i++)
503 for (j=0 ; j<scoreboardlines-1-i ; j++)
504 if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j+1]].frags)
507 fragsort[j] = fragsort[j+1];
512 if (Sbar_IsTeammatch ())
514 // now sort players by teams.
515 for (i=0 ; i<scoreboardlines ; i++)
517 for (j=0 ; j<scoreboardlines-1-i ; j++)
519 if (cl.scores[fragsort[j]].colors < cl.scores[fragsort[j+1]].colors)
522 fragsort[j] = fragsort[j+1];
528 // calculate team scores
530 for (i=0 ; i<scoreboardlines ; i++)
532 if (color != (cl.scores[fragsort[i]].colors & 15))
534 color = cl.scores[fragsort[i]].colors & 15;
538 strcpy(teams[teamlines-1].name, "^1Red Team");
539 else if (color == 13)
540 strcpy(teams[teamlines-1].name, "^4Blue Team");
542 strcpy(teams[teamlines-1].name, "^6Pink Team");
543 else if (color == 12)
544 strcpy(teams[teamlines-1].name, "^3Yellow Team");
546 strcpy(teams[teamlines-1].name, "Total Team Score");
548 teams[teamlines-1].frags = 0;
549 teams[teamlines-1].colors = color + 16 * color;
552 if (cl.scores[fragsort[i]].frags != -666)
554 // do not add spedcators
555 // (ugly hack for nexuiz)
556 teams[teamlines-1].frags += cl.scores[fragsort[i]].frags;
560 // now sort teams by scores.
561 for (i=0 ; i<teamlines ; i++)
563 for (i=0 ; i<teamlines ; i++)
565 for (j=0 ; j<teamlines-1-i ; j++)
567 if (teams[teamsort[j]].frags < teams[teamsort[j+1]].frags)
570 teamsort[j] = teamsort[j+1];
583 void Sbar_SoloScoreboard (void)
586 int minutes, seconds, tens, units;
589 if (gamemode != GAME_NEXUIZ) {
590 sprintf (str,"Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
591 Sbar_DrawString (8, 4, str);
593 sprintf (str,"Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
594 Sbar_DrawString (8, 12, str);
598 minutes = cl.time / 60;
599 seconds = cl.time - 60*minutes;
601 units = seconds - 10*tens;
602 sprintf (str,"Time :%3i:%i%i", minutes, tens, units);
603 Sbar_DrawString (184, 4, str);
606 if (gamemode == GAME_NEXUIZ) {
607 l = (int) strlen (cl.worldmodel->name);
608 Sbar_DrawString (232 - l*4, 12, cl.worldmodel->name);
610 l = (int) strlen (cl.levelname);
611 Sbar_DrawString (232 - l*4, 12, cl.levelname);
620 void Sbar_DrawScoreboard (void)
622 Sbar_SoloScoreboard ();
623 if (cl.gametype == GAME_DEATHMATCH)
624 Sbar_DeathmatchOverlay ();
627 //=============================================================================
629 // AK to make DrawInventory smaller
630 static void Sbar_DrawWeapon(int nr, float fade, int active)
632 // width = 300, height = 100
633 const int w_width = 300, w_height = 100, w_space = 10;
634 const float w_scale = 0.4;
636 DrawQ_Pic(vid_conwidth.integer - (w_width + w_space) * w_scale, (w_height + w_space) * w_scale * nr + w_space, sb_weapons[0][nr], w_width * w_scale, w_height * w_scale, (active) ? 1 : 0.6, active ? 1 : 0.6, active ? 1 : 1, fade * sbar_alpha_fg.value, DRAWFLAG_ADDITIVE);
637 //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);
640 DrawQ_Pic(vid_conwidth.integer - (w_width + w_space) * w_scale, (w_height + w_space) * w_scale * nr + w_space, NULL, w_width * w_scale, w_height * w_scale, 0.3, 0.3, 0.3, fade * sbar_alpha_fg.value, DRAWFLAG_ADDITIVE);
648 void Sbar_DrawInventory (void)
655 if (gamemode == GAME_ROGUE)
657 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
658 Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], sbar_alpha_bg.value);
660 Sbar_DrawAlphaPic (0, -24, rsb_invbar[1], sbar_alpha_bg.value);
663 Sbar_DrawAlphaPic (0, -24, sb_ibar, sbar_alpha_bg.value);
666 for (i=0 ; i<7 ; i++)
668 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<i) )
670 time = cl.item_gettime[i];
671 flashon = (int)((cl.time - time)*10);
674 if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i) )
680 flashon = (flashon%5) + 2;
682 Sbar_DrawAlphaPic (i*24, -16, sb_weapons[flashon][i], sbar_alpha_bg.value);
688 if (gamemode == GAME_HIPNOTIC)
690 int grenadeflashing=0;
691 for (i=0 ; i<4 ; i++)
693 if (cl.stats[STAT_ITEMS] & (1<<hipweapons[i]) )
695 time = cl.item_gettime[hipweapons[i]];
696 flashon = (int)((cl.time - time)*10);
699 if ( cl.stats[STAT_ACTIVEWEAPON] == (1<<hipweapons[i]) )
705 flashon = (flashon%5) + 2;
707 // check grenade launcher
710 if (cl.stats[STAT_ITEMS] & HIT_PROXIMITY_GUN)
715 Sbar_DrawPic (96, -16, hsb_weapons[flashon][2]);
721 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<4))
723 if (!grenadeflashing)
724 Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
727 Sbar_DrawPic (96, -16, hsb_weapons[flashon][4]);
730 Sbar_DrawPic (176 + (i*24), -16, hsb_weapons[flashon][i]);
735 if (gamemode == GAME_ROGUE)
737 // check for powered up weapon.
738 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
740 if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i))
741 Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]);
745 for (i=0 ; i<4 ; i++)
747 sprintf (num, "%3i",cl.stats[STAT_SHELLS+i] );
749 Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[0] - '0');
751 Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[1] - '0');
753 Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0');
757 for (i=0 ; i<6 ; i++)
758 if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
760 //MED 01/04/97 changed keys
761 if (gamemode != GAME_HIPNOTIC || (i>1))
762 Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
765 //MED 01/04/97 added hipnotic items
767 if (gamemode == GAME_HIPNOTIC)
769 for (i=0 ; i<2 ; i++)
770 if (cl.stats[STAT_ITEMS] & (1<<(24+i)))
771 Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
774 if (gamemode == GAME_ROGUE)
777 for (i=0 ; i<2 ; i++)
778 if (cl.stats[STAT_ITEMS] & (1<<(29+i)))
779 Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
784 for (i=0 ; i<4 ; i++)
785 if (cl.stats[STAT_ITEMS] & (1<<(28+i)))
786 Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
790 //=============================================================================
797 void Sbar_DrawFrags (void)
807 l = min(scoreboardlines, 4);
811 for (i = 0;i < l;i++)
817 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
818 DrawQ_Pic (sbar_x + x + 10, sbar_y - 23, NULL, 28, 4, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
819 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
820 DrawQ_Pic (sbar_x + x + 10, sbar_y + 4 - 23, NULL, 28, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
824 sprintf (num, "%3i",f);
826 if (k == cl.viewentity - 1)
828 Sbar_DrawCharacter ( x + 2, -24, 16);
829 Sbar_DrawCharacter ( x + 32 - 4, -24, 17);
831 Sbar_DrawCharacter (x + 8, -24, num[0]);
832 Sbar_DrawCharacter (x + 16, -24, num[1]);
833 Sbar_DrawCharacter (x + 24, -24, num[2]);
838 //=============================================================================
846 void Sbar_DrawFace (void)
850 // PGM 01/19/97 - team color drawing
851 // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
852 if (gamemode == GAME_ROGUE && !cl.islocalgame && (teamplay.integer > 3) && (teamplay.integer < 7))
858 s = &cl.scores[cl.viewentity - 1];
860 Sbar_DrawPic (112, 0, rsb_teambord);
861 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
862 DrawQ_Pic (sbar_x + 113, vid_conheight.integer-SBAR_HEIGHT+3, NULL, 22, 9, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
863 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
864 DrawQ_Pic (sbar_x + 113, vid_conheight.integer-SBAR_HEIGHT+12, NULL, 22, 9, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
868 sprintf (num, "%3i",f);
870 if ((s->colors & 0xf0)==0)
873 Sbar_DrawCharacter(109, 3, 18 + num[0] - '0');
875 Sbar_DrawCharacter(116, 3, 18 + num[1] - '0');
877 Sbar_DrawCharacter(123, 3, 18 + num[2] - '0');
881 Sbar_DrawCharacter ( 109, 3, num[0]);
882 Sbar_DrawCharacter ( 116, 3, num[1]);
883 Sbar_DrawCharacter ( 123, 3, num[2]);
888 // PGM 01/19/97 - team color drawing
890 if ( (cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
891 Sbar_DrawPic (112, 0, sb_face_invis_invuln);
892 else if (cl.stats[STAT_ITEMS] & IT_QUAD)
893 Sbar_DrawPic (112, 0, sb_face_quad );
894 else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
895 Sbar_DrawPic (112, 0, sb_face_invis );
896 else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
897 Sbar_DrawPic (112, 0, sb_face_invuln);
900 f = cl.stats[STAT_HEALTH] / 20;
902 Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]);
906 void Sbar_ShowFPS(void)
908 float fps_x, fps_y, fps_scalex, fps_scaley, fps_height;
912 qboolean red = false;
919 if (showfps.integer > 1)
921 static double currtime, frametimes[32];
922 double newtime, total;
924 static int framecycle = 0;
926 newtime = Sys_DoubleTime();
927 frametimes[framecycle] = newtime - currtime;
930 while(total < 0.2 && count < 32 && frametimes[i = (framecycle - count) & 31])
932 total += frametimes[i];
937 if (showfps.integer == 2)
938 calc = (((double)count / total) + 0.5);
939 else // showfps 3, rapid update
940 calc = ((1.0 / (newtime - currtime)) + 0.5);
945 static double nexttime = 0, lasttime = 0;
946 static float framerate = 0;
947 static int framecount = 0;
949 newtime = Sys_DoubleTime();
950 if (newtime >= nexttime)
952 framerate = ((float)framecount / (newtime - lasttime) + 0.5);
954 nexttime = max(nexttime + 1, lasttime - 1);
961 if ((red = (calc < 1.0f)))
962 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0f / calc + 0.5));
964 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(calc + 0.5));
966 if (showtime.integer)
967 strlcpy(timestring, Sys_TimeString(showtime_format.string), sizeof(timestring));
968 if (showdate.integer)
969 strlcpy(datestring, Sys_TimeString(showdate_format.string), sizeof(datestring));
970 if (fpsstring[0] || timestring[0])
974 fps_height = fps_scaley * ((fpsstring[0] != 0) + (timestring[0] != 0) + (datestring[0] != 0));
975 //fps_y = vid_conheight.integer - sb_lines; // yes this may draw over the sbar
976 //fps_y = bound(0, fps_y, vid_conheight.integer - fps_height);
977 fps_y = vid_conheight.integer - fps_height;
980 fps_x = vid_conwidth.integer - fps_scalex * strlen(fpsstring);
981 DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(fpsstring), fps_scaley, 0, 0, 0, 0.5, 0);
983 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 0, 0, 1, 0);
985 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
990 fps_x = vid_conwidth.integer - fps_scalex * strlen(timestring);
991 DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(timestring), fps_scaley, 0, 0, 0, 0.5, 0);
992 DrawQ_String(fps_x, fps_y, timestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
997 fps_x = vid_conwidth.integer - fps_scalex * strlen(datestring);
998 DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(datestring), fps_scaley, 0, 0, 0, 0.5, 0);
999 DrawQ_String(fps_x, fps_y, datestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
1000 fps_y += fps_scaley;
1005 void Sbar_DrawGauge(float x, float y, cachepic_t *pic, float width, float height, float rangey, float rangeheight, float c1, float c2, float c1r, float c1g, float c1b, float c1a, float c2r, float c2g, float c2b, float c2a, float c3r, float c3g, float c3b, float c3a, int drawflags)
1008 c2 = bound(0, c2, 1);
1009 c1 = bound(0, c1, 1 - c2);
1011 r[1] = rangey + rangeheight * (c2 + c1);
1012 r[2] = rangey + rangeheight * (c2);
1016 DrawQ_SuperPic(x, y + r[0], pic, width, (r[1] - r[0]), 0,(r[0] / height), c3r,c3g,c3b,c3a, 1,(r[0] / height), c3r,c3g,c3b,c3a, 0,(r[1] / height), c3r,c3g,c3b,c3a, 1,(r[1] / height), c3r,c3g,c3b,c3a, drawflags);
1018 DrawQ_SuperPic(x, y + r[1], pic, width, (r[2] - r[1]), 0,(r[1] / height), c1r,c1g,c1b,c1a, 1,(r[1] / height), c1r,c1g,c1b,c1a, 0,(r[2] / height), c1r,c1g,c1b,c1a, 1,(r[2] / height), c1r,c1g,c1b,c1a, drawflags);
1020 DrawQ_SuperPic(x, y + r[2], pic, width, (r[3] - r[2]), 0,(r[2] / height), c2r,c2g,c2b,c2a, 1,(r[2] / height), c2r,c2g,c2b,c2a, 0,(r[3] / height), c2r,c2g,c2b,c2a, 1,(r[3] / height), c2r,c2g,c2b,c2a, drawflags);
1022 DrawQ_SuperPic(x, y + r[3], pic, width, (r[4] - r[3]), 0,(r[3] / height), c3r,c3g,c3b,c3a, 1,(r[3] / height), c3r,c3g,c3b,c3a, 0,(r[4] / height), c3r,c3g,c3b,c3a, 1,(r[4] / height), c3r,c3g,c3b,c3a, drawflags);
1030 extern float v_dmg_time, v_dmg_roll, v_dmg_pitch;
1031 extern cvar_t v_kicktime;
1032 void Sbar_Draw (void)
1034 if(cl.csqc_vidvars.drawenginesbar) //[515]: csqc drawsbar
1036 if (cl.intermission == 1)
1038 Sbar_IntermissionOverlay();
1041 else if (cl.intermission == 2)
1043 Sbar_FinaleOverlay();
1047 if (gamemode == GAME_NETHERWORLD)
1050 else if (gamemode == GAME_SOM)
1052 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1053 Sbar_DrawScoreboard ();
1056 // this is the top left of the sbar area
1058 sbar_y = vid_conheight.integer - 24*3;
1061 if (cl.stats[STAT_ARMOR])
1063 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1064 Sbar_DrawPic(0, 0, somsb_armor[2]);
1065 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1066 Sbar_DrawPic(0, 0, somsb_armor[1]);
1067 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1068 Sbar_DrawPic(0, 0, somsb_armor[0]);
1069 Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1073 Sbar_DrawPic(0, 24, somsb_health);
1074 Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1077 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1078 Sbar_DrawPic(0, 48, somsb_ammo[0]);
1079 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1080 Sbar_DrawPic(0, 48, somsb_ammo[1]);
1081 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1082 Sbar_DrawPic(0, 48, somsb_ammo[2]);
1083 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1084 Sbar_DrawPic(0, 48, somsb_ammo[3]);
1085 Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
1086 if (cl.stats[STAT_SHELLS])
1087 Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
1090 else if (gamemode == GAME_NEXUIZ)
1092 sbar_y = vid_conheight.integer - 47;
1093 sbar_x = (vid_conwidth.integer - 640)/2;
1095 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1097 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1098 Sbar_DrawScoreboard ();
1106 // we have a max time 2s (min time = 0)
1107 if ((time = cl.time - cl.weapontime) < 2)
1109 fade = (1.0 - 0.5 * time);
1111 for (i = 0; i < 8;i++)
1112 if (cl.stats[STAT_ITEMS] & (1 << i))
1113 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1115 if((cl.stats[STAT_ITEMS] & (1<<12)))
1116 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1119 //if (!cl.islocalgame)
1120 // Sbar_DrawFrags ();
1123 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1125 Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1128 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1130 // Nexuiz has no anum pics
1131 //Sbar_DrawNum (36, 0, 666, 3, 1);
1132 // Nexuiz has no disc pic
1133 //Sbar_DrawPic (0, 0, sb_disc);
1137 Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1140 if(cl.stats[STAT_HEALTH] > 100)
1141 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1142 else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1143 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1145 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1147 // AK dont draw ammo for the laser
1148 if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1150 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1151 Sbar_DrawPic (519, 0, sb_ammo[0]);
1152 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1153 Sbar_DrawPic (519, 0, sb_ammo[1]);
1154 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1155 Sbar_DrawPic (519, 0, sb_ammo[2]);
1156 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1157 Sbar_DrawPic (519, 0, sb_ammo[3]);
1159 if(cl.stats[STAT_AMMO] <= 10)
1160 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1162 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1167 DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1170 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1171 // Sbar_MiniDeathmatchOverlay (0, 17);
1173 else if (gamemode == GAME_ZYMOTIC)
1176 float scale = 64.0f / 256.0f;
1177 float kickoffset[3];
1178 VectorClear(kickoffset);
1181 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1182 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1184 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1185 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1186 // left1 16, 48 : 126 -66
1187 // left2 16, 128 : 196 -66
1188 // right 176, 48 : 196 -136
1189 Sbar_DrawGauge(sbar_x + 16 * scale, sbar_y + 48 * scale, zymsb_crosshair_left1, 64*scale, 80*scale, 78*scale, -66*scale, cl.stats[STAT_AMMO] * (1.0 / 200.0), cl.stats[STAT_SHELLS] * (1.0 / 200.0), 0.8f,0.8f,0.0f,1.0f, 0.8f,0.5f,0.0f,1.0f, 0.3f,0.3f,0.3f,1.0f, DRAWFLAG_NORMAL);
1190 Sbar_DrawGauge(sbar_x + 16 * scale, sbar_y + 128 * scale, zymsb_crosshair_left2, 64*scale, 80*scale, 68*scale, -66*scale, cl.stats[STAT_NAILS] * (1.0 / 200.0), cl.stats[STAT_ROCKETS] * (1.0 / 200.0), 0.8f,0.8f,0.0f,1.0f, 0.8f,0.5f,0.0f,1.0f, 0.3f,0.3f,0.3f,1.0f, DRAWFLAG_NORMAL);
1191 Sbar_DrawGauge(sbar_x + 176 * scale, sbar_y + 48 * scale, zymsb_crosshair_right, 64*scale, 160*scale, 148*scale, -136*scale, cl.stats[STAT_ARMOR] * (1.0 / 300.0), cl.stats[STAT_HEALTH] * (1.0 / 300.0), 0.0f,0.5f,1.0f,1.0f, 1.0f,0.0f,0.0f,1.0f, 0.3f,0.3f,0.3f,1.0f, DRAWFLAG_NORMAL);
1192 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1194 float scale = 128.0f / 256.0f;
1195 float healthstart, healthheight, healthstarttc, healthendtc;
1196 float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1197 float ammostart, ammoheight, ammostarttc, ammoendtc;
1198 float clipstart, clipheight, clipstarttc, clipendtc;
1199 float kickoffset[3], offset;
1200 VectorClear(kickoffset);
1203 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1204 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1206 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1207 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1208 offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1209 DrawQ_SuperPic(sbar_x + 120 * scale, sbar_y + ( 88 - offset) * scale, zymsb_crosshair_line, 16 * scale, 36 * scale, 0,0, 1,1,1,1, 1,0, 1,1,1,1, 0,1, 1,1,1,1, 1,1, 1,1,1,1, 0);
1210 DrawQ_SuperPic(sbar_x + (132 + offset) * scale, sbar_y + 120 * scale, zymsb_crosshair_line, 36 * scale, 16 * scale, 0,1, 1,1,1,1, 0,0, 1,1,1,1, 1,1, 1,1,1,1, 1,0, 1,1,1,1, 0);
1211 DrawQ_SuperPic(sbar_x + 120 * scale, sbar_y + (132 + offset) * scale, zymsb_crosshair_line, 16 * scale, 36 * scale, 1,1, 1,1,1,1, 0,1, 1,1,1,1, 1,0, 1,1,1,1, 0,0, 1,1,1,1, 0);
1212 DrawQ_SuperPic(sbar_x + ( 88 - offset) * scale, sbar_y + 120 * scale, zymsb_crosshair_line, 36 * scale, 16 * scale, 1,0, 1,1,1,1, 1,1, 1,1,1,1, 0,0, 1,1,1,1, 0,1, 1,1,1,1, 0);
1213 healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1214 shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1215 healthstart = 204 - healthheight;
1216 shieldstart = healthstart - shieldheight;
1217 healthstarttc = healthstart * (1.0f / 256.0f);
1218 healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1219 shieldstarttc = shieldstart * (1.0f / 256.0f);
1220 shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1221 ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1222 ammostart = 114 - ammoheight;
1223 ammostarttc = ammostart * (1.0f / 256.0f);
1224 ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1225 clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1226 clipstart = 190 - clipheight;
1227 clipstarttc = clipstart * (1.0f / 256.0f);
1228 clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1229 if (healthheight > 0) DrawQ_SuperPic(sbar_x + 0 * scale, sbar_y + healthstart * scale, zymsb_crosshair_health, 256 * scale, healthheight * scale, 0,healthstarttc, 1.0f,0.0f,0.0f,1.0f, 1,healthstarttc, 1.0f,0.0f,0.0f,1.0f, 0,healthendtc, 1.0f,0.0f,0.0f,1.0f, 1,healthendtc, 1.0f,0.0f,0.0f,1.0f, DRAWFLAG_NORMAL);
1230 if (shieldheight > 0) DrawQ_SuperPic(sbar_x + 0 * scale, sbar_y + shieldstart * scale, zymsb_crosshair_health, 256 * scale, shieldheight * scale, 0,shieldstarttc, 0.0f,0.5f,1.0f,1.0f, 1,shieldstarttc, 0.0f,0.5f,1.0f,1.0f, 0,shieldendtc, 0.0f,0.5f,1.0f,1.0f, 1,shieldendtc, 0.0f,0.5f,1.0f,1.0f, DRAWFLAG_NORMAL);
1231 if (ammoheight > 0) DrawQ_SuperPic(sbar_x + 0 * scale, sbar_y + ammostart * scale, zymsb_crosshair_ammo, 256 * scale, ammoheight * scale, 0,ammostarttc, 0.8f,0.8f,0.0f,1.0f, 1,ammostarttc, 0.8f,0.8f,0.0f,1.0f, 0,ammoendtc, 0.8f,0.8f,0.0f,1.0f, 1,ammoendtc, 0.8f,0.8f,0.0f,1.0f, DRAWFLAG_NORMAL);
1232 if (clipheight > 0) DrawQ_SuperPic(sbar_x + 0 * scale, sbar_y + clipstart * scale, zymsb_crosshair_clip, 256 * scale, clipheight * scale, 0,clipstarttc, 1.0f,1.0f,0.0f,1.0f, 1,clipstarttc, 1.0f,1.0f,0.0f,1.0f, 0,clipendtc, 1.0f,1.0f,0.0f,1.0f, 1,clipendtc, 1.0f,1.0f,0.0f,1.0f, DRAWFLAG_NORMAL);
1233 DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1234 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1237 else // Quake and others
1239 sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1240 if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1243 sbar_x = (vid_conwidth.integer - 320)/2;
1247 if (gamemode != GAME_GOODVSBAD2)
1248 Sbar_DrawInventory ();
1249 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1253 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1255 if (gamemode != GAME_GOODVSBAD2)
1256 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1257 Sbar_DrawScoreboard ();
1261 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1263 // keys (hipnotic only)
1264 //MED 01/04/97 moved keys here so they would not be overwritten
1265 if (gamemode == GAME_HIPNOTIC)
1267 if (cl.stats[STAT_ITEMS] & IT_KEY1)
1268 Sbar_DrawPic (209, 3, sb_items[0]);
1269 if (cl.stats[STAT_ITEMS] & IT_KEY2)
1270 Sbar_DrawPic (209, 12, sb_items[1]);
1273 if (gamemode != GAME_GOODVSBAD2)
1275 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1277 Sbar_DrawNum (24, 0, 666, 3, 1);
1278 Sbar_DrawPic (0, 0, sb_disc);
1282 if (gamemode == GAME_ROGUE)
1284 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1285 if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1286 Sbar_DrawPic (0, 0, sb_armor[2]);
1287 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1288 Sbar_DrawPic (0, 0, sb_armor[1]);
1289 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1290 Sbar_DrawPic (0, 0, sb_armor[0]);
1294 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1295 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1296 Sbar_DrawPic (0, 0, sb_armor[2]);
1297 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1298 Sbar_DrawPic (0, 0, sb_armor[1]);
1299 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1300 Sbar_DrawPic (0, 0, sb_armor[0]);
1309 Sbar_DrawNum (154, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1312 if (gamemode == GAME_ROGUE)
1314 if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1315 Sbar_DrawPic (224, 0, sb_ammo[0]);
1316 else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1317 Sbar_DrawPic (224, 0, sb_ammo[1]);
1318 else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1319 Sbar_DrawPic (224, 0, sb_ammo[2]);
1320 else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1321 Sbar_DrawPic (224, 0, sb_ammo[3]);
1322 else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1323 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1324 else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1325 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1326 else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1327 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1331 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1332 Sbar_DrawPic (224, 0, sb_ammo[0]);
1333 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1334 Sbar_DrawPic (224, 0, sb_ammo[1]);
1335 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1336 Sbar_DrawPic (224, 0, sb_ammo[2]);
1337 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1338 Sbar_DrawPic (224, 0, sb_ammo[3]);
1341 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1345 if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1347 if (gamemode == GAME_TRANSFUSION)
1348 Sbar_MiniDeathmatchOverlay (0, 0);
1350 Sbar_MiniDeathmatchOverlay (324, vid_conheight.integer - sb_lines);
1357 if(cl.csqc_vidvars.drawcrosshair)
1358 R_Draw2DCrosshair();
1360 if (cl_prydoncursor.integer)
1361 DrawQ_Pic((cl.cmd.cursor_screen[0] + 1) * 0.5 * vid_conwidth.integer, (cl.cmd.cursor_screen[1] + 1) * 0.5 * vid_conheight.integer, Draw_CachePic(va("gfx/prydoncursor%03i", cl_prydoncursor.integer), true), 0, 0, 1, 1, 1, 1, 0);
1364 //=============================================================================
1368 Sbar_DeathmatchOverlay
1372 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1376 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1378 minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : realtime - s->qw_entertime) / 60.0);
1379 // draw colors behind score
1380 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1381 DrawQ_Pic(x + 14*8, y+1, NULL, 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);
1382 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1383 DrawQ_Pic(x + 14*8, y+4, NULL, 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);
1385 //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);
1386 DrawQ_ColoredString(x, y, va("%c%4i %2i %4i %4i %-4s %s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1390 // draw colors behind score
1391 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1392 DrawQ_Pic(x + 1*8, y+1, NULL, 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);
1393 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1394 DrawQ_Pic(x + 1*8, y+4, NULL, 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);
1396 //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);
1397 DrawQ_ColoredString(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, NULL );
1402 void Sbar_DeathmatchOverlay (void)
1407 // request new ping times every two second
1408 if (cl.last_ping_request < realtime - 2)
1410 cl.last_ping_request = realtime;
1411 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1413 MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
1414 MSG_WriteString(&cls.netcon->message, "pings");
1418 pic = Draw_CachePic ("gfx/ranking", true);
1419 DrawQ_Pic ((vid_conwidth.integer - pic->width)/2, 8, pic, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1424 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1425 x = (vid_conwidth.integer - (6 + 17 + 15) * 8) / 2;
1427 x = (vid_conwidth.integer - (6 + 15) * 8) / 2;
1430 if (Sbar_IsTeammatch ())
1432 // show team scores first
1433 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1434 y += Sbar_PrintScoreboardItem((teams + teamsort[i]), x, y);
1438 for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1439 y += Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1444 Sbar_DeathmatchOverlay
1448 void Sbar_MiniDeathmatchOverlay (int x, int y)
1452 // decide where to print
1453 if (gamemode == GAME_TRANSFUSION)
1454 numlines = (vid_conwidth.integer - x + 127) / 128;
1456 numlines = (vid_conheight.integer - y + 7) / 8;
1458 // give up if there isn't room
1459 if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1466 for (i = 0; i < scoreboardlines; i++)
1467 if (fragsort[i] == cl.playerentity - 1)
1472 i = min(i, scoreboardlines - numlines);
1475 if (gamemode == GAME_TRANSFUSION)
1477 for (;i < scoreboardlines && x < vid_conwidth.integer;i++)
1478 x += 128 + Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1482 for (;i < scoreboardlines && y < vid_conheight.integer;i++)
1483 y += Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1489 Sbar_IntermissionOverlay
1493 void Sbar_IntermissionOverlay (void)
1498 if (cl.gametype == GAME_DEATHMATCH)
1500 Sbar_DeathmatchOverlay ();
1504 sbar_x = (vid_conwidth.integer - 320) >> 1;
1505 sbar_y = (vid_conheight.integer - 200) >> 1;
1507 DrawQ_Pic (sbar_x + 64, sbar_y + 24, Draw_CachePic("gfx/complete", true), 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1508 DrawQ_Pic (sbar_x + 0, sbar_y + 56, Draw_CachePic("gfx/inter", true), 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1511 dig = cl.completed_time/60;
1512 Sbar_DrawNum (160, 64, dig, 3, 0);
1513 num = cl.completed_time - dig*60;
1514 if (gamemode != GAME_NEXUIZ)
1515 Sbar_DrawPic (234,64,sb_colon);
1516 Sbar_DrawPic (246,64,sb_nums[0][num/10]);
1517 Sbar_DrawPic (266,64,sb_nums[0][num%10]);
1519 Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
1520 if (gamemode != GAME_NEXUIZ)
1521 Sbar_DrawPic (232, 104, sb_slash);
1522 Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1524 Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1525 if (gamemode != GAME_NEXUIZ)
1526 Sbar_DrawPic (232, 144, sb_slash);
1527 Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1538 void Sbar_FinaleOverlay (void)
1542 pic = Draw_CachePic ("gfx/finale", true);
1543 DrawQ_Pic((vid_conwidth.integer - pic->width)/2, 16, pic, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);