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)(max(0, 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 = max(0, 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 ();
1122 int redflag, blueflag;
1124 // we have a max time 2s (min time = 0)
1125 if ((time = max(0, cl.time - cl.weapontime)) < 2)
1127 fade = (1.0 - 0.5 * time);
1129 for (i = 0; i < 8;i++)
1130 if (cl.stats[STAT_ITEMS] & (1 << i))
1131 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1133 if((cl.stats[STAT_ITEMS] & (1<<12)))
1134 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1137 //if (!cl.islocalgame)
1138 // Sbar_DrawFrags ();
1141 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1143 Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1146 redflag = ((cl.stats[STAT_ITEMS]>>15) & 3);
1148 Sbar_DrawPic (10, -85, sb_items[redflag+10]);
1149 blueflag = ((cl.stats[STAT_ITEMS]>>17) & 3);
1151 Sbar_DrawPic (10, -145, sb_items[blueflag+14]);
1154 Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1157 if(cl.stats[STAT_HEALTH] > 100)
1158 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1159 else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1160 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1162 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1164 // AK dont draw ammo for the laser
1165 if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1167 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1168 Sbar_DrawPic (519, 0, sb_ammo[0]);
1169 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1170 Sbar_DrawPic (519, 0, sb_ammo[1]);
1171 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1172 Sbar_DrawPic (519, 0, sb_ammo[2]);
1173 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1174 Sbar_DrawPic (519, 0, sb_ammo[3]);
1176 if(cl.stats[STAT_AMMO] <= 10)
1177 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1179 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1184 DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1187 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1188 // Sbar_MiniDeathmatchOverlay (0, 17);
1190 else if (gamemode == GAME_ZYMOTIC)
1193 float scale = 64.0f / 256.0f;
1194 float kickoffset[3];
1195 VectorClear(kickoffset);
1198 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1199 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1201 sbar_x = (int)((vid_conwidth.integer - 256 * scale)/2 + kickoffset[0]);
1202 sbar_y = (int)((vid_conheight.integer - 256 * scale)/2 + kickoffset[1]);
1203 // left1 16, 48 : 126 -66
1204 // left2 16, 128 : 196 -66
1205 // right 176, 48 : 196 -136
1206 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);
1207 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);
1208 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);
1209 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1211 float scale = 128.0f / 256.0f;
1212 float healthstart, healthheight, healthstarttc, healthendtc;
1213 float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1214 float ammostart, ammoheight, ammostarttc, ammoendtc;
1215 float clipstart, clipheight, clipstarttc, clipendtc;
1216 float kickoffset[3], offset;
1217 VectorClear(kickoffset);
1220 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1221 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1223 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1224 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1225 offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1226 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);
1227 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);
1228 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);
1229 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);
1230 healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1231 shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1232 healthstart = 204 - healthheight;
1233 shieldstart = healthstart - shieldheight;
1234 healthstarttc = healthstart * (1.0f / 256.0f);
1235 healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1236 shieldstarttc = shieldstart * (1.0f / 256.0f);
1237 shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1238 ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1239 ammostart = 114 - ammoheight;
1240 ammostarttc = ammostart * (1.0f / 256.0f);
1241 ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1242 clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1243 clipstart = 190 - clipheight;
1244 clipstarttc = clipstart * (1.0f / 256.0f);
1245 clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1246 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);
1247 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);
1248 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);
1249 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);
1250 DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1251 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1254 else // Quake and others
1256 sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1257 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1258 //if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1259 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1262 sbar_x = (vid_conwidth.integer - 320)/2;
1266 if (gamemode != GAME_GOODVSBAD2)
1267 Sbar_DrawInventory ();
1268 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1272 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1274 if (gamemode != GAME_GOODVSBAD2)
1275 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1276 Sbar_DrawScoreboard ();
1280 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1282 // keys (hipnotic only)
1283 //MED 01/04/97 moved keys here so they would not be overwritten
1284 if (gamemode == GAME_HIPNOTIC)
1286 if (cl.stats[STAT_ITEMS] & IT_KEY1)
1287 Sbar_DrawPic (209, 3, sb_items[0]);
1288 if (cl.stats[STAT_ITEMS] & IT_KEY2)
1289 Sbar_DrawPic (209, 12, sb_items[1]);
1292 if (gamemode != GAME_GOODVSBAD2)
1294 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1296 Sbar_DrawNum (24, 0, 666, 3, 1);
1297 Sbar_DrawPic (0, 0, sb_disc);
1301 if (gamemode == GAME_ROGUE)
1303 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1304 if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1305 Sbar_DrawPic (0, 0, sb_armor[2]);
1306 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1307 Sbar_DrawPic (0, 0, sb_armor[1]);
1308 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1309 Sbar_DrawPic (0, 0, sb_armor[0]);
1313 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1314 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1315 Sbar_DrawPic (0, 0, sb_armor[2]);
1316 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1317 Sbar_DrawPic (0, 0, sb_armor[1]);
1318 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1319 Sbar_DrawPic (0, 0, sb_armor[0]);
1328 Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1331 if (gamemode == GAME_ROGUE)
1333 if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1334 Sbar_DrawPic (224, 0, sb_ammo[0]);
1335 else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1336 Sbar_DrawPic (224, 0, sb_ammo[1]);
1337 else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1338 Sbar_DrawPic (224, 0, sb_ammo[2]);
1339 else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1340 Sbar_DrawPic (224, 0, sb_ammo[3]);
1341 else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1342 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1343 else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1344 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1345 else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1346 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1350 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1351 Sbar_DrawPic (224, 0, sb_ammo[0]);
1352 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1353 Sbar_DrawPic (224, 0, sb_ammo[1]);
1354 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1355 Sbar_DrawPic (224, 0, sb_ammo[2]);
1356 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1357 Sbar_DrawPic (224, 0, sb_ammo[3]);
1360 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1364 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1365 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1366 if (!cl.islocalgame && vid_conwidth.integer > 320)
1368 if (gamemode == GAME_TRANSFUSION)
1369 Sbar_MiniDeathmatchOverlay (0, 0);
1371 Sbar_MiniDeathmatchOverlay (324, vid_conheight.integer - sb_lines);
1378 if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && crosshair.integer <= NUMCROSSHAIRS && !cl.intermission && !r_letterbox.value && (pic = r_crosshairs[crosshair.integer]))
1379 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);
1381 if (cl_prydoncursor.integer)
1382 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);
1385 //=============================================================================
1389 Sbar_DeathmatchOverlay
1393 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1397 minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : cl.time - s->qw_entertime) / 60.0);
1398 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1400 if (s->qw_spectator)
1402 if (s->qw_ping || s->qw_packetloss)
1403 DrawQ_ColoredString(x, y, va("%4i %3i %4i spectator %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes, (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1405 DrawQ_ColoredString(x, y, va(" %4i spectator %c%s", minutes, (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1409 // draw colors behind score
1410 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1411 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);
1412 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1413 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);
1415 //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);
1416 if (s->qw_ping || s->qw_packetloss)
1417 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 );
1419 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 );
1424 if (s->qw_spectator)
1426 if (s->qw_ping || s->qw_packetloss)
1427 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 );
1429 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 );
1433 // draw colors behind score
1434 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1435 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);
1436 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1437 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);
1439 //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);
1440 if (s->qw_ping || s->qw_packetloss)
1441 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 );
1443 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 );
1449 void Sbar_DeathmatchOverlay (void)
1453 // request new ping times every two second
1454 if (cl.last_ping_request < realtime - 2 && cls.netcon)
1456 cl.last_ping_request = realtime;
1457 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1459 MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
1460 MSG_WriteString(&cls.netcon->message, "pings");
1462 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)
1464 // 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
1465 static int ping_anyway_counter = 0;
1466 if(cl.parsingtextexpectingpingforscores == 1)
1468 Con_DPrintf("want to send ping, but still waiting for other reply\n");
1469 if(++ping_anyway_counter >= 5)
1470 cl.parsingtextexpectingpingforscores = 0;
1472 if(cl.parsingtextexpectingpingforscores != 1)
1474 ping_anyway_counter = 0;
1475 cl.parsingtextexpectingpingforscores = 1; // hide the output of the next ping report
1476 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1477 MSG_WriteString(&cls.netcon->message, "ping");
1482 // newer server definitely has pings command, so use it for more efficiency
1483 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1484 MSG_WriteString(&cls.netcon->message, "pings");
1488 DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1494 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1496 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)
1497 DrawQ_ColoredString(x, y, va("ping pl%% time frags team name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1501 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)
1502 DrawQ_ColoredString(x, y, va("ping pl%% frags name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1506 if (Sbar_IsTeammatch ())
1508 // show team scores first
1509 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1510 y += (int)Sbar_PrintScoreboardItem((teams + teamsort[i]), x, y);
1514 for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1515 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1520 Sbar_DeathmatchOverlay
1524 void Sbar_MiniDeathmatchOverlay (int x, int y)
1528 // decide where to print
1529 if (gamemode == GAME_TRANSFUSION)
1530 numlines = (vid_conwidth.integer - x + 127) / 128;
1532 numlines = (vid_conheight.integer - y + 7) / 8;
1534 // give up if there isn't room
1535 if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1542 for (i = 0; i < scoreboardlines; i++)
1543 if (fragsort[i] == cl.playerentity - 1)
1548 i = min(i, scoreboardlines - numlines);
1551 if (gamemode == GAME_TRANSFUSION)
1553 for (;i < scoreboardlines && x < vid_conwidth.integer;i++)
1554 x += 128 + (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1558 for (;i < scoreboardlines && y < vid_conheight.integer;i++)
1559 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1565 Sbar_IntermissionOverlay
1569 void Sbar_IntermissionOverlay (void)
1574 // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1575 //if (cl.gametype == GAME_DEATHMATCH)
1576 if (!cl.islocalgame)
1578 Sbar_DeathmatchOverlay ();
1582 sbar_x = (vid_conwidth.integer - 320) >> 1;
1583 sbar_y = (vid_conheight.integer - 200) >> 1;
1585 DrawQ_Pic (sbar_x + 64, sbar_y + 24, sb_complete, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1586 DrawQ_Pic (sbar_x + 0, sbar_y + 56, sb_inter, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1589 dig = (int)cl.completed_time / 60;
1590 Sbar_DrawNum (160, 64, dig, 3, 0);
1591 num = (int)cl.completed_time - dig*60;
1592 if (gamemode != GAME_NEXUIZ)
1593 Sbar_DrawPic (234,64,sb_colon);
1594 Sbar_DrawPic (246,64,sb_nums[0][num/10]);
1595 Sbar_DrawPic (266,64,sb_nums[0][num%10]);
1597 Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
1598 if (gamemode != GAME_NEXUIZ)
1599 Sbar_DrawPic (232, 104, sb_slash);
1600 Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1602 Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1603 if (gamemode != GAME_NEXUIZ)
1604 Sbar_DrawPic (232, 144, sb_slash);
1605 Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1616 void Sbar_FinaleOverlay (void)
1618 DrawQ_Pic((vid_conwidth.integer - sb_finale->width)/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);