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 cvar_t crosshair_color_red = {CVAR_SAVE, "crosshair_color_red", "1", "customizable crosshair color"};
100 cvar_t crosshair_color_green = {CVAR_SAVE, "crosshair_color_green", "0", "customizable crosshair color"};
101 cvar_t crosshair_color_blue = {CVAR_SAVE, "crosshair_color_blue", "0", "customizable crosshair color"};
102 cvar_t crosshair_color_alpha = {CVAR_SAVE, "crosshair_color_alpha", "1", "how opaque the crosshair should be"};
103 cvar_t crosshair_size = {CVAR_SAVE, "crosshair_size", "1", "adjusts size of the crosshair on the screen"};
105 void Sbar_MiniDeathmatchOverlay (int x, int y);
106 void Sbar_DeathmatchOverlay (void);
107 void Sbar_IntermissionOverlay (void);
108 void Sbar_FinaleOverlay (void);
118 void Sbar_ShowScores (void)
122 sb_showscores = true;
132 void Sbar_DontShowScores (void)
134 sb_showscores = false;
137 void sbar_start(void)
141 if (gamemode == GAME_NETHERWORLD)
144 else if (gamemode == GAME_SOM)
146 sb_disc = Draw_CachePic("gfx/disc", true);
148 for (i = 0;i < 10;i++)
149 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
151 somsb_health = Draw_CachePic("gfx/hud_health", true);
152 somsb_ammo[0] = Draw_CachePic("gfx/sb_shells", true);
153 somsb_ammo[1] = Draw_CachePic("gfx/sb_nails", true);
154 somsb_ammo[2] = Draw_CachePic("gfx/sb_rocket", true);
155 somsb_ammo[3] = Draw_CachePic("gfx/sb_cells", true);
156 somsb_armor[0] = Draw_CachePic("gfx/sb_armor1", true);
157 somsb_armor[1] = Draw_CachePic("gfx/sb_armor2", true);
158 somsb_armor[2] = Draw_CachePic("gfx/sb_armor3", true);
160 else if (gamemode == GAME_NEXUIZ)
162 for (i = 0;i < 10;i++)
163 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
164 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus", true);
166 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells", true);
167 sb_ammo[1] = Draw_CachePic ("gfx/sb_bullets", true);
168 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket", true);
169 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells", true);
171 sb_items[2] = Draw_CachePic ("gfx/sb_slowmo", true);
172 sb_items[3] = Draw_CachePic ("gfx/sb_invinc", true);
173 sb_items[4] = Draw_CachePic ("gfx/sb_energy", true);
174 sb_items[5] = Draw_CachePic ("gfx/sb_str", true);
176 sb_items[11] = Draw_CachePic ("gfx/sb_flag_red_taken", true);
177 sb_items[12] = Draw_CachePic ("gfx/sb_flag_red_lost", true);
178 sb_items[13] = Draw_CachePic ("gfx/sb_flag_red_carrying", true);
179 sb_items[15] = Draw_CachePic ("gfx/sb_flag_blue_taken", true);
180 sb_items[16] = Draw_CachePic ("gfx/sb_flag_blue_lost", true);
181 sb_items[17] = Draw_CachePic ("gfx/sb_flag_blue_carrying", true);
183 sb_sbar = Draw_CachePic("gfx/sbar", true);
184 sb_sbar_minimal = Draw_CachePic("gfx/sbar_minimal", true);
185 sb_sbar_overlay = Draw_CachePic("gfx/sbar_overlay", true);
187 for(i = 0; i < 9;i++)
188 sb_weapons[0][i] = Draw_CachePic(va("gfx/inv_weapon%i",i), true);
190 else if (gamemode == GAME_ZYMOTIC)
192 zymsb_crosshair_center = Draw_CachePic ("gfx/hud/crosshair_center", true);
193 zymsb_crosshair_line = Draw_CachePic ("gfx/hud/crosshair_line", true);
194 zymsb_crosshair_health = Draw_CachePic ("gfx/hud/crosshair_health", true);
195 zymsb_crosshair_clip = Draw_CachePic ("gfx/hud/crosshair_clip", true);
196 zymsb_crosshair_ammo = Draw_CachePic ("gfx/hud/crosshair_ammo", true);
197 zymsb_crosshair_background = Draw_CachePic ("gfx/hud/crosshair_background", true);
198 zymsb_crosshair_left1 = Draw_CachePic ("gfx/hud/crosshair_left1", true);
199 zymsb_crosshair_left2 = Draw_CachePic ("gfx/hud/crosshair_left2", true);
200 zymsb_crosshair_right = Draw_CachePic ("gfx/hud/crosshair_right", true);
204 sb_disc = Draw_CachePic("gfx/disc", true);
206 for (i = 0;i < 10;i++)
208 sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
209 sb_nums[1][i] = Draw_CachePic (va("gfx/anum_%i",i), true);
212 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus", true);
213 sb_nums[1][10] = Draw_CachePic ("gfx/anum_minus", true);
215 sb_colon = Draw_CachePic ("gfx/num_colon", true);
216 sb_slash = Draw_CachePic ("gfx/num_slash", true);
218 sb_weapons[0][0] = Draw_CachePic ("gfx/inv_shotgun", true);
219 sb_weapons[0][1] = Draw_CachePic ("gfx/inv_sshotgun", true);
220 sb_weapons[0][2] = Draw_CachePic ("gfx/inv_nailgun", true);
221 sb_weapons[0][3] = Draw_CachePic ("gfx/inv_snailgun", true);
222 sb_weapons[0][4] = Draw_CachePic ("gfx/inv_rlaunch", true);
223 sb_weapons[0][5] = Draw_CachePic ("gfx/inv_srlaunch", true);
224 sb_weapons[0][6] = Draw_CachePic ("gfx/inv_lightng", true);
226 sb_weapons[1][0] = Draw_CachePic ("gfx/inv2_shotgun", true);
227 sb_weapons[1][1] = Draw_CachePic ("gfx/inv2_sshotgun", true);
228 sb_weapons[1][2] = Draw_CachePic ("gfx/inv2_nailgun", true);
229 sb_weapons[1][3] = Draw_CachePic ("gfx/inv2_snailgun", true);
230 sb_weapons[1][4] = Draw_CachePic ("gfx/inv2_rlaunch", true);
231 sb_weapons[1][5] = Draw_CachePic ("gfx/inv2_srlaunch", true);
232 sb_weapons[1][6] = Draw_CachePic ("gfx/inv2_lightng", true);
234 for (i = 0;i < 5;i++)
236 sb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_shotgun",i+1), true);
237 sb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_sshotgun",i+1), true);
238 sb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_nailgun",i+1), true);
239 sb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_snailgun",i+1), true);
240 sb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_rlaunch",i+1), true);
241 sb_weapons[2+i][5] = Draw_CachePic (va("gfx/inva%i_srlaunch",i+1), true);
242 sb_weapons[2+i][6] = Draw_CachePic (va("gfx/inva%i_lightng",i+1), true);
245 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells", true);
246 sb_ammo[1] = Draw_CachePic ("gfx/sb_nails", true);
247 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket", true);
248 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells", true);
250 sb_armor[0] = Draw_CachePic ("gfx/sb_armor1", true);
251 sb_armor[1] = Draw_CachePic ("gfx/sb_armor2", true);
252 sb_armor[2] = Draw_CachePic ("gfx/sb_armor3", true);
254 sb_items[0] = Draw_CachePic ("gfx/sb_key1", true);
255 sb_items[1] = Draw_CachePic ("gfx/sb_key2", true);
256 sb_items[2] = Draw_CachePic ("gfx/sb_invis", true);
257 sb_items[3] = Draw_CachePic ("gfx/sb_invuln", true);
258 sb_items[4] = Draw_CachePic ("gfx/sb_suit", true);
259 sb_items[5] = Draw_CachePic ("gfx/sb_quad", true);
261 sb_sigil[0] = Draw_CachePic ("gfx/sb_sigil1", true);
262 sb_sigil[1] = Draw_CachePic ("gfx/sb_sigil2", true);
263 sb_sigil[2] = Draw_CachePic ("gfx/sb_sigil3", true);
264 sb_sigil[3] = Draw_CachePic ("gfx/sb_sigil4", true);
266 sb_faces[4][0] = Draw_CachePic ("gfx/face1", true);
267 sb_faces[4][1] = Draw_CachePic ("gfx/face_p1", true);
268 sb_faces[3][0] = Draw_CachePic ("gfx/face2", true);
269 sb_faces[3][1] = Draw_CachePic ("gfx/face_p2", true);
270 sb_faces[2][0] = Draw_CachePic ("gfx/face3", true);
271 sb_faces[2][1] = Draw_CachePic ("gfx/face_p3", true);
272 sb_faces[1][0] = Draw_CachePic ("gfx/face4", true);
273 sb_faces[1][1] = Draw_CachePic ("gfx/face_p4", true);
274 sb_faces[0][0] = Draw_CachePic ("gfx/face5", true);
275 sb_faces[0][1] = Draw_CachePic ("gfx/face_p5", true);
277 sb_face_invis = Draw_CachePic ("gfx/face_invis", true);
278 sb_face_invuln = Draw_CachePic ("gfx/face_invul2", true);
279 sb_face_invis_invuln = Draw_CachePic ("gfx/face_inv2", true);
280 sb_face_quad = Draw_CachePic ("gfx/face_quad", true);
282 sb_sbar = Draw_CachePic ("gfx/sbar", true);
283 sb_ibar = Draw_CachePic ("gfx/ibar", true);
284 sb_scorebar = Draw_CachePic ("gfx/scorebar", true);
286 //MED 01/04/97 added new hipnotic weapons
287 if (gamemode == GAME_HIPNOTIC)
289 hsb_weapons[0][0] = Draw_CachePic ("gfx/inv_laser", true);
290 hsb_weapons[0][1] = Draw_CachePic ("gfx/inv_mjolnir", true);
291 hsb_weapons[0][2] = Draw_CachePic ("gfx/inv_gren_prox", true);
292 hsb_weapons[0][3] = Draw_CachePic ("gfx/inv_prox_gren", true);
293 hsb_weapons[0][4] = Draw_CachePic ("gfx/inv_prox", true);
295 hsb_weapons[1][0] = Draw_CachePic ("gfx/inv2_laser", true);
296 hsb_weapons[1][1] = Draw_CachePic ("gfx/inv2_mjolnir", true);
297 hsb_weapons[1][2] = Draw_CachePic ("gfx/inv2_gren_prox", true);
298 hsb_weapons[1][3] = Draw_CachePic ("gfx/inv2_prox_gren", true);
299 hsb_weapons[1][4] = Draw_CachePic ("gfx/inv2_prox", true);
301 for (i = 0;i < 5;i++)
303 hsb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_laser",i+1), true);
304 hsb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_mjolnir",i+1), true);
305 hsb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_gren_prox",i+1), true);
306 hsb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_prox_gren",i+1), true);
307 hsb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_prox",i+1), true);
310 hsb_items[0] = Draw_CachePic ("gfx/sb_wsuit", true);
311 hsb_items[1] = Draw_CachePic ("gfx/sb_eshld", true);
313 else if (gamemode == GAME_ROGUE)
315 rsb_invbar[0] = Draw_CachePic ("gfx/r_invbar1", true);
316 rsb_invbar[1] = Draw_CachePic ("gfx/r_invbar2", true);
318 rsb_weapons[0] = Draw_CachePic ("gfx/r_lava", true);
319 rsb_weapons[1] = Draw_CachePic ("gfx/r_superlava", true);
320 rsb_weapons[2] = Draw_CachePic ("gfx/r_gren", true);
321 rsb_weapons[3] = Draw_CachePic ("gfx/r_multirock", true);
322 rsb_weapons[4] = Draw_CachePic ("gfx/r_plasma", true);
324 rsb_items[0] = Draw_CachePic ("gfx/r_shield1", true);
325 rsb_items[1] = Draw_CachePic ("gfx/r_agrav1", true);
327 // PGM 01/19/97 - team color border
328 rsb_teambord = Draw_CachePic ("gfx/r_teambord", true);
329 // PGM 01/19/97 - team color border
331 rsb_ammo[0] = Draw_CachePic ("gfx/r_ammolava", true);
332 rsb_ammo[1] = Draw_CachePic ("gfx/r_ammomulti", true);
333 rsb_ammo[2] = Draw_CachePic ("gfx/r_ammoplasma", true);
337 sb_ranking = Draw_CachePic ("gfx/ranking", true);
338 sb_complete = Draw_CachePic ("gfx/complete", true);
339 sb_inter = Draw_CachePic ("gfx/inter", true);
340 sb_finale = Draw_CachePic ("gfx/finale", true);
343 void sbar_shutdown(void)
347 void sbar_newmap(void)
351 void Sbar_Init (void)
353 Cmd_AddCommand("+showscores", Sbar_ShowScores, "show scoreboard");
354 Cmd_AddCommand("-showscores", Sbar_DontShowScores, "hide scoreboard");
355 Cvar_RegisterVariable(&showfps);
356 Cvar_RegisterVariable(&showtime);
357 Cvar_RegisterVariable(&showtime_format);
358 Cvar_RegisterVariable(&showdate);
359 Cvar_RegisterVariable(&showdate_format);
360 Cvar_RegisterVariable(&sbar_alpha_bg);
361 Cvar_RegisterVariable(&sbar_alpha_fg);
362 Cvar_RegisterVariable(&cl_deathscoreboard);
364 Cvar_RegisterVariable(&crosshair_color_red);
365 Cvar_RegisterVariable(&crosshair_color_green);
366 Cvar_RegisterVariable(&crosshair_color_blue);
367 Cvar_RegisterVariable(&crosshair_color_alpha);
368 Cvar_RegisterVariable(&crosshair_size);
370 R_RegisterModule("sbar", sbar_start, sbar_shutdown, sbar_newmap);
374 //=============================================================================
376 // drawing routines are relative to the status bar location
385 void Sbar_DrawPic (int x, int y, cachepic_t *pic)
387 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, sbar_alpha_fg.value, 0);
390 void Sbar_DrawAlphaPic (int x, int y, cachepic_t *pic, float alpha)
392 DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, alpha, 0);
399 Draws one solid graphics character
402 void Sbar_DrawCharacter (int x, int y, int num)
404 DrawQ_String (sbar_x + x + 4 , sbar_y + y, va("%c", num), 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0);
412 void Sbar_DrawString (int x, int y, char *str)
414 DrawQ_String (sbar_x + x, sbar_y + y, str, 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0);
422 void Sbar_DrawNum (int x, int y, int num, int digits, int color)
427 l = sprintf(str, "%i", num);
441 Sbar_DrawPic (x, y, sb_nums[color][frame]);
454 void Sbar_DrawXNum (int x, int y, int num, int digits, int lettersize, float r, float g, float b, float a, int flags)
459 l = sprintf(str, "%i", num);
464 x += (digits-l) * lettersize;
473 DrawQ_Pic (sbar_x + x, sbar_y + y, sb_nums[0][frame],lettersize,lettersize,r,g,b,a * sbar_alpha_fg.value,flags);
480 //=============================================================================
483 int Sbar_IsTeammatch()
485 // currently only nexuiz uses the team score board
486 return ((gamemode == GAME_NEXUIZ)
487 && (teamplay.integer > 0));
495 static int fragsort[MAX_SCOREBOARD];
496 static int scoreboardlines;
498 //[515]: Sbar_GetPlayer for csqc "getplayerkey" func
499 int Sbar_GetPlayer (int index)
504 if(index >= scoreboardlines)
506 index = fragsort[index];
508 if(index >= scoreboardlines)
513 static scoreboard_t teams[MAX_SCOREBOARD];
514 static int teamsort[MAX_SCOREBOARD];
515 static int teamlines;
516 void Sbar_SortFrags (void)
522 for (i=0 ; i<cl.maxclients ; i++)
524 if (cl.scores[i].name[0])
526 fragsort[scoreboardlines] = i;
531 for (i=0 ; i<scoreboardlines ; i++)
532 for (j=0 ; j<scoreboardlines-1-i ; j++)
533 if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j+1]].frags)
536 fragsort[j] = fragsort[j+1];
541 if (Sbar_IsTeammatch ())
543 // now sort players by teams.
544 for (i=0 ; i<scoreboardlines ; i++)
546 for (j=0 ; j<scoreboardlines-1-i ; j++)
548 if (cl.scores[fragsort[j]].colors < cl.scores[fragsort[j+1]].colors)
551 fragsort[j] = fragsort[j+1];
557 // calculate team scores
559 for (i=0 ; i<scoreboardlines ; i++)
561 if (color != (cl.scores[fragsort[i]].colors & 15))
563 const char* teamname;
565 color = cl.scores[fragsort[i]].colors & 15;
571 teamname = "^1Red Team";
574 teamname = "^4Blue Team";
577 teamname = "^6Pink Team";
580 teamname = "^3Yellow Team";
583 teamname = "Total Team Score";
586 strlcpy(teams[teamlines-1].name, teamname, sizeof(teams[teamlines-1].name));
588 teams[teamlines-1].frags = 0;
589 teams[teamlines-1].colors = color + 16 * color;
592 if (cl.scores[fragsort[i]].frags != -666)
594 // do not add spedcators
595 // (ugly hack for nexuiz)
596 teams[teamlines-1].frags += cl.scores[fragsort[i]].frags;
600 // now sort teams by scores.
601 for (i=0 ; i<teamlines ; i++)
603 for (i=0 ; i<teamlines ; i++)
605 for (j=0 ; j<teamlines-1-i ; j++)
607 if (teams[teamsort[j]].frags < teams[teamsort[j+1]].frags)
610 teamsort[j] = teamsort[j+1];
623 void Sbar_SoloScoreboard (void)
626 int minutes, seconds, tens, units;
629 if (gamemode != GAME_NEXUIZ) {
630 sprintf (str,"Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
631 Sbar_DrawString (8, 4, str);
633 sprintf (str,"Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
634 Sbar_DrawString (8, 12, str);
638 minutes = (int)(cl.time / 60);
639 seconds = (int)(cl.time - 60*minutes);
641 units = seconds - 10*tens;
642 sprintf (str,"Time :%3i:%i%i", minutes, tens, units);
643 Sbar_DrawString (184, 4, str);
646 if (gamemode == GAME_NEXUIZ) {
647 l = (int) strlen (cl.worldmodel->name);
648 Sbar_DrawString (232 - l*4, 12, cl.worldmodel->name);
650 l = (int) strlen (cl.levelname);
651 Sbar_DrawString (232 - l*4, 12, cl.levelname);
660 void Sbar_DrawScoreboard (void)
662 Sbar_SoloScoreboard ();
663 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
664 //if (cl.gametype == GAME_DEATHMATCH)
666 Sbar_DeathmatchOverlay ();
669 //=============================================================================
671 // AK to make DrawInventory smaller
672 static void Sbar_DrawWeapon(int nr, float fade, int active)
674 // width = 300, height = 100
675 const int w_width = 300, w_height = 100, w_space = 10;
676 const float w_scale = 0.4;
678 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);
679 //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);
682 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);
690 void Sbar_DrawInventory (void)
697 if (gamemode == GAME_ROGUE)
699 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
700 Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], sbar_alpha_bg.value);
702 Sbar_DrawAlphaPic (0, -24, rsb_invbar[1], sbar_alpha_bg.value);
705 Sbar_DrawAlphaPic (0, -24, sb_ibar, sbar_alpha_bg.value);
708 for (i=0 ; i<7 ; i++)
710 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<i) )
712 time = cl.item_gettime[i];
713 flashon = (int)((cl.time - time)*10);
716 if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i) )
722 flashon = (flashon%5) + 2;
724 Sbar_DrawAlphaPic (i*24, -16, sb_weapons[flashon][i], sbar_alpha_bg.value);
730 if (gamemode == GAME_HIPNOTIC)
732 int grenadeflashing=0;
733 for (i=0 ; i<4 ; i++)
735 if (cl.stats[STAT_ITEMS] & (1<<hipweapons[i]) )
737 time = cl.item_gettime[hipweapons[i]];
738 flashon = (int)((cl.time - time)*10);
741 if ( cl.stats[STAT_ACTIVEWEAPON] == (1<<hipweapons[i]) )
747 flashon = (flashon%5) + 2;
749 // check grenade launcher
752 if (cl.stats[STAT_ITEMS] & HIT_PROXIMITY_GUN)
757 Sbar_DrawPic (96, -16, hsb_weapons[flashon][2]);
763 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<4))
765 if (!grenadeflashing)
766 Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
769 Sbar_DrawPic (96, -16, hsb_weapons[flashon][4]);
772 Sbar_DrawPic (176 + (i*24), -16, hsb_weapons[flashon][i]);
777 if (gamemode == GAME_ROGUE)
779 // check for powered up weapon.
780 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
782 if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i))
783 Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]);
787 for (i=0 ; i<4 ; i++)
789 sprintf (num, "%3i",cl.stats[STAT_SHELLS+i] );
791 Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[0] - '0');
793 Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[1] - '0');
795 Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0');
799 for (i=0 ; i<6 ; i++)
800 if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
802 //MED 01/04/97 changed keys
803 if (gamemode != GAME_HIPNOTIC || (i>1))
804 Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
807 //MED 01/04/97 added hipnotic items
809 if (gamemode == GAME_HIPNOTIC)
811 for (i=0 ; i<2 ; i++)
812 if (cl.stats[STAT_ITEMS] & (1<<(24+i)))
813 Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
816 if (gamemode == GAME_ROGUE)
819 for (i=0 ; i<2 ; i++)
820 if (cl.stats[STAT_ITEMS] & (1<<(29+i)))
821 Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
826 for (i=0 ; i<4 ; i++)
827 if (cl.stats[STAT_ITEMS] & (1<<(28+i)))
828 Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
832 //=============================================================================
839 void Sbar_DrawFrags (void)
849 l = min(scoreboardlines, 4);
853 for (i = 0;i < l;i++)
859 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
860 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);
861 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
862 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);
866 sprintf (num, "%3i",f);
868 if (k == cl.viewentity - 1)
870 Sbar_DrawCharacter ( x + 2, -24, 16);
871 Sbar_DrawCharacter ( x + 32 - 4, -24, 17);
873 Sbar_DrawCharacter (x + 8, -24, num[0]);
874 Sbar_DrawCharacter (x + 16, -24, num[1]);
875 Sbar_DrawCharacter (x + 24, -24, num[2]);
880 //=============================================================================
888 void Sbar_DrawFace (void)
892 // PGM 01/19/97 - team color drawing
893 // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
894 if (gamemode == GAME_ROGUE && !cl.islocalgame && (teamplay.integer > 3) && (teamplay.integer < 7))
900 s = &cl.scores[cl.viewentity - 1];
902 Sbar_DrawPic (112, 0, rsb_teambord);
903 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
904 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);
905 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
906 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);
910 sprintf (num, "%3i",f);
912 if ((s->colors & 0xf0)==0)
915 Sbar_DrawCharacter(109, 3, 18 + num[0] - '0');
917 Sbar_DrawCharacter(116, 3, 18 + num[1] - '0');
919 Sbar_DrawCharacter(123, 3, 18 + num[2] - '0');
923 Sbar_DrawCharacter ( 109, 3, num[0]);
924 Sbar_DrawCharacter ( 116, 3, num[1]);
925 Sbar_DrawCharacter ( 123, 3, num[2]);
930 // PGM 01/19/97 - team color drawing
932 if ( (cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
933 Sbar_DrawPic (112, 0, sb_face_invis_invuln);
934 else if (cl.stats[STAT_ITEMS] & IT_QUAD)
935 Sbar_DrawPic (112, 0, sb_face_quad );
936 else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
937 Sbar_DrawPic (112, 0, sb_face_invis );
938 else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
939 Sbar_DrawPic (112, 0, sb_face_invuln);
942 f = cl.stats[STAT_HEALTH] / 20;
944 Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]);
948 void Sbar_ShowFPS(void)
950 float fps_x, fps_y, fps_scalex, fps_scaley, fps_height;
954 qboolean red = false;
961 static double nexttime = 0, lasttime = 0;
962 static double framerate = 0;
963 static int framecount = 0;
965 newtime = Sys_DoubleTime();
966 if (newtime >= nexttime)
968 framerate = framecount / (newtime - lasttime);
970 nexttime = max(nexttime + 1, lasttime - 1);
976 if ((red = (calc < 1.0f)))
977 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0f / calc + 0.5));
979 dpsnprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(calc + 0.5));
981 if (showtime.integer)
982 strlcpy(timestring, Sys_TimeString(showtime_format.string), sizeof(timestring));
983 if (showdate.integer)
984 strlcpy(datestring, Sys_TimeString(showdate_format.string), sizeof(datestring));
985 if (fpsstring[0] || timestring[0])
989 fps_height = fps_scaley * ((fpsstring[0] != 0) + (timestring[0] != 0) + (datestring[0] != 0));
990 //fps_y = vid_conheight.integer - sb_lines; // yes this may draw over the sbar
991 //fps_y = bound(0, fps_y, vid_conheight.integer - fps_height);
992 fps_y = vid_conheight.integer - fps_height;
995 fps_x = vid_conwidth.integer - fps_scalex * strlen(fpsstring);
996 DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(fpsstring), fps_scaley, 0, 0, 0, 0.5, 0);
998 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 0, 0, 1, 0);
1000 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
1001 fps_y += fps_scaley;
1005 fps_x = vid_conwidth.integer - fps_scalex * strlen(timestring);
1006 DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(timestring), fps_scaley, 0, 0, 0, 0.5, 0);
1007 DrawQ_String(fps_x, fps_y, timestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
1008 fps_y += fps_scaley;
1012 fps_x = vid_conwidth.integer - fps_scalex * strlen(datestring);
1013 DrawQ_Pic(fps_x, fps_y, NULL, fps_scalex * strlen(datestring), fps_scaley, 0, 0, 0, 0.5, 0);
1014 DrawQ_String(fps_x, fps_y, datestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
1015 fps_y += fps_scaley;
1020 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)
1023 c2 = bound(0, c2, 1);
1024 c1 = bound(0, c1, 1 - c2);
1026 r[1] = rangey + rangeheight * (c2 + c1);
1027 r[2] = rangey + rangeheight * (c2);
1031 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);
1033 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);
1035 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);
1037 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);
1045 extern float v_dmg_time, v_dmg_roll, v_dmg_pitch;
1046 extern cvar_t v_kicktime;
1047 void Sbar_Draw (void)
1051 if(cl.csqc_vidvars.drawenginesbar) //[515]: csqc drawsbar
1053 if (cl.intermission == 1)
1055 Sbar_IntermissionOverlay();
1058 else if (cl.intermission == 2)
1060 Sbar_FinaleOverlay();
1064 if (gamemode == GAME_NETHERWORLD)
1067 else if (gamemode == GAME_SOM)
1069 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1070 Sbar_DrawScoreboard ();
1073 // this is the top left of the sbar area
1075 sbar_y = vid_conheight.integer - 24*3;
1078 if (cl.stats[STAT_ARMOR])
1080 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1081 Sbar_DrawPic(0, 0, somsb_armor[2]);
1082 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1083 Sbar_DrawPic(0, 0, somsb_armor[1]);
1084 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1085 Sbar_DrawPic(0, 0, somsb_armor[0]);
1086 Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1090 Sbar_DrawPic(0, 24, somsb_health);
1091 Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1094 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1095 Sbar_DrawPic(0, 48, somsb_ammo[0]);
1096 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1097 Sbar_DrawPic(0, 48, somsb_ammo[1]);
1098 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1099 Sbar_DrawPic(0, 48, somsb_ammo[2]);
1100 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1101 Sbar_DrawPic(0, 48, somsb_ammo[3]);
1102 Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
1103 if (cl.stats[STAT_SHELLS])
1104 Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
1107 else if (gamemode == GAME_NEXUIZ)
1109 sbar_y = vid_conheight.integer - 47;
1110 sbar_x = (vid_conwidth.integer - 640)/2;
1112 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1114 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1115 Sbar_DrawScoreboard ();
1123 // we have a max time 2s (min time = 0)
1124 if ((time = cl.time - cl.weapontime) < 2)
1126 fade = (1.0 - 0.5 * time);
1128 for (i = 0; i < 8;i++)
1129 if (cl.stats[STAT_ITEMS] & (1 << i))
1130 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1132 if((cl.stats[STAT_ITEMS] & (1<<12)))
1133 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1136 //if (!cl.islocalgame)
1137 // Sbar_DrawFrags ();
1140 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1142 Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1145 int redflag = ((cl.stats[STAT_ITEMS]>>15) & 3);
1147 Sbar_DrawPic (10, -85, sb_items[redflag+10]);
1148 int blueflag = ((cl.stats[STAT_ITEMS]>>17) & 3);
1150 Sbar_DrawPic (10, -145, sb_items[blueflag+14]);
1153 Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1156 if(cl.stats[STAT_HEALTH] > 100)
1157 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1158 else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1159 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1161 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1163 // AK dont draw ammo for the laser
1164 if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1166 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1167 Sbar_DrawPic (519, 0, sb_ammo[0]);
1168 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1169 Sbar_DrawPic (519, 0, sb_ammo[1]);
1170 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1171 Sbar_DrawPic (519, 0, sb_ammo[2]);
1172 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1173 Sbar_DrawPic (519, 0, sb_ammo[3]);
1175 if(cl.stats[STAT_AMMO] <= 10)
1176 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1178 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1183 DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1186 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1187 // Sbar_MiniDeathmatchOverlay (0, 17);
1189 else if (gamemode == GAME_ZYMOTIC)
1192 float scale = 64.0f / 256.0f;
1193 float kickoffset[3];
1194 VectorClear(kickoffset);
1197 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1198 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1200 sbar_x = (int)((vid_conwidth.integer - 256 * scale)/2 + kickoffset[0]);
1201 sbar_y = (int)((vid_conheight.integer - 256 * scale)/2 + kickoffset[1]);
1202 // left1 16, 48 : 126 -66
1203 // left2 16, 128 : 196 -66
1204 // right 176, 48 : 196 -136
1205 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);
1206 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);
1207 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);
1208 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1210 float scale = 128.0f / 256.0f;
1211 float healthstart, healthheight, healthstarttc, healthendtc;
1212 float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1213 float ammostart, ammoheight, ammostarttc, ammoendtc;
1214 float clipstart, clipheight, clipstarttc, clipendtc;
1215 float kickoffset[3], offset;
1216 VectorClear(kickoffset);
1219 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1220 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1222 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1223 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1224 offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1225 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);
1226 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);
1227 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);
1228 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);
1229 healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1230 shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1231 healthstart = 204 - healthheight;
1232 shieldstart = healthstart - shieldheight;
1233 healthstarttc = healthstart * (1.0f / 256.0f);
1234 healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1235 shieldstarttc = shieldstart * (1.0f / 256.0f);
1236 shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1237 ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1238 ammostart = 114 - ammoheight;
1239 ammostarttc = ammostart * (1.0f / 256.0f);
1240 ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1241 clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1242 clipstart = 190 - clipheight;
1243 clipstarttc = clipstart * (1.0f / 256.0f);
1244 clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1245 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);
1246 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);
1247 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);
1248 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);
1249 DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1250 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1253 else // Quake and others
1255 sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1256 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1257 //if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1258 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1261 sbar_x = (vid_conwidth.integer - 320)/2;
1265 if (gamemode != GAME_GOODVSBAD2)
1266 Sbar_DrawInventory ();
1267 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1271 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1273 if (gamemode != GAME_GOODVSBAD2)
1274 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1275 Sbar_DrawScoreboard ();
1279 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1281 // keys (hipnotic only)
1282 //MED 01/04/97 moved keys here so they would not be overwritten
1283 if (gamemode == GAME_HIPNOTIC)
1285 if (cl.stats[STAT_ITEMS] & IT_KEY1)
1286 Sbar_DrawPic (209, 3, sb_items[0]);
1287 if (cl.stats[STAT_ITEMS] & IT_KEY2)
1288 Sbar_DrawPic (209, 12, sb_items[1]);
1291 if (gamemode != GAME_GOODVSBAD2)
1293 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1295 Sbar_DrawNum (24, 0, 666, 3, 1);
1296 Sbar_DrawPic (0, 0, sb_disc);
1300 if (gamemode == GAME_ROGUE)
1302 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1303 if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1304 Sbar_DrawPic (0, 0, sb_armor[2]);
1305 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1306 Sbar_DrawPic (0, 0, sb_armor[1]);
1307 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1308 Sbar_DrawPic (0, 0, sb_armor[0]);
1312 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1313 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1314 Sbar_DrawPic (0, 0, sb_armor[2]);
1315 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1316 Sbar_DrawPic (0, 0, sb_armor[1]);
1317 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1318 Sbar_DrawPic (0, 0, sb_armor[0]);
1327 Sbar_DrawNum (154, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1330 if (gamemode == GAME_ROGUE)
1332 if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1333 Sbar_DrawPic (224, 0, sb_ammo[0]);
1334 else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1335 Sbar_DrawPic (224, 0, sb_ammo[1]);
1336 else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1337 Sbar_DrawPic (224, 0, sb_ammo[2]);
1338 else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1339 Sbar_DrawPic (224, 0, sb_ammo[3]);
1340 else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1341 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1342 else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1343 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1344 else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1345 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1349 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1350 Sbar_DrawPic (224, 0, sb_ammo[0]);
1351 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1352 Sbar_DrawPic (224, 0, sb_ammo[1]);
1353 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1354 Sbar_DrawPic (224, 0, sb_ammo[2]);
1355 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1356 Sbar_DrawPic (224, 0, sb_ammo[3]);
1359 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1363 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1364 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1365 if (!cl.islocalgame && vid_conwidth.integer > 320)
1367 if (gamemode == GAME_TRANSFUSION)
1368 Sbar_MiniDeathmatchOverlay (0, 0);
1370 Sbar_MiniDeathmatchOverlay (324, vid_conheight.integer - sb_lines);
1377 if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && crosshair.integer <= NUMCROSSHAIRS && !cl.intermission && !r_letterbox.value && (pic = r_crosshairs[crosshair.integer]))
1378 DrawQ_Pic((vid_conwidth.integer - pic->width * crosshair_size.value) * 0.5f, (vid_conheight.integer - pic->height * crosshair_size.value) * 0.5f, pic, pic->width * crosshair_size.value, pic->height * crosshair_size.value, crosshair_color_red.value, crosshair_color_green.value, crosshair_color_blue.value, crosshair_color_alpha.value, 0);
1380 if (cl_prydoncursor.integer)
1381 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);
1384 //=============================================================================
1388 Sbar_DeathmatchOverlay
1392 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1396 minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : cl.time - s->qw_entertime) / 60.0);
1397 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1399 if (s->qw_spectator)
1401 if (s->qw_ping || s->qw_packetloss)
1402 DrawQ_ColoredString(x, y, va("%4i %3i %4i spectator %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1404 DrawQ_ColoredString(x, y, va(" %4i spectator %c%s", minutes, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1408 // draw colors behind score
1409 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1410 DrawQ_Pic(x + 14*8, y+1, NULL, 40, 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);
1411 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1412 DrawQ_Pic(x + 14*8, y+4, NULL, 40, 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);
1414 //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);
1415 if (s->qw_ping || s->qw_packetloss)
1416 DrawQ_ColoredString(x, y, va("%4i %3i %4i %5i %-4s %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1418 DrawQ_ColoredString(x, y, va(" %4i %5i %-4s %c%s", minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1423 if (s->qw_spectator)
1425 if (s->qw_ping || s->qw_packetloss)
1426 DrawQ_ColoredString(x, y, va("%4i %3i spect %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1428 DrawQ_ColoredString(x, y, va(" spect %c%s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1432 // draw colors behind score
1433 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1434 DrawQ_Pic(x + 9*8, y+1, NULL, 40, 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);
1435 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1436 DrawQ_Pic(x + 9*8, y+4, NULL, 40, 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);
1438 //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);
1439 if (s->qw_ping || s->qw_packetloss)
1440 DrawQ_ColoredString(x, y, va("%4i %3i %5i %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), (int) s->frags, (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1442 DrawQ_ColoredString(x, y, va(" %5i %c%s", (int) s->frags, (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1448 void Sbar_DeathmatchOverlay (void)
1452 // request new ping times every two second
1453 if (cl.last_ping_request < realtime - 2 && cls.netcon)
1455 cl.last_ping_request = realtime;
1456 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1458 MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
1459 MSG_WriteString(&cls.netcon->message, "pings");
1461 else if (cls.protocol == PROTOCOL_QUAKE || cls.protocol == PROTOCOL_QUAKEDP || cls.protocol == PROTOCOL_NEHAHRAMOVIE || cls.protocol == PROTOCOL_DARKPLACES1 || cls.protocol == PROTOCOL_DARKPLACES2 || cls.protocol == PROTOCOL_DARKPLACES3 || cls.protocol == PROTOCOL_DARKPLACES4 || cls.protocol == PROTOCOL_DARKPLACES5 || cls.protocol == PROTOCOL_DARKPLACES6 || cls.protocol == PROTOCOL_DARKPLACES7)
1463 // these servers usually lack the pings command and so a less efficient "ping" command must be sent, which on modern DP servers will also reply with a pingplreport command after the ping listing
1464 cl.parsingtextexpectingpingforscores = true; // hide the output of the next ping report
1465 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1466 MSG_WriteString(&cls.netcon->message, "ping");
1470 // newer server definitely has pings command, so use it for more efficiency
1471 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1472 MSG_WriteString(&cls.netcon->message, "pings");
1476 DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1482 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1484 x = (vid_conwidth.integer - (26 + 15) * 8) / 2; // 26 characters until name, then we assume 15 character names (they can be longer but usually aren't)
1485 DrawQ_ColoredString(x, y, va("ping pl%% time frags team name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1489 x = (vid_conwidth.integer - (16 + 15) * 8) / 2; // 16 characters until name, then we assume 15 character names (they can be longer but usually aren't)
1490 DrawQ_ColoredString(x, y, va("ping pl%% frags name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1494 if (Sbar_IsTeammatch ())
1496 // show team scores first
1497 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1498 y += (int)Sbar_PrintScoreboardItem((teams + teamsort[i]), x, y);
1502 for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1503 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1508 Sbar_DeathmatchOverlay
1512 void Sbar_MiniDeathmatchOverlay (int x, int y)
1516 // decide where to print
1517 if (gamemode == GAME_TRANSFUSION)
1518 numlines = (vid_conwidth.integer - x + 127) / 128;
1520 numlines = (vid_conheight.integer - y + 7) / 8;
1522 // give up if there isn't room
1523 if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1530 for (i = 0; i < scoreboardlines; i++)
1531 if (fragsort[i] == cl.playerentity - 1)
1536 i = min(i, scoreboardlines - numlines);
1539 if (gamemode == GAME_TRANSFUSION)
1541 for (;i < scoreboardlines && x < vid_conwidth.integer;i++)
1542 x += 128 + (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1546 for (;i < scoreboardlines && y < vid_conheight.integer;i++)
1547 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1553 Sbar_IntermissionOverlay
1557 void Sbar_IntermissionOverlay (void)
1562 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1563 //if (cl.gametype == GAME_DEATHMATCH)
1564 if (!cl.islocalgame)
1566 Sbar_DeathmatchOverlay ();
1570 sbar_x = (vid_conwidth.integer - 320) >> 1;
1571 sbar_y = (vid_conheight.integer - 200) >> 1;
1573 DrawQ_Pic (sbar_x + 64, sbar_y + 24, sb_complete, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1574 DrawQ_Pic (sbar_x + 0, sbar_y + 56, sb_inter, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1577 dig = (int)cl.completed_time / 60;
1578 Sbar_DrawNum (160, 64, dig, 3, 0);
1579 num = (int)cl.completed_time - dig*60;
1580 if (gamemode != GAME_NEXUIZ)
1581 Sbar_DrawPic (234,64,sb_colon);
1582 Sbar_DrawPic (246,64,sb_nums[0][num/10]);
1583 Sbar_DrawPic (266,64,sb_nums[0][num%10]);
1585 Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
1586 if (gamemode != GAME_NEXUIZ)
1587 Sbar_DrawPic (232, 104, sb_slash);
1588 Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1590 Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1591 if (gamemode != GAME_NEXUIZ)
1592 Sbar_DrawPic (232, 144, sb_slash);
1593 Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1604 void Sbar_FinaleOverlay (void)
1606 DrawQ_Pic((vid_conwidth.integer - sb_finale->width)/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);