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 cachepic_t *sb_ranking;
85 cachepic_t *sb_complete;
87 cachepic_t *sb_finale;
89 cvar_t showfps = {CVAR_SAVE, "showfps", "0", "shows your rendered fps (frames per second)"};
90 cvar_t showtime = {CVAR_SAVE, "showtime", "0", "shows current time of day (useful on screenshots)"};
91 cvar_t showtime_format = {CVAR_SAVE, "showtime_format", "%H:%M:%S", "format string for time of day"};
92 cvar_t showdate = {CVAR_SAVE, "showdate", "0", "shows current date (useful on screenshots)"};
93 cvar_t showdate_format = {CVAR_SAVE, "showdate_format", "%Y-%m-%d", "format string for date"};
94 cvar_t sbar_alpha_bg = {CVAR_SAVE, "sbar_alpha_bg", "0.4", "opacity value of the statusbar background image"};
95 cvar_t sbar_alpha_fg = {CVAR_SAVE, "sbar_alpha_fg", "1", "opacity value of the statusbar weapon/item icons and numbers"};
97 cvar_t cl_deathscoreboard = {0, "cl_deathscoreboard", "1", "shows scoreboard (+showscores) while dead"};
99 void Sbar_MiniDeathmatchOverlay (int x, int y);
100 void Sbar_DeathmatchOverlay (void);
101 void Sbar_IntermissionOverlay (void);
102 void Sbar_FinaleOverlay (void);
112 void Sbar_ShowScores (void)
116 sb_showscores = true;
126 void Sbar_DontShowScores (void)
128 sb_showscores = false;
131 void sbar_start(void)
135 if (gamemode == GAME_NETHERWORLD)
138 else if (gamemode == GAME_SOM)
140 sb_disc = Draw_CachePic("gfx/disc", true);
142 for (i = 0;i < 10;i++)
143 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
145 somsb_health = Draw_CachePic("gfx/hud_health", true);
146 somsb_ammo[0] = Draw_CachePic("gfx/sb_shells", true);
147 somsb_ammo[1] = Draw_CachePic("gfx/sb_nails", true);
148 somsb_ammo[2] = Draw_CachePic("gfx/sb_rocket", true);
149 somsb_ammo[3] = Draw_CachePic("gfx/sb_cells", true);
150 somsb_armor[0] = Draw_CachePic("gfx/sb_armor1", true);
151 somsb_armor[1] = Draw_CachePic("gfx/sb_armor2", true);
152 somsb_armor[2] = Draw_CachePic("gfx/sb_armor3", true);
154 else if (gamemode == GAME_NEXUIZ)
156 for (i = 0;i < 10;i++)
157 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
158 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus", true);
160 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells", true);
161 sb_ammo[1] = Draw_CachePic ("gfx/sb_bullets", true);
162 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket", true);
163 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells", true);
165 sb_items[2] = Draw_CachePic ("gfx/sb_slowmo", true);
166 sb_items[3] = Draw_CachePic ("gfx/sb_invinc", true);
167 sb_items[4] = Draw_CachePic ("gfx/sb_energy", true);
168 sb_items[5] = Draw_CachePic ("gfx/sb_str", true);
170 sb_sbar = Draw_CachePic("gfx/sbar", true);
171 sb_sbar_minimal = Draw_CachePic("gfx/sbar_minimal", true);
172 sb_sbar_overlay = Draw_CachePic("gfx/sbar_overlay", true);
174 for(i = 0; i < 9;i++)
175 sb_weapons[0][i] = Draw_CachePic(va("gfx/inv_weapon%i",i), true);
177 else if (gamemode == GAME_ZYMOTIC)
179 zymsb_crosshair_center = Draw_CachePic ("gfx/hud/crosshair_center", true);
180 zymsb_crosshair_line = Draw_CachePic ("gfx/hud/crosshair_line", true);
181 zymsb_crosshair_health = Draw_CachePic ("gfx/hud/crosshair_health", true);
182 zymsb_crosshair_clip = Draw_CachePic ("gfx/hud/crosshair_clip", true);
183 zymsb_crosshair_ammo = Draw_CachePic ("gfx/hud/crosshair_ammo", true);
184 zymsb_crosshair_background = Draw_CachePic ("gfx/hud/crosshair_background", true);
185 zymsb_crosshair_left1 = Draw_CachePic ("gfx/hud/crosshair_left1", true);
186 zymsb_crosshair_left2 = Draw_CachePic ("gfx/hud/crosshair_left2", true);
187 zymsb_crosshair_right = Draw_CachePic ("gfx/hud/crosshair_right", true);
191 sb_disc = Draw_CachePic("gfx/disc", true);
193 for (i = 0;i < 10;i++)
195 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
196 sb_nums[1][i] = Draw_CachePic (va("gfx/anum_%i",i), true);
199 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus", true);
200 sb_nums[1][10] = Draw_CachePic ("gfx/anum_minus", true);
202 sb_colon = Draw_CachePic ("gfx/num_colon", true);
203 sb_slash = Draw_CachePic ("gfx/num_slash", true);
205 sb_weapons[0][0] = Draw_CachePic ("gfx/inv_shotgun", true);
206 sb_weapons[0][1] = Draw_CachePic ("gfx/inv_sshotgun", true);
207 sb_weapons[0][2] = Draw_CachePic ("gfx/inv_nailgun", true);
208 sb_weapons[0][3] = Draw_CachePic ("gfx/inv_snailgun", true);
209 sb_weapons[0][4] = Draw_CachePic ("gfx/inv_rlaunch", true);
210 sb_weapons[0][5] = Draw_CachePic ("gfx/inv_srlaunch", true);
211 sb_weapons[0][6] = Draw_CachePic ("gfx/inv_lightng", true);
213 sb_weapons[1][0] = Draw_CachePic ("gfx/inv2_shotgun", true);
214 sb_weapons[1][1] = Draw_CachePic ("gfx/inv2_sshotgun", true);
215 sb_weapons[1][2] = Draw_CachePic ("gfx/inv2_nailgun", true);
216 sb_weapons[1][3] = Draw_CachePic ("gfx/inv2_snailgun", true);
217 sb_weapons[1][4] = Draw_CachePic ("gfx/inv2_rlaunch", true);
218 sb_weapons[1][5] = Draw_CachePic ("gfx/inv2_srlaunch", true);
219 sb_weapons[1][6] = Draw_CachePic ("gfx/inv2_lightng", true);
221 for (i = 0;i < 5;i++)
223 sb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_shotgun",i+1), true);
224 sb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_sshotgun",i+1), true);
225 sb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_nailgun",i+1), true);
226 sb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_snailgun",i+1), true);
227 sb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_rlaunch",i+1), true);
228 sb_weapons[2+i][5] = Draw_CachePic (va("gfx/inva%i_srlaunch",i+1), true);
229 sb_weapons[2+i][6] = Draw_CachePic (va("gfx/inva%i_lightng",i+1), true);
232 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells", true);
233 sb_ammo[1] = Draw_CachePic ("gfx/sb_nails", true);
234 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket", true);
235 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells", true);
237 sb_armor[0] = Draw_CachePic ("gfx/sb_armor1", true);
238 sb_armor[1] = Draw_CachePic ("gfx/sb_armor2", true);
239 sb_armor[2] = Draw_CachePic ("gfx/sb_armor3", true);
241 sb_items[0] = Draw_CachePic ("gfx/sb_key1", true);
242 sb_items[1] = Draw_CachePic ("gfx/sb_key2", true);
243 sb_items[2] = Draw_CachePic ("gfx/sb_invis", true);
244 sb_items[3] = Draw_CachePic ("gfx/sb_invuln", true);
245 sb_items[4] = Draw_CachePic ("gfx/sb_suit", true);
246 sb_items[5] = Draw_CachePic ("gfx/sb_quad", true);
248 sb_sigil[0] = Draw_CachePic ("gfx/sb_sigil1", true);
249 sb_sigil[1] = Draw_CachePic ("gfx/sb_sigil2", true);
250 sb_sigil[2] = Draw_CachePic ("gfx/sb_sigil3", true);
251 sb_sigil[3] = Draw_CachePic ("gfx/sb_sigil4", true);
253 sb_faces[4][0] = Draw_CachePic ("gfx/face1", true);
254 sb_faces[4][1] = Draw_CachePic ("gfx/face_p1", true);
255 sb_faces[3][0] = Draw_CachePic ("gfx/face2", true);
256 sb_faces[3][1] = Draw_CachePic ("gfx/face_p2", true);
257 sb_faces[2][0] = Draw_CachePic ("gfx/face3", true);
258 sb_faces[2][1] = Draw_CachePic ("gfx/face_p3", true);
259 sb_faces[1][0] = Draw_CachePic ("gfx/face4", true);
260 sb_faces[1][1] = Draw_CachePic ("gfx/face_p4", true);
261 sb_faces[0][0] = Draw_CachePic ("gfx/face5", true);
262 sb_faces[0][1] = Draw_CachePic ("gfx/face_p5", true);
264 sb_face_invis = Draw_CachePic ("gfx/face_invis", true);
265 sb_face_invuln = Draw_CachePic ("gfx/face_invul2", true);
266 sb_face_invis_invuln = Draw_CachePic ("gfx/face_inv2", true);
267 sb_face_quad = Draw_CachePic ("gfx/face_quad", true);
269 sb_sbar = Draw_CachePic ("gfx/sbar", true);
270 sb_ibar = Draw_CachePic ("gfx/ibar", true);
271 sb_scorebar = Draw_CachePic ("gfx/scorebar", true);
273 //MED 01/04/97 added new hipnotic weapons
274 if (gamemode == GAME_HIPNOTIC)
276 hsb_weapons[0][0] = Draw_CachePic ("gfx/inv_laser", true);
277 hsb_weapons[0][1] = Draw_CachePic ("gfx/inv_mjolnir", true);
278 hsb_weapons[0][2] = Draw_CachePic ("gfx/inv_gren_prox", true);
279 hsb_weapons[0][3] = Draw_CachePic ("gfx/inv_prox_gren", true);
280 hsb_weapons[0][4] = Draw_CachePic ("gfx/inv_prox", true);
282 hsb_weapons[1][0] = Draw_CachePic ("gfx/inv2_laser", true);
283 hsb_weapons[1][1] = Draw_CachePic ("gfx/inv2_mjolnir", true);
284 hsb_weapons[1][2] = Draw_CachePic ("gfx/inv2_gren_prox", true);
285 hsb_weapons[1][3] = Draw_CachePic ("gfx/inv2_prox_gren", true);
286 hsb_weapons[1][4] = Draw_CachePic ("gfx/inv2_prox", true);
288 for (i = 0;i < 5;i++)
290 hsb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_laser",i+1), true);
291 hsb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_mjolnir",i+1), true);
292 hsb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_gren_prox",i+1), true);
293 hsb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_prox_gren",i+1), true);
294 hsb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_prox",i+1), true);
297 hsb_items[0] = Draw_CachePic ("gfx/sb_wsuit", true);
298 hsb_items[1] = Draw_CachePic ("gfx/sb_eshld", true);
300 else if (gamemode == GAME_ROGUE)
302 rsb_invbar[0] = Draw_CachePic ("gfx/r_invbar1", true);
303 rsb_invbar[1] = Draw_CachePic ("gfx/r_invbar2", true);
305 rsb_weapons[0] = Draw_CachePic ("gfx/r_lava", true);
306 rsb_weapons[1] = Draw_CachePic ("gfx/r_superlava", true);
307 rsb_weapons[2] = Draw_CachePic ("gfx/r_gren", true);
308 rsb_weapons[3] = Draw_CachePic ("gfx/r_multirock", true);
309 rsb_weapons[4] = Draw_CachePic ("gfx/r_plasma", true);
311 rsb_items[0] = Draw_CachePic ("gfx/r_shield1", true);
312 rsb_items[1] = Draw_CachePic ("gfx/r_agrav1", true);
314 // PGM 01/19/97 - team color border
315 rsb_teambord = Draw_CachePic ("gfx/r_teambord", true);
316 // PGM 01/19/97 - team color border
318 rsb_ammo[0] = Draw_CachePic ("gfx/r_ammolava", true);
319 rsb_ammo[1] = Draw_CachePic ("gfx/r_ammomulti", true);
320 rsb_ammo[2] = Draw_CachePic ("gfx/r_ammoplasma", true);
324 sb_ranking = Draw_CachePic ("gfx/ranking", true);
325 sb_complete = Draw_CachePic ("gfx/complete", true);
326 sb_inter = Draw_CachePic ("gfx/inter", true);
327 sb_finale = Draw_CachePic ("gfx/finale", true);
330 void sbar_shutdown(void)
334 void sbar_newmap(void)
338 void Sbar_Init (void)
340 Cmd_AddCommand ("+showscores", Sbar_ShowScores, "show scoreboard");
341 Cmd_AddCommand ("-showscores", Sbar_DontShowScores, "hide scoreboard");
342 Cvar_RegisterVariable (&showfps);
343 Cvar_RegisterVariable (&showtime);
344 Cvar_RegisterVariable (&showtime_format);
345 Cvar_RegisterVariable (&showdate);
346 Cvar_RegisterVariable (&showdate_format);
347 Cvar_RegisterVariable (&sbar_alpha_bg);
348 Cvar_RegisterVariable (&sbar_alpha_fg);
349 Cvar_RegisterVariable (&cl_deathscoreboard);
351 R_RegisterModule("sbar", sbar_start, sbar_shutdown, sbar_newmap);
355 //=============================================================================
357 // drawing routines are relative to the status bar location
366 void Sbar_DrawPic (int x, int y, cachepic_t *pic)
368 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, sbar_alpha_fg.value, 0);
371 void Sbar_DrawAlphaPic (int x, int y, cachepic_t *pic, float alpha)
373 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, alpha, 0);
380 Draws one solid graphics character
383 void Sbar_DrawCharacter (int x, int y, int num)
385 DrawQ_String (sbar_x + x + 4 , sbar_y + y, va("%c", num), 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0);
393 void Sbar_DrawString (int x, int y, char *str)
395 DrawQ_String (sbar_x + x, sbar_y + y, str, 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0);
403 void Sbar_DrawNum (int x, int y, int num, int digits, int color)
408 l = sprintf(str, "%i", num);
422 Sbar_DrawPic (x, y, sb_nums[color][frame]);
435 void Sbar_DrawXNum (int x, int y, int num, int digits, int lettersize, float r, float g, float b, float a, int flags)
440 l = sprintf(str, "%i", num);
445 x += (digits-l) * lettersize;
454 DrawQ_Pic (sbar_x + x, sbar_y + y, sb_nums[0][frame],lettersize,lettersize,r,g,b,a * sbar_alpha_fg.value,flags);
461 //=============================================================================
464 int Sbar_IsTeammatch()
466 // currently only nexuiz uses the team score board
467 return ((gamemode == GAME_NEXUIZ)
468 && (teamplay.integer > 0));
476 static int fragsort[MAX_SCOREBOARD];
477 static int scoreboardlines;
479 //[515]: Sbar_GetPlayer for csqc "getplayerkey" func
480 int Sbar_GetPlayer (int index)
485 if(index >= scoreboardlines)
487 index = fragsort[index];
489 if(index >= scoreboardlines)
494 static scoreboard_t teams[MAX_SCOREBOARD];
495 static int teamsort[MAX_SCOREBOARD];
496 static int teamlines;
497 void Sbar_SortFrags (void)
503 for (i=0 ; i<cl.maxclients ; i++)
505 if (cl.scores[i].name[0])
507 fragsort[scoreboardlines] = i;
512 for (i=0 ; i<scoreboardlines ; i++)
513 for (j=0 ; j<scoreboardlines-1-i ; j++)
514 if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j+1]].frags)
517 fragsort[j] = fragsort[j+1];
522 if (Sbar_IsTeammatch ())
524 // now sort players by teams.
525 for (i=0 ; i<scoreboardlines ; i++)
527 for (j=0 ; j<scoreboardlines-1-i ; j++)
529 if (cl.scores[fragsort[j]].colors < cl.scores[fragsort[j+1]].colors)
532 fragsort[j] = fragsort[j+1];
538 // calculate team scores
540 for (i=0 ; i<scoreboardlines ; i++)
542 if (color != (cl.scores[fragsort[i]].colors & 15))
544 color = cl.scores[fragsort[i]].colors & 15;
548 strcpy(teams[teamlines-1].name, "^1Red Team");
549 else if (color == 13)
550 strcpy(teams[teamlines-1].name, "^4Blue Team");
552 strcpy(teams[teamlines-1].name, "^6Pink Team");
553 else if (color == 12)
554 strcpy(teams[teamlines-1].name, "^3Yellow Team");
556 strcpy(teams[teamlines-1].name, "Total Team Score");
558 teams[teamlines-1].frags = 0;
559 teams[teamlines-1].colors = color + 16 * color;
562 if (cl.scores[fragsort[i]].frags != -666)
564 // do not add spedcators
565 // (ugly hack for nexuiz)
566 teams[teamlines-1].frags += cl.scores[fragsort[i]].frags;
570 // now sort teams by scores.
571 for (i=0 ; i<teamlines ; i++)
573 for (i=0 ; i<teamlines ; i++)
575 for (j=0 ; j<teamlines-1-i ; j++)
577 if (teams[teamsort[j]].frags < teams[teamsort[j+1]].frags)
580 teamsort[j] = teamsort[j+1];
593 void Sbar_SoloScoreboard (void)
596 int minutes, seconds, tens, units;
599 if (gamemode != GAME_NEXUIZ) {
600 sprintf (str,"Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
601 Sbar_DrawString (8, 4, str);
603 sprintf (str,"Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
604 Sbar_DrawString (8, 12, str);
608 minutes = (int)(cl.time / 60);
609 seconds = (int)(cl.time - 60*minutes);
611 units = seconds - 10*tens;
612 sprintf (str,"Time :%3i:%i%i", minutes, tens, units);
613 Sbar_DrawString (184, 4, str);
616 if (gamemode == GAME_NEXUIZ) {
617 l = (int) strlen (cl.worldmodel->name);
618 Sbar_DrawString (232 - l*4, 12, cl.worldmodel->name);
620 l = (int) strlen (cl.levelname);
621 Sbar_DrawString (232 - l*4, 12, cl.levelname);
630 void Sbar_DrawScoreboard (void)
632 Sbar_SoloScoreboard ();
633 if (cl.gametype == GAME_DEATHMATCH)
634 Sbar_DeathmatchOverlay ();
637 //=============================================================================
639 // AK to make DrawInventory smaller
640 static void Sbar_DrawWeapon(int nr, float fade, int active)
642 // width = 300, height = 100
643 const int w_width = 300, w_height = 100, w_space = 10;
644 const float w_scale = 0.4;
646 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);
647 //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);
650 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);
658 void Sbar_DrawInventory (void)
665 if (gamemode == GAME_ROGUE)
667 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
668 Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], sbar_alpha_bg.value);
670 Sbar_DrawAlphaPic (0, -24, rsb_invbar[1], sbar_alpha_bg.value);
673 Sbar_DrawAlphaPic (0, -24, sb_ibar, sbar_alpha_bg.value);
676 for (i=0 ; i<7 ; i++)
678 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<i) )
680 time = cl.item_gettime[i];
681 flashon = (int)((cl.time - time)*10);
684 if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i) )
690 flashon = (flashon%5) + 2;
692 Sbar_DrawAlphaPic (i*24, -16, sb_weapons[flashon][i], sbar_alpha_bg.value);
698 if (gamemode == GAME_HIPNOTIC)
700 int grenadeflashing=0;
701 for (i=0 ; i<4 ; i++)
703 if (cl.stats[STAT_ITEMS] & (1<<hipweapons[i]) )
705 time = cl.item_gettime[hipweapons[i]];
706 flashon = (int)((cl.time - time)*10);
709 if ( cl.stats[STAT_ACTIVEWEAPON] == (1<<hipweapons[i]) )
715 flashon = (flashon%5) + 2;
717 // check grenade launcher
720 if (cl.stats[STAT_ITEMS] & HIT_PROXIMITY_GUN)
725 Sbar_DrawPic (96, -16, hsb_weapons[flashon][2]);
731 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<4))
733 if (!grenadeflashing)
734 Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
737 Sbar_DrawPic (96, -16, hsb_weapons[flashon][4]);
740 Sbar_DrawPic (176 + (i*24), -16, hsb_weapons[flashon][i]);
745 if (gamemode == GAME_ROGUE)
747 // check for powered up weapon.
748 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
750 if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i))
751 Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]);
755 for (i=0 ; i<4 ; i++)
757 sprintf (num, "%3i",cl.stats[STAT_SHELLS+i] );
759 Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[0] - '0');
761 Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[1] - '0');
763 Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0');
767 for (i=0 ; i<6 ; i++)
768 if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
770 //MED 01/04/97 changed keys
771 if (gamemode != GAME_HIPNOTIC || (i>1))
772 Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
775 //MED 01/04/97 added hipnotic items
777 if (gamemode == GAME_HIPNOTIC)
779 for (i=0 ; i<2 ; i++)
780 if (cl.stats[STAT_ITEMS] & (1<<(24+i)))
781 Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
784 if (gamemode == GAME_ROGUE)
787 for (i=0 ; i<2 ; i++)
788 if (cl.stats[STAT_ITEMS] & (1<<(29+i)))
789 Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
794 for (i=0 ; i<4 ; i++)
795 if (cl.stats[STAT_ITEMS] & (1<<(28+i)))
796 Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
800 //=============================================================================
807 void Sbar_DrawFrags (void)
817 l = min(scoreboardlines, 4);
821 for (i = 0;i < l;i++)
827 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
828 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);
829 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
830 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);
834 sprintf (num, "%3i",f);
836 if (k == cl.viewentity - 1)
838 Sbar_DrawCharacter ( x + 2, -24, 16);
839 Sbar_DrawCharacter ( x + 32 - 4, -24, 17);
841 Sbar_DrawCharacter (x + 8, -24, num[0]);
842 Sbar_DrawCharacter (x + 16, -24, num[1]);
843 Sbar_DrawCharacter (x + 24, -24, num[2]);
848 //=============================================================================
856 void Sbar_DrawFace (void)
860 // PGM 01/19/97 - team color drawing
861 // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
862 if (gamemode == GAME_ROGUE && !cl.islocalgame && (teamplay.integer > 3) && (teamplay.integer < 7))
868 s = &cl.scores[cl.viewentity - 1];
870 Sbar_DrawPic (112, 0, rsb_teambord);
871 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
872 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);
873 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
874 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);
878 sprintf (num, "%3i",f);
880 if ((s->colors & 0xf0)==0)
883 Sbar_DrawCharacter(109, 3, 18 + num[0] - '0');
885 Sbar_DrawCharacter(116, 3, 18 + num[1] - '0');
887 Sbar_DrawCharacter(123, 3, 18 + num[2] - '0');
891 Sbar_DrawCharacter ( 109, 3, num[0]);
892 Sbar_DrawCharacter ( 116, 3, num[1]);
893 Sbar_DrawCharacter ( 123, 3, num[2]);
898 // PGM 01/19/97 - team color drawing
900 if ( (cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
901 Sbar_DrawPic (112, 0, sb_face_invis_invuln);
902 else if (cl.stats[STAT_ITEMS] & IT_QUAD)
903 Sbar_DrawPic (112, 0, sb_face_quad );
904 else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
905 Sbar_DrawPic (112, 0, sb_face_invis );
906 else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
907 Sbar_DrawPic (112, 0, sb_face_invuln);
910 f = cl.stats[STAT_HEALTH] / 20;
912 Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]);
916 void Sbar_ShowFPS(void)
918 float fps_x, fps_y, fps_scalex, fps_scaley, fps_height;
922 qboolean red = false;
929 static double nexttime = 0, lasttime = 0;
930 static double framerate = 0;
931 static int framecount = 0;
933 newtime = Sys_DoubleTime();
934 if (newtime >= nexttime)
936 framerate = framecount / (newtime - lasttime);
938 nexttime = max(nexttime + 0.1, lasttime - 0.1);
944 if ((red = (calc < 1.0f)))
945 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0f / calc + 0.5));
947 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(calc + 0.5));
949 if (showtime.integer)
950 strlcpy(timestring, Sys_TimeString(showtime_format.string), sizeof(timestring));
951 if (showdate.integer)
952 strlcpy(datestring, Sys_TimeString(showdate_format.string), sizeof(datestring));
953 if (fpsstring[0] || timestring[0])
957 fps_height = fps_scaley * ((fpsstring[0] != 0) + (timestring[0] != 0) + (datestring[0] != 0));
958 //fps_y = vid_conheight.integer - sb_lines; // yes this may draw over the sbar
959 //fps_y = bound(0, fps_y, vid_conheight.integer - fps_height);
960 fps_y = vid_conheight.integer - fps_height;
963 fps_x = vid_conwidth.integer - fps_scalex * strlen(fpsstring);
964 DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(fpsstring), fps_scaley, 0, 0, 0, 0.5, 0);
966 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 0, 0, 1, 0);
968 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
973 fps_x = vid_conwidth.integer - fps_scalex * strlen(timestring);
974 DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(timestring), fps_scaley, 0, 0, 0, 0.5, 0);
975 DrawQ_String(fps_x, fps_y, timestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
980 fps_x = vid_conwidth.integer - fps_scalex * strlen(datestring);
981 DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(datestring), fps_scaley, 0, 0, 0, 0.5, 0);
982 DrawQ_String(fps_x, fps_y, datestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
988 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)
991 c2 = bound(0, c2, 1);
992 c1 = bound(0, c1, 1 - c2);
994 r[1] = rangey + rangeheight * (c2 + c1);
995 r[2] = rangey + rangeheight * (c2);
999 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);
1001 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);
1003 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);
1005 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);
1013 extern float v_dmg_time, v_dmg_roll, v_dmg_pitch;
1014 extern cvar_t v_kicktime;
1015 void Sbar_Draw (void)
1017 if(cl.csqc_vidvars.drawenginesbar) //[515]: csqc drawsbar
1019 if (cl.intermission == 1)
1021 Sbar_IntermissionOverlay();
1024 else if (cl.intermission == 2)
1026 Sbar_FinaleOverlay();
1030 if (gamemode == GAME_NETHERWORLD)
1033 else if (gamemode == GAME_SOM)
1035 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1036 Sbar_DrawScoreboard ();
1039 // this is the top left of the sbar area
1041 sbar_y = vid_conheight.integer - 24*3;
1044 if (cl.stats[STAT_ARMOR])
1046 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1047 Sbar_DrawPic(0, 0, somsb_armor[2]);
1048 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1049 Sbar_DrawPic(0, 0, somsb_armor[1]);
1050 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1051 Sbar_DrawPic(0, 0, somsb_armor[0]);
1052 Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1056 Sbar_DrawPic(0, 24, somsb_health);
1057 Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1060 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1061 Sbar_DrawPic(0, 48, somsb_ammo[0]);
1062 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1063 Sbar_DrawPic(0, 48, somsb_ammo[1]);
1064 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1065 Sbar_DrawPic(0, 48, somsb_ammo[2]);
1066 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1067 Sbar_DrawPic(0, 48, somsb_ammo[3]);
1068 Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
1069 if (cl.stats[STAT_SHELLS])
1070 Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
1073 else if (gamemode == GAME_NEXUIZ)
1075 sbar_y = vid_conheight.integer - 47;
1076 sbar_x = (vid_conwidth.integer - 640)/2;
1078 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1080 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1081 Sbar_DrawScoreboard ();
1089 // we have a max time 2s (min time = 0)
1090 if ((time = cl.time - cl.weapontime) < 2)
1092 fade = (1.0 - 0.5 * time);
1094 for (i = 0; i < 8;i++)
1095 if (cl.stats[STAT_ITEMS] & (1 << i))
1096 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1098 if((cl.stats[STAT_ITEMS] & (1<<12)))
1099 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1102 //if (!cl.islocalgame)
1103 // Sbar_DrawFrags ();
1106 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1108 Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1111 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1113 // Nexuiz has no anum pics
1114 //Sbar_DrawNum (36, 0, 666, 3, 1);
1115 // Nexuiz has no disc pic
1116 //Sbar_DrawPic (0, 0, sb_disc);
1120 Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1123 if(cl.stats[STAT_HEALTH] > 100)
1124 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1125 else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1126 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1128 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1130 // AK dont draw ammo for the laser
1131 if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1133 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1134 Sbar_DrawPic (519, 0, sb_ammo[0]);
1135 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1136 Sbar_DrawPic (519, 0, sb_ammo[1]);
1137 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1138 Sbar_DrawPic (519, 0, sb_ammo[2]);
1139 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1140 Sbar_DrawPic (519, 0, sb_ammo[3]);
1142 if(cl.stats[STAT_AMMO] <= 10)
1143 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1145 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1150 DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1153 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1154 // Sbar_MiniDeathmatchOverlay (0, 17);
1156 else if (gamemode == GAME_ZYMOTIC)
1159 float scale = 64.0f / 256.0f;
1160 float kickoffset[3];
1161 VectorClear(kickoffset);
1164 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1165 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1167 sbar_x = (int)((vid_conwidth.integer - 256 * scale)/2 + kickoffset[0]);
1168 sbar_y = (int)((vid_conheight.integer - 256 * scale)/2 + kickoffset[1]);
1169 // left1 16, 48 : 126 -66
1170 // left2 16, 128 : 196 -66
1171 // right 176, 48 : 196 -136
1172 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);
1173 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);
1174 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);
1175 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1177 float scale = 128.0f / 256.0f;
1178 float healthstart, healthheight, healthstarttc, healthendtc;
1179 float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1180 float ammostart, ammoheight, ammostarttc, ammoendtc;
1181 float clipstart, clipheight, clipstarttc, clipendtc;
1182 float kickoffset[3], offset;
1183 VectorClear(kickoffset);
1186 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1187 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1189 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1190 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1191 offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1192 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);
1193 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);
1194 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);
1195 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);
1196 healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1197 shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1198 healthstart = 204 - healthheight;
1199 shieldstart = healthstart - shieldheight;
1200 healthstarttc = healthstart * (1.0f / 256.0f);
1201 healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1202 shieldstarttc = shieldstart * (1.0f / 256.0f);
1203 shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1204 ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1205 ammostart = 114 - ammoheight;
1206 ammostarttc = ammostart * (1.0f / 256.0f);
1207 ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1208 clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1209 clipstart = 190 - clipheight;
1210 clipstarttc = clipstart * (1.0f / 256.0f);
1211 clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1212 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);
1213 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);
1214 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);
1215 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);
1216 DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1217 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1220 else // Quake and others
1222 sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1223 if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1226 sbar_x = (vid_conwidth.integer - 320)/2;
1230 if (gamemode != GAME_GOODVSBAD2)
1231 Sbar_DrawInventory ();
1232 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1236 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1238 if (gamemode != GAME_GOODVSBAD2)
1239 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1240 Sbar_DrawScoreboard ();
1244 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1246 // keys (hipnotic only)
1247 //MED 01/04/97 moved keys here so they would not be overwritten
1248 if (gamemode == GAME_HIPNOTIC)
1250 if (cl.stats[STAT_ITEMS] & IT_KEY1)
1251 Sbar_DrawPic (209, 3, sb_items[0]);
1252 if (cl.stats[STAT_ITEMS] & IT_KEY2)
1253 Sbar_DrawPic (209, 12, sb_items[1]);
1256 if (gamemode != GAME_GOODVSBAD2)
1258 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1260 Sbar_DrawNum (24, 0, 666, 3, 1);
1261 Sbar_DrawPic (0, 0, sb_disc);
1265 if (gamemode == GAME_ROGUE)
1267 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1268 if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1269 Sbar_DrawPic (0, 0, sb_armor[2]);
1270 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1271 Sbar_DrawPic (0, 0, sb_armor[1]);
1272 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1273 Sbar_DrawPic (0, 0, sb_armor[0]);
1277 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1278 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1279 Sbar_DrawPic (0, 0, sb_armor[2]);
1280 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1281 Sbar_DrawPic (0, 0, sb_armor[1]);
1282 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1283 Sbar_DrawPic (0, 0, sb_armor[0]);
1292 Sbar_DrawNum (154, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1295 if (gamemode == GAME_ROGUE)
1297 if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1298 Sbar_DrawPic (224, 0, sb_ammo[0]);
1299 else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1300 Sbar_DrawPic (224, 0, sb_ammo[1]);
1301 else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1302 Sbar_DrawPic (224, 0, sb_ammo[2]);
1303 else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1304 Sbar_DrawPic (224, 0, sb_ammo[3]);
1305 else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1306 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1307 else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1308 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1309 else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1310 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1314 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1315 Sbar_DrawPic (224, 0, sb_ammo[0]);
1316 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1317 Sbar_DrawPic (224, 0, sb_ammo[1]);
1318 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1319 Sbar_DrawPic (224, 0, sb_ammo[2]);
1320 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1321 Sbar_DrawPic (224, 0, sb_ammo[3]);
1324 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1328 if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1330 if (gamemode == GAME_TRANSFUSION)
1331 Sbar_MiniDeathmatchOverlay (0, 0);
1333 Sbar_MiniDeathmatchOverlay (324, vid_conheight.integer - sb_lines);
1340 if(cl.csqc_vidvars.drawcrosshair)
1341 R_Draw2DCrosshair();
1343 if (cl_prydoncursor.integer)
1344 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);
1347 //=============================================================================
1351 Sbar_DeathmatchOverlay
1355 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1359 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1361 minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : realtime - s->qw_entertime) / 60.0);
1362 // draw colors behind score
1363 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1364 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);
1365 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1366 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);
1368 //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);
1369 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 );
1373 // draw colors behind score
1374 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1375 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);
1376 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1377 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);
1379 //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);
1380 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 );
1385 void Sbar_DeathmatchOverlay (void)
1389 // request new ping times every two second
1390 if (cl.last_ping_request < realtime - 2)
1392 cl.last_ping_request = realtime;
1393 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1395 MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
1396 MSG_WriteString(&cls.netcon->message, "pings");
1400 DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1405 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1406 x = (vid_conwidth.integer - (6 + 17 + 15) * 8) / 2;
1408 x = (vid_conwidth.integer - (6 + 15) * 8) / 2;
1411 if (Sbar_IsTeammatch ())
1413 // show team scores first
1414 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1415 y += (int)Sbar_PrintScoreboardItem((teams + teamsort[i]), x, y);
1419 for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1420 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1425 Sbar_DeathmatchOverlay
1429 void Sbar_MiniDeathmatchOverlay (int x, int y)
1433 // decide where to print
1434 if (gamemode == GAME_TRANSFUSION)
1435 numlines = (vid_conwidth.integer - x + 127) / 128;
1437 numlines = (vid_conheight.integer - y + 7) / 8;
1439 // give up if there isn't room
1440 if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1447 for (i = 0; i < scoreboardlines; i++)
1448 if (fragsort[i] == cl.playerentity - 1)
1453 i = min(i, scoreboardlines - numlines);
1456 if (gamemode == GAME_TRANSFUSION)
1458 for (;i < scoreboardlines && x < vid_conwidth.integer;i++)
1459 x += 128 + (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1463 for (;i < scoreboardlines && y < vid_conheight.integer;i++)
1464 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1470 Sbar_IntermissionOverlay
1474 void Sbar_IntermissionOverlay (void)
1479 if (cl.gametype == GAME_DEATHMATCH)
1481 Sbar_DeathmatchOverlay ();
1485 sbar_x = (vid_conwidth.integer - 320) >> 1;
1486 sbar_y = (vid_conheight.integer - 200) >> 1;
1488 DrawQ_Pic (sbar_x + 64, sbar_y + 24, sb_complete, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1489 DrawQ_Pic (sbar_x + 0, sbar_y + 56, sb_inter, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1492 dig = (int)cl.completed_time / 60;
1493 Sbar_DrawNum (160, 64, dig, 3, 0);
1494 num = (int)cl.completed_time - dig*60;
1495 if (gamemode != GAME_NEXUIZ)
1496 Sbar_DrawPic (234,64,sb_colon);
1497 Sbar_DrawPic (246,64,sb_nums[0][num/10]);
1498 Sbar_DrawPic (266,64,sb_nums[0][num%10]);
1500 Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
1501 if (gamemode != GAME_NEXUIZ)
1502 Sbar_DrawPic (232, 104, sb_slash);
1503 Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1505 Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1506 if (gamemode != GAME_NEXUIZ)
1507 Sbar_DrawPic (232, 144, sb_slash);
1508 Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1519 void Sbar_FinaleOverlay (void)
1521 DrawQ_Pic((vid_conwidth.integer - sb_finale->width)/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);