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 = (int)(cl.time / 60);
599 seconds = (int)(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 static double nexttime = 0, lasttime = 0;
920 static double framerate = 0;
921 static int framecount = 0;
923 newtime = Sys_DoubleTime();
924 if (newtime >= nexttime)
926 framerate = framecount / (newtime - lasttime);
928 nexttime = max(nexttime + 0.1, lasttime - 0.1);
934 if ((red = (calc < 1.0f)))
935 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0f / calc + 0.5));
937 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(calc + 0.5));
939 if (showtime.integer)
940 strlcpy(timestring, Sys_TimeString(showtime_format.string), sizeof(timestring));
941 if (showdate.integer)
942 strlcpy(datestring, Sys_TimeString(showdate_format.string), sizeof(datestring));
943 if (fpsstring[0] || timestring[0])
947 fps_height = fps_scaley * ((fpsstring[0] != 0) + (timestring[0] != 0) + (datestring[0] != 0));
948 //fps_y = vid_conheight.integer - sb_lines; // yes this may draw over the sbar
949 //fps_y = bound(0, fps_y, vid_conheight.integer - fps_height);
950 fps_y = vid_conheight.integer - fps_height;
953 fps_x = vid_conwidth.integer - fps_scalex * strlen(fpsstring);
954 DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(fpsstring), fps_scaley, 0, 0, 0, 0.5, 0);
956 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 0, 0, 1, 0);
958 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
963 fps_x = vid_conwidth.integer - fps_scalex * strlen(timestring);
964 DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(timestring), fps_scaley, 0, 0, 0, 0.5, 0);
965 DrawQ_String(fps_x, fps_y, timestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
970 fps_x = vid_conwidth.integer - fps_scalex * strlen(datestring);
971 DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(datestring), fps_scaley, 0, 0, 0, 0.5, 0);
972 DrawQ_String(fps_x, fps_y, datestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
978 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)
981 c2 = bound(0, c2, 1);
982 c1 = bound(0, c1, 1 - c2);
984 r[1] = rangey + rangeheight * (c2 + c1);
985 r[2] = rangey + rangeheight * (c2);
989 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);
991 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);
993 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);
995 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);
1003 extern float v_dmg_time, v_dmg_roll, v_dmg_pitch;
1004 extern cvar_t v_kicktime;
1005 void Sbar_Draw (void)
1007 if(cl.csqc_vidvars.drawenginesbar) //[515]: csqc drawsbar
1009 if (cl.intermission == 1)
1011 Sbar_IntermissionOverlay();
1014 else if (cl.intermission == 2)
1016 Sbar_FinaleOverlay();
1020 if (gamemode == GAME_NETHERWORLD)
1023 else if (gamemode == GAME_SOM)
1025 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1026 Sbar_DrawScoreboard ();
1029 // this is the top left of the sbar area
1031 sbar_y = vid_conheight.integer - 24*3;
1034 if (cl.stats[STAT_ARMOR])
1036 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1037 Sbar_DrawPic(0, 0, somsb_armor[2]);
1038 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1039 Sbar_DrawPic(0, 0, somsb_armor[1]);
1040 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1041 Sbar_DrawPic(0, 0, somsb_armor[0]);
1042 Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1046 Sbar_DrawPic(0, 24, somsb_health);
1047 Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1050 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1051 Sbar_DrawPic(0, 48, somsb_ammo[0]);
1052 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1053 Sbar_DrawPic(0, 48, somsb_ammo[1]);
1054 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1055 Sbar_DrawPic(0, 48, somsb_ammo[2]);
1056 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1057 Sbar_DrawPic(0, 48, somsb_ammo[3]);
1058 Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
1059 if (cl.stats[STAT_SHELLS])
1060 Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
1063 else if (gamemode == GAME_NEXUIZ)
1065 sbar_y = vid_conheight.integer - 47;
1066 sbar_x = (vid_conwidth.integer - 640)/2;
1068 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1070 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1071 Sbar_DrawScoreboard ();
1079 // we have a max time 2s (min time = 0)
1080 if ((time = cl.time - cl.weapontime) < 2)
1082 fade = (1.0 - 0.5 * time);
1084 for (i = 0; i < 8;i++)
1085 if (cl.stats[STAT_ITEMS] & (1 << i))
1086 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1088 if((cl.stats[STAT_ITEMS] & (1<<12)))
1089 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1092 //if (!cl.islocalgame)
1093 // Sbar_DrawFrags ();
1096 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1098 Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1101 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1103 // Nexuiz has no anum pics
1104 //Sbar_DrawNum (36, 0, 666, 3, 1);
1105 // Nexuiz has no disc pic
1106 //Sbar_DrawPic (0, 0, sb_disc);
1110 Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1113 if(cl.stats[STAT_HEALTH] > 100)
1114 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1115 else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1116 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1118 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1120 // AK dont draw ammo for the laser
1121 if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1123 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1124 Sbar_DrawPic (519, 0, sb_ammo[0]);
1125 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1126 Sbar_DrawPic (519, 0, sb_ammo[1]);
1127 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1128 Sbar_DrawPic (519, 0, sb_ammo[2]);
1129 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1130 Sbar_DrawPic (519, 0, sb_ammo[3]);
1132 if(cl.stats[STAT_AMMO] <= 10)
1133 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1135 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1140 DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1143 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1144 // Sbar_MiniDeathmatchOverlay (0, 17);
1146 else if (gamemode == GAME_ZYMOTIC)
1149 float scale = 64.0f / 256.0f;
1150 float kickoffset[3];
1151 VectorClear(kickoffset);
1154 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1155 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1157 sbar_x = (int)((vid_conwidth.integer - 256 * scale)/2 + kickoffset[0]);
1158 sbar_y = (int)((vid_conheight.integer - 256 * scale)/2 + kickoffset[1]);
1159 // left1 16, 48 : 126 -66
1160 // left2 16, 128 : 196 -66
1161 // right 176, 48 : 196 -136
1162 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);
1163 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);
1164 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);
1165 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1167 float scale = 128.0f / 256.0f;
1168 float healthstart, healthheight, healthstarttc, healthendtc;
1169 float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1170 float ammostart, ammoheight, ammostarttc, ammoendtc;
1171 float clipstart, clipheight, clipstarttc, clipendtc;
1172 float kickoffset[3], offset;
1173 VectorClear(kickoffset);
1176 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1177 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1179 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1180 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1181 offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1182 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);
1183 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);
1184 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);
1185 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);
1186 healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1187 shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1188 healthstart = 204 - healthheight;
1189 shieldstart = healthstart - shieldheight;
1190 healthstarttc = healthstart * (1.0f / 256.0f);
1191 healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1192 shieldstarttc = shieldstart * (1.0f / 256.0f);
1193 shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1194 ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1195 ammostart = 114 - ammoheight;
1196 ammostarttc = ammostart * (1.0f / 256.0f);
1197 ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1198 clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1199 clipstart = 190 - clipheight;
1200 clipstarttc = clipstart * (1.0f / 256.0f);
1201 clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1202 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);
1203 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);
1204 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);
1205 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);
1206 DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1207 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1210 else // Quake and others
1212 sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1213 if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1216 sbar_x = (vid_conwidth.integer - 320)/2;
1220 if (gamemode != GAME_GOODVSBAD2)
1221 Sbar_DrawInventory ();
1222 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1226 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1228 if (gamemode != GAME_GOODVSBAD2)
1229 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1230 Sbar_DrawScoreboard ();
1234 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1236 // keys (hipnotic only)
1237 //MED 01/04/97 moved keys here so they would not be overwritten
1238 if (gamemode == GAME_HIPNOTIC)
1240 if (cl.stats[STAT_ITEMS] & IT_KEY1)
1241 Sbar_DrawPic (209, 3, sb_items[0]);
1242 if (cl.stats[STAT_ITEMS] & IT_KEY2)
1243 Sbar_DrawPic (209, 12, sb_items[1]);
1246 if (gamemode != GAME_GOODVSBAD2)
1248 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1250 Sbar_DrawNum (24, 0, 666, 3, 1);
1251 Sbar_DrawPic (0, 0, sb_disc);
1255 if (gamemode == GAME_ROGUE)
1257 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1258 if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1259 Sbar_DrawPic (0, 0, sb_armor[2]);
1260 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1261 Sbar_DrawPic (0, 0, sb_armor[1]);
1262 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1263 Sbar_DrawPic (0, 0, sb_armor[0]);
1267 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1268 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1269 Sbar_DrawPic (0, 0, sb_armor[2]);
1270 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1271 Sbar_DrawPic (0, 0, sb_armor[1]);
1272 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1273 Sbar_DrawPic (0, 0, sb_armor[0]);
1282 Sbar_DrawNum (154, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1285 if (gamemode == GAME_ROGUE)
1287 if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1288 Sbar_DrawPic (224, 0, sb_ammo[0]);
1289 else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1290 Sbar_DrawPic (224, 0, sb_ammo[1]);
1291 else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1292 Sbar_DrawPic (224, 0, sb_ammo[2]);
1293 else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1294 Sbar_DrawPic (224, 0, sb_ammo[3]);
1295 else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1296 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1297 else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1298 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1299 else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1300 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1304 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1305 Sbar_DrawPic (224, 0, sb_ammo[0]);
1306 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1307 Sbar_DrawPic (224, 0, sb_ammo[1]);
1308 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1309 Sbar_DrawPic (224, 0, sb_ammo[2]);
1310 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1311 Sbar_DrawPic (224, 0, sb_ammo[3]);
1314 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1318 if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1320 if (gamemode == GAME_TRANSFUSION)
1321 Sbar_MiniDeathmatchOverlay (0, 0);
1323 Sbar_MiniDeathmatchOverlay (324, vid_conheight.integer - sb_lines);
1330 if(cl.csqc_vidvars.drawcrosshair)
1331 R_Draw2DCrosshair();
1333 if (cl_prydoncursor.integer)
1334 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);
1337 //=============================================================================
1341 Sbar_DeathmatchOverlay
1345 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1349 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1351 minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : realtime - s->qw_entertime) / 60.0);
1352 // draw colors behind score
1353 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1354 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);
1355 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1356 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);
1358 //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);
1359 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 );
1363 // draw colors behind score
1364 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1365 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);
1366 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1367 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);
1369 //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);
1370 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 );
1375 void Sbar_DeathmatchOverlay (void)
1380 // request new ping times every two second
1381 if (cl.last_ping_request < realtime - 2)
1383 cl.last_ping_request = realtime;
1384 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1386 MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
1387 MSG_WriteString(&cls.netcon->message, "pings");
1391 pic = Draw_CachePic ("gfx/ranking", true);
1392 DrawQ_Pic ((vid_conwidth.integer - pic->width)/2, 8, pic, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1397 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1398 x = (vid_conwidth.integer - (6 + 17 + 15) * 8) / 2;
1400 x = (vid_conwidth.integer - (6 + 15) * 8) / 2;
1403 if (Sbar_IsTeammatch ())
1405 // show team scores first
1406 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1407 y += (int)Sbar_PrintScoreboardItem((teams + teamsort[i]), x, y);
1411 for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1412 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1417 Sbar_DeathmatchOverlay
1421 void Sbar_MiniDeathmatchOverlay (int x, int y)
1425 // decide where to print
1426 if (gamemode == GAME_TRANSFUSION)
1427 numlines = (vid_conwidth.integer - x + 127) / 128;
1429 numlines = (vid_conheight.integer - y + 7) / 8;
1431 // give up if there isn't room
1432 if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1439 for (i = 0; i < scoreboardlines; i++)
1440 if (fragsort[i] == cl.playerentity - 1)
1445 i = min(i, scoreboardlines - numlines);
1448 if (gamemode == GAME_TRANSFUSION)
1450 for (;i < scoreboardlines && x < vid_conwidth.integer;i++)
1451 x += 128 + (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1455 for (;i < scoreboardlines && y < vid_conheight.integer;i++)
1456 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1462 Sbar_IntermissionOverlay
1466 void Sbar_IntermissionOverlay (void)
1471 if (cl.gametype == GAME_DEATHMATCH)
1473 Sbar_DeathmatchOverlay ();
1477 sbar_x = (vid_conwidth.integer - 320) >> 1;
1478 sbar_y = (vid_conheight.integer - 200) >> 1;
1480 DrawQ_Pic (sbar_x + 64, sbar_y + 24, Draw_CachePic("gfx/complete", true), 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1481 DrawQ_Pic (sbar_x + 0, sbar_y + 56, Draw_CachePic("gfx/inter", true), 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1484 dig = (int)cl.completed_time / 60;
1485 Sbar_DrawNum (160, 64, dig, 3, 0);
1486 num = (int)cl.completed_time - dig*60;
1487 if (gamemode != GAME_NEXUIZ)
1488 Sbar_DrawPic (234,64,sb_colon);
1489 Sbar_DrawPic (246,64,sb_nums[0][num/10]);
1490 Sbar_DrawPic (266,64,sb_nums[0][num%10]);
1492 Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
1493 if (gamemode != GAME_NEXUIZ)
1494 Sbar_DrawPic (232, 104, sb_slash);
1495 Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1497 Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1498 if (gamemode != GAME_NEXUIZ)
1499 Sbar_DrawPic (232, 144, sb_slash);
1500 Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1511 void Sbar_FinaleOverlay (void)
1515 pic = Draw_CachePic ("gfx/finale", true);
1516 DrawQ_Pic((vid_conwidth.integer - pic->width)/2, 16, pic, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);