]> icculus.org git repositories - divverent/darkplaces.git/blob - sbar.c
added a score-distribution/place/score block left of the hud
[divverent/darkplaces.git] / sbar.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
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.
8
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.
12
13 See the GNU General Public License for more details.
14
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.
18
19 */
20 // sbar.c -- status bar code
21
22 #include "quakedef.h"
23
24 cachepic_t *sb_disc;
25
26 #define STAT_MINUS 10 // num frame for '-' stats digit
27 cachepic_t *sb_nums[2][11];
28 cachepic_t *sb_colon, *sb_slash;
29 cachepic_t *sb_ibar;
30 cachepic_t *sb_sbar;
31 cachepic_t *sb_scorebar;
32 // AK only used by NEX
33 cachepic_t *sb_sbar_minimal;
34 cachepic_t *sb_sbar_overlay;
35
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];
42
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];
46 cachepic_t *sb_health; // GAME_NEXUIZ
47
48 cachepic_t *sb_face_invis;
49 cachepic_t *sb_face_quad;
50 cachepic_t *sb_face_invuln;
51 cachepic_t *sb_face_invis_invuln;
52
53 qboolean sb_showscores;
54
55 int sb_lines;                   // scan lines to draw
56
57 cachepic_t *rsb_invbar[2];
58 cachepic_t *rsb_weapons[5];
59 cachepic_t *rsb_items[2];
60 cachepic_t *rsb_ammo[3];
61 cachepic_t *rsb_teambord;               // PGM 01/19/97 - team color border
62
63 //MED 01/04/97 added two more weapons + 3 alternates for grenade launcher
64 cachepic_t *hsb_weapons[7][5];   // 0 is active, 1 is owned, 2-5 are flashes
65 //MED 01/04/97 added array to simplify weapon parsing
66 int hipweapons[4] = {HIT_LASER_CANNON_BIT,HIT_MJOLNIR_BIT,4,HIT_PROXIMITY_GUN_BIT};
67 //MED 01/04/97 added hipnotic items array
68 cachepic_t *hsb_items[2];
69
70 //GAME_SOM stuff:
71 cachepic_t *somsb_health;
72 cachepic_t *somsb_ammo[4];
73 cachepic_t *somsb_armor[3];
74
75 cachepic_t *zymsb_crosshair_center;
76 cachepic_t *zymsb_crosshair_line;
77 cachepic_t *zymsb_crosshair_health;
78 cachepic_t *zymsb_crosshair_ammo;
79 cachepic_t *zymsb_crosshair_clip;
80 cachepic_t *zymsb_crosshair_background;
81 cachepic_t *zymsb_crosshair_left1;
82 cachepic_t *zymsb_crosshair_left2;
83 cachepic_t *zymsb_crosshair_right;
84
85 cachepic_t *sb_ranking;
86 cachepic_t *sb_complete;
87 cachepic_t *sb_inter;
88 cachepic_t *sb_finale;
89
90 cvar_t showfps = {CVAR_SAVE, "showfps", "0", "shows your rendered fps (frames per second)"};
91 cvar_t showtime = {CVAR_SAVE, "showtime", "0", "shows current time of day (useful on screenshots)"};
92 cvar_t showtime_format = {CVAR_SAVE, "showtime_format", "%H:%M:%S", "format string for time of day"};
93 cvar_t showdate = {CVAR_SAVE, "showdate", "0", "shows current date (useful on screenshots)"};
94 cvar_t showdate_format = {CVAR_SAVE, "showdate_format", "%Y-%m-%d", "format string for date"};
95 cvar_t sbar_alpha_bg = {CVAR_SAVE, "sbar_alpha_bg", "0.4", "opacity value of the statusbar background image"};
96 cvar_t sbar_alpha_fg = {CVAR_SAVE, "sbar_alpha_fg", "1", "opacity value of the statusbar weapon/item icons and numbers"};
97 cvar_t sbar_hudselector = {CVAR_SAVE, "sbar_hudselector", "0", "selects which of the builtin hud layouts to use (meaning is somewhat dependent on gamemode, so nexuiz has a very different set of hud layouts than quake for example)"};
98
99 cvar_t cl_deathscoreboard = {0, "cl_deathscoreboard", "1", "shows scoreboard (+showscores) while dead"};
100
101 cvar_t crosshair_color_red = {CVAR_SAVE, "crosshair_color_red", "1", "customizable crosshair color"};
102 cvar_t crosshair_color_green = {CVAR_SAVE, "crosshair_color_green", "0", "customizable crosshair color"};
103 cvar_t crosshair_color_blue = {CVAR_SAVE, "crosshair_color_blue", "0", "customizable crosshair color"};
104 cvar_t crosshair_color_alpha = {CVAR_SAVE, "crosshair_color_alpha", "1", "how opaque the crosshair should be"};
105 cvar_t crosshair_size = {CVAR_SAVE, "crosshair_size", "1", "adjusts size of the crosshair on the screen"};
106
107 void Sbar_MiniDeathmatchOverlay (int x, int y);
108 void Sbar_DeathmatchOverlay (void);
109 void Sbar_IntermissionOverlay (void);
110 void Sbar_FinaleOverlay (void);
111
112
113 /*
114 ===============
115 Sbar_ShowScores
116
117 Tab key down
118 ===============
119 */
120 void Sbar_ShowScores (void)
121 {
122         if (sb_showscores)
123                 return;
124         sb_showscores = true;
125 }
126
127 /*
128 ===============
129 Sbar_DontShowScores
130
131 Tab key up
132 ===============
133 */
134 void Sbar_DontShowScores (void)
135 {
136         sb_showscores = false;
137 }
138
139 void sbar_start(void)
140 {
141         int i;
142
143         if (gamemode == GAME_NETHERWORLD)
144         {
145         }
146         else if (gamemode == GAME_SOM)
147         {
148                 sb_disc = Draw_CachePic("gfx/disc", true);
149
150                 for (i = 0;i < 10;i++)
151                         sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
152
153                 somsb_health = Draw_CachePic("gfx/hud_health", true);
154                 somsb_ammo[0] = Draw_CachePic("gfx/sb_shells", true);
155                 somsb_ammo[1] = Draw_CachePic("gfx/sb_nails", true);
156                 somsb_ammo[2] = Draw_CachePic("gfx/sb_rocket", true);
157                 somsb_ammo[3] = Draw_CachePic("gfx/sb_cells", true);
158                 somsb_armor[0] = Draw_CachePic("gfx/sb_armor1", true);
159                 somsb_armor[1] = Draw_CachePic("gfx/sb_armor2", true);
160                 somsb_armor[2] = Draw_CachePic("gfx/sb_armor3", true);
161         }
162         else if (gamemode == GAME_NEXUIZ)
163         {
164                 for (i = 0;i < 10;i++)
165                         sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
166                 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus", true);
167
168                 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells", true);
169                 sb_ammo[1] = Draw_CachePic ("gfx/sb_bullets", true);
170                 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket", true);
171                 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells", true);
172
173                 sb_armor[0] = Draw_CachePic ("gfx/sb_armor", true);
174                 sb_armor[1] = NULL;
175                 sb_armor[2] = NULL;
176
177                 sb_health = Draw_CachePic ("gfx/sb_health", true);
178
179                 sb_items[2] = Draw_CachePic ("gfx/sb_slowmo", true);
180                 sb_items[3] = Draw_CachePic ("gfx/sb_invinc", true);
181                 sb_items[4] = Draw_CachePic ("gfx/sb_energy", true);
182                 sb_items[5] = Draw_CachePic ("gfx/sb_str", true);
183
184                 sb_items[11] = Draw_CachePic ("gfx/sb_flag_red_taken", true);
185                 sb_items[12] = Draw_CachePic ("gfx/sb_flag_red_lost", true);
186                 sb_items[13] = Draw_CachePic ("gfx/sb_flag_red_carrying", true);
187                 sb_items[14] = Draw_CachePic ("gfx/sb_key_carrying", true);
188                 sb_items[15] = Draw_CachePic ("gfx/sb_flag_blue_taken", true);
189                 sb_items[16] = Draw_CachePic ("gfx/sb_flag_blue_lost", true);
190                 sb_items[17] = Draw_CachePic ("gfx/sb_flag_blue_carrying", true);
191
192                 sb_sbar = Draw_CachePic("gfx/sbar", true);
193                 sb_sbar_minimal = Draw_CachePic("gfx/sbar_minimal", true);
194                 sb_sbar_overlay = Draw_CachePic("gfx/sbar_overlay", true);
195
196                 for(i = 0; i < 9;i++)
197                         sb_weapons[0][i] = Draw_CachePic(va("gfx/inv_weapon%i",i), true);
198         }
199         else if (gamemode == GAME_ZYMOTIC)
200         {
201                 zymsb_crosshair_center = Draw_CachePic ("gfx/hud/crosshair_center", true);
202                 zymsb_crosshair_line = Draw_CachePic ("gfx/hud/crosshair_line", true);
203                 zymsb_crosshair_health = Draw_CachePic ("gfx/hud/crosshair_health", true);
204                 zymsb_crosshair_clip = Draw_CachePic ("gfx/hud/crosshair_clip", true);
205                 zymsb_crosshair_ammo = Draw_CachePic ("gfx/hud/crosshair_ammo", true);
206                 zymsb_crosshair_background = Draw_CachePic ("gfx/hud/crosshair_background", true);
207                 zymsb_crosshair_left1 = Draw_CachePic ("gfx/hud/crosshair_left1", true);
208                 zymsb_crosshair_left2 = Draw_CachePic ("gfx/hud/crosshair_left2", true);
209                 zymsb_crosshair_right = Draw_CachePic ("gfx/hud/crosshair_right", true);
210         }
211         else
212         {
213                 sb_disc = Draw_CachePic("gfx/disc", true);
214
215                 for (i = 0;i < 10;i++)
216                 {
217                         sb_nums[0][i] = Draw_CachePic (va("gfx/num_%i",i), true);
218                         sb_nums[1][i] = Draw_CachePic (va("gfx/anum_%i",i), true);
219                 }
220
221                 sb_nums[0][10] = Draw_CachePic ("gfx/num_minus", true);
222                 sb_nums[1][10] = Draw_CachePic ("gfx/anum_minus", true);
223
224                 sb_colon = Draw_CachePic ("gfx/num_colon", true);
225                 sb_slash = Draw_CachePic ("gfx/num_slash", true);
226
227                 sb_weapons[0][0] = Draw_CachePic ("gfx/inv_shotgun", true);
228                 sb_weapons[0][1] = Draw_CachePic ("gfx/inv_sshotgun", true);
229                 sb_weapons[0][2] = Draw_CachePic ("gfx/inv_nailgun", true);
230                 sb_weapons[0][3] = Draw_CachePic ("gfx/inv_snailgun", true);
231                 sb_weapons[0][4] = Draw_CachePic ("gfx/inv_rlaunch", true);
232                 sb_weapons[0][5] = Draw_CachePic ("gfx/inv_srlaunch", true);
233                 sb_weapons[0][6] = Draw_CachePic ("gfx/inv_lightng", true);
234
235                 sb_weapons[1][0] = Draw_CachePic ("gfx/inv2_shotgun", true);
236                 sb_weapons[1][1] = Draw_CachePic ("gfx/inv2_sshotgun", true);
237                 sb_weapons[1][2] = Draw_CachePic ("gfx/inv2_nailgun", true);
238                 sb_weapons[1][3] = Draw_CachePic ("gfx/inv2_snailgun", true);
239                 sb_weapons[1][4] = Draw_CachePic ("gfx/inv2_rlaunch", true);
240                 sb_weapons[1][5] = Draw_CachePic ("gfx/inv2_srlaunch", true);
241                 sb_weapons[1][6] = Draw_CachePic ("gfx/inv2_lightng", true);
242
243                 for (i = 0;i < 5;i++)
244                 {
245                         sb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_shotgun",i+1), true);
246                         sb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_sshotgun",i+1), true);
247                         sb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_nailgun",i+1), true);
248                         sb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_snailgun",i+1), true);
249                         sb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_rlaunch",i+1), true);
250                         sb_weapons[2+i][5] = Draw_CachePic (va("gfx/inva%i_srlaunch",i+1), true);
251                         sb_weapons[2+i][6] = Draw_CachePic (va("gfx/inva%i_lightng",i+1), true);
252                 }
253
254                 sb_ammo[0] = Draw_CachePic ("gfx/sb_shells", true);
255                 sb_ammo[1] = Draw_CachePic ("gfx/sb_nails", true);
256                 sb_ammo[2] = Draw_CachePic ("gfx/sb_rocket", true);
257                 sb_ammo[3] = Draw_CachePic ("gfx/sb_cells", true);
258
259                 sb_armor[0] = Draw_CachePic ("gfx/sb_armor1", true);
260                 sb_armor[1] = Draw_CachePic ("gfx/sb_armor2", true);
261                 sb_armor[2] = Draw_CachePic ("gfx/sb_armor3", true);
262
263                 sb_items[0] = Draw_CachePic ("gfx/sb_key1", true);
264                 sb_items[1] = Draw_CachePic ("gfx/sb_key2", true);
265                 sb_items[2] = Draw_CachePic ("gfx/sb_invis", true);
266                 sb_items[3] = Draw_CachePic ("gfx/sb_invuln", true);
267                 sb_items[4] = Draw_CachePic ("gfx/sb_suit", true);
268                 sb_items[5] = Draw_CachePic ("gfx/sb_quad", true);
269
270                 sb_sigil[0] = Draw_CachePic ("gfx/sb_sigil1", true);
271                 sb_sigil[1] = Draw_CachePic ("gfx/sb_sigil2", true);
272                 sb_sigil[2] = Draw_CachePic ("gfx/sb_sigil3", true);
273                 sb_sigil[3] = Draw_CachePic ("gfx/sb_sigil4", true);
274
275                 sb_faces[4][0] = Draw_CachePic ("gfx/face1", true);
276                 sb_faces[4][1] = Draw_CachePic ("gfx/face_p1", true);
277                 sb_faces[3][0] = Draw_CachePic ("gfx/face2", true);
278                 sb_faces[3][1] = Draw_CachePic ("gfx/face_p2", true);
279                 sb_faces[2][0] = Draw_CachePic ("gfx/face3", true);
280                 sb_faces[2][1] = Draw_CachePic ("gfx/face_p3", true);
281                 sb_faces[1][0] = Draw_CachePic ("gfx/face4", true);
282                 sb_faces[1][1] = Draw_CachePic ("gfx/face_p4", true);
283                 sb_faces[0][0] = Draw_CachePic ("gfx/face5", true);
284                 sb_faces[0][1] = Draw_CachePic ("gfx/face_p5", true);
285
286                 sb_face_invis = Draw_CachePic ("gfx/face_invis", true);
287                 sb_face_invuln = Draw_CachePic ("gfx/face_invul2", true);
288                 sb_face_invis_invuln = Draw_CachePic ("gfx/face_inv2", true);
289                 sb_face_quad = Draw_CachePic ("gfx/face_quad", true);
290
291                 sb_sbar = Draw_CachePic ("gfx/sbar", true);
292                 sb_ibar = Draw_CachePic ("gfx/ibar", true);
293                 sb_scorebar = Draw_CachePic ("gfx/scorebar", true);
294
295         //MED 01/04/97 added new hipnotic weapons
296                 if (gamemode == GAME_HIPNOTIC)
297                 {
298                         hsb_weapons[0][0] = Draw_CachePic ("gfx/inv_laser", true);
299                         hsb_weapons[0][1] = Draw_CachePic ("gfx/inv_mjolnir", true);
300                         hsb_weapons[0][2] = Draw_CachePic ("gfx/inv_gren_prox", true);
301                         hsb_weapons[0][3] = Draw_CachePic ("gfx/inv_prox_gren", true);
302                         hsb_weapons[0][4] = Draw_CachePic ("gfx/inv_prox", true);
303
304                         hsb_weapons[1][0] = Draw_CachePic ("gfx/inv2_laser", true);
305                         hsb_weapons[1][1] = Draw_CachePic ("gfx/inv2_mjolnir", true);
306                         hsb_weapons[1][2] = Draw_CachePic ("gfx/inv2_gren_prox", true);
307                         hsb_weapons[1][3] = Draw_CachePic ("gfx/inv2_prox_gren", true);
308                         hsb_weapons[1][4] = Draw_CachePic ("gfx/inv2_prox", true);
309
310                         for (i = 0;i < 5;i++)
311                         {
312                                 hsb_weapons[2+i][0] = Draw_CachePic (va("gfx/inva%i_laser",i+1), true);
313                                 hsb_weapons[2+i][1] = Draw_CachePic (va("gfx/inva%i_mjolnir",i+1), true);
314                                 hsb_weapons[2+i][2] = Draw_CachePic (va("gfx/inva%i_gren_prox",i+1), true);
315                                 hsb_weapons[2+i][3] = Draw_CachePic (va("gfx/inva%i_prox_gren",i+1), true);
316                                 hsb_weapons[2+i][4] = Draw_CachePic (va("gfx/inva%i_prox",i+1), true);
317                         }
318
319                         hsb_items[0] = Draw_CachePic ("gfx/sb_wsuit", true);
320                         hsb_items[1] = Draw_CachePic ("gfx/sb_eshld", true);
321                 }
322                 else if (gamemode == GAME_ROGUE)
323                 {
324                         rsb_invbar[0] = Draw_CachePic ("gfx/r_invbar1", true);
325                         rsb_invbar[1] = Draw_CachePic ("gfx/r_invbar2", true);
326
327                         rsb_weapons[0] = Draw_CachePic ("gfx/r_lava", true);
328                         rsb_weapons[1] = Draw_CachePic ("gfx/r_superlava", true);
329                         rsb_weapons[2] = Draw_CachePic ("gfx/r_gren", true);
330                         rsb_weapons[3] = Draw_CachePic ("gfx/r_multirock", true);
331                         rsb_weapons[4] = Draw_CachePic ("gfx/r_plasma", true);
332
333                         rsb_items[0] = Draw_CachePic ("gfx/r_shield1", true);
334                         rsb_items[1] = Draw_CachePic ("gfx/r_agrav1", true);
335
336         // PGM 01/19/97 - team color border
337                         rsb_teambord = Draw_CachePic ("gfx/r_teambord", true);
338         // PGM 01/19/97 - team color border
339
340                         rsb_ammo[0] = Draw_CachePic ("gfx/r_ammolava", true);
341                         rsb_ammo[1] = Draw_CachePic ("gfx/r_ammomulti", true);
342                         rsb_ammo[2] = Draw_CachePic ("gfx/r_ammoplasma", true);
343                 }
344         }
345
346         sb_ranking = Draw_CachePic ("gfx/ranking", true);
347         sb_complete = Draw_CachePic ("gfx/complete", true);
348         sb_inter = Draw_CachePic ("gfx/inter", true);
349         sb_finale = Draw_CachePic ("gfx/finale", true);
350 }
351
352 void sbar_shutdown(void)
353 {
354 }
355
356 void sbar_newmap(void)
357 {
358 }
359
360 void Sbar_Init (void)
361 {
362         Cmd_AddCommand("+showscores", Sbar_ShowScores, "show scoreboard");
363         Cmd_AddCommand("-showscores", Sbar_DontShowScores, "hide scoreboard");
364         Cvar_RegisterVariable(&showfps);
365         Cvar_RegisterVariable(&showtime);
366         Cvar_RegisterVariable(&showtime_format);
367         Cvar_RegisterVariable(&showdate);
368         Cvar_RegisterVariable(&showdate_format);
369         Cvar_RegisterVariable(&sbar_alpha_bg);
370         Cvar_RegisterVariable(&sbar_alpha_fg);
371         Cvar_RegisterVariable(&sbar_hudselector);
372         Cvar_RegisterVariable(&cl_deathscoreboard);
373
374         Cvar_RegisterVariable(&crosshair_color_red);
375         Cvar_RegisterVariable(&crosshair_color_green);
376         Cvar_RegisterVariable(&crosshair_color_blue);
377         Cvar_RegisterVariable(&crosshair_color_alpha);
378         Cvar_RegisterVariable(&crosshair_size);
379
380         R_RegisterModule("sbar", sbar_start, sbar_shutdown, sbar_newmap);
381 }
382
383
384 //=============================================================================
385
386 // drawing routines are relative to the status bar location
387
388 int sbar_x, sbar_y;
389
390 /*
391 =============
392 Sbar_DrawPic
393 =============
394 */
395 void Sbar_DrawStretchPic (int x, int y, cachepic_t *pic, float alpha, float overridewidth, float overrideheight)
396 {
397         DrawQ_Pic (sbar_x + x, sbar_y + y, pic, overridewidth, overrideheight, 1, 1, 1, alpha, 0);
398 }
399
400 void Sbar_DrawPic (int x, int y, cachepic_t *pic)
401 {
402         DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, sbar_alpha_fg.value, 0);
403 }
404
405 void Sbar_DrawAlphaPic (int x, int y, cachepic_t *pic, float alpha)
406 {
407         DrawQ_Pic (sbar_x + x, sbar_y + y, pic, 0, 0, 1, 1, 1, alpha, 0);
408 }
409
410 /*
411 ================
412 Sbar_DrawCharacter
413
414 Draws one solid graphics character
415 ================
416 */
417 void Sbar_DrawCharacter (int x, int y, int num)
418 {
419         DrawQ_String (sbar_x + x + 4 , sbar_y + y, va("%c", num), 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0, NULL, true);
420 }
421
422 /*
423 ================
424 Sbar_DrawString
425 ================
426 */
427 void Sbar_DrawString (int x, int y, char *str)
428 {
429         DrawQ_String (sbar_x + x, sbar_y + y, str, 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0, NULL, false);
430 }
431
432 /*
433 =============
434 Sbar_DrawNum
435 =============
436 */
437 void Sbar_DrawNum (int x, int y, int num, int digits, int color)
438 {
439         char str[32], *ptr;
440         int l, frame;
441
442         l = sprintf(str, "%i", num);
443         ptr = str;
444         if (l > digits)
445                 ptr += (l-digits);
446         if (l < digits)
447                 x += (digits-l)*24;
448
449         while (*ptr)
450         {
451                 if (*ptr == '-')
452                         frame = STAT_MINUS;
453                 else
454                         frame = *ptr -'0';
455
456                 Sbar_DrawPic (x, y, sb_nums[color][frame]);
457                 x += 24;
458
459                 ptr++;
460         }
461 }
462
463 /*
464 =============
465 Sbar_DrawXNum
466 =============
467 */
468
469 void Sbar_DrawXNum (int x, int y, int num, int digits, int lettersize, float r, float g, float b, float a, int flags)
470 {
471         char str[32], *ptr;
472         int l, frame;
473
474         if (digits < 0)
475         {
476                 digits = -digits;
477                 l = sprintf(str, "%0*i", digits, num);
478         }
479         else
480                 l = sprintf(str, "%i", num);
481         ptr = str;
482         if (l > digits)
483                 ptr += (l-digits);
484         if (l < digits)
485                 x += (digits-l) * lettersize;
486
487         while (*ptr)
488         {
489                 if (*ptr == '-')
490                         frame = STAT_MINUS;
491                 else
492                         frame = *ptr -'0';
493
494                 DrawQ_Pic (sbar_x + x, sbar_y + y, sb_nums[0][frame],lettersize,lettersize,r,g,b,a * sbar_alpha_fg.value,flags);
495                 x += lettersize;
496
497                 ptr++;
498         }
499 }
500
501 //=============================================================================
502
503
504 int Sbar_IsTeammatch()
505 {
506         // currently only nexuiz uses the team score board
507         return ((gamemode == GAME_NEXUIZ)
508                 && (teamplay.integer > 0));
509 }
510
511 /*
512 ===============
513 Sbar_SortFrags
514 ===============
515 */
516 static int fragsort[MAX_SCOREBOARD];
517 static int scoreboardlines;
518
519 //[515]: Sbar_GetPlayer for csqc "getplayerkey" func
520 int Sbar_GetPlayer (int index)
521 {
522         if(index < 0)
523         {
524                 index = -1-index;
525                 if(index >= scoreboardlines)
526                         return -1;
527                 index = fragsort[index];
528         }
529         if(index >= scoreboardlines)
530                 return -1;
531         return index;
532 }
533
534 static scoreboard_t teams[MAX_SCOREBOARD];
535 static int teamsort[MAX_SCOREBOARD];
536 static int teamlines;
537 void Sbar_SortFrags (void)
538 {
539         int i, j, k, color;
540
541         // sort by frags
542         scoreboardlines = 0;
543         for (i=0 ; i<cl.maxclients ; i++)
544         {
545                 if (cl.scores[i].name[0])
546                 {
547                         fragsort[scoreboardlines] = i;
548                         scoreboardlines++;
549                 }
550         }
551
552         for (i=0 ; i<scoreboardlines ; i++)
553                 for (j=0 ; j<scoreboardlines-1-i ; j++)
554                         if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j+1]].frags)
555                         {
556                                 k = fragsort[j];
557                                 fragsort[j] = fragsort[j+1];
558                                 fragsort[j+1] = k;
559                         }
560
561         teamlines = 0;
562         if (Sbar_IsTeammatch ())
563         {
564                 // now sort players by teams.
565                 for (i=0 ; i<scoreboardlines ; i++)
566                 {
567                         for (j=0 ; j<scoreboardlines-1-i ; j++)
568                         {
569                                 if (cl.scores[fragsort[j]].colors < cl.scores[fragsort[j+1]].colors)
570                                 {
571                                         k = fragsort[j];
572                                         fragsort[j] = fragsort[j+1];
573                                         fragsort[j+1] = k;
574                                 }
575                         }
576                 }
577
578                 // calculate team scores
579                 color = -1;
580                 for (i=0 ; i<scoreboardlines ; i++)
581                 {
582                         if (color != (cl.scores[fragsort[i]].colors & 15))
583                         {
584                                 const char* teamname;
585
586                                 color = cl.scores[fragsort[i]].colors & 15;
587                                 teamlines++;
588
589                                 switch (color)
590                                 {
591                                         case 4:
592                                                 teamname = "^1Red Team";
593                                                 break;
594                                         case 13:
595                                                 teamname = "^4Blue Team";
596                                                 break;
597                                         case 9:
598                                                 teamname = "^6Pink Team";
599                                                 break;
600                                         case 12:
601                                                 teamname = "^3Yellow Team";
602                                                 break;
603                                         default:
604                                                 teamname = "Total Team Score";
605                                                 break;
606                                 }
607                                 strlcpy(teams[teamlines-1].name, teamname, sizeof(teams[teamlines-1].name));
608
609                                 teams[teamlines-1].frags = 0;
610                                 teams[teamlines-1].colors = color + 16 * color;
611                         }
612
613                         if (cl.scores[fragsort[i]].frags != -666)
614                         {
615                                 // do not add spedcators
616                                 // (ugly hack for nexuiz)
617                                 teams[teamlines-1].frags += cl.scores[fragsort[i]].frags;
618                         }
619                 }
620
621                 // now sort teams by scores.
622                 for (i=0 ; i<teamlines ; i++)
623                         teamsort[i] = i;
624                 for (i=0 ; i<teamlines ; i++)
625                 {
626                         for (j=0 ; j<teamlines-1-i ; j++)
627                         {
628                                 if (teams[teamsort[j]].frags < teams[teamsort[j+1]].frags)
629                                 {
630                                         k = teamsort[j];
631                                         teamsort[j] = teamsort[j+1];
632                                         teamsort[j+1] = k;
633                                 }
634                         }
635                 }
636         }
637 }
638
639 /*
640 ===============
641 Sbar_SoloScoreboard
642 ===============
643 */
644 void Sbar_SoloScoreboard (void)
645 {
646 #if 1
647         char    str[80], timestr[40];
648         int             max, timelen;
649         int             minutes, seconds;
650         double  t;
651
652         t = (cl.intermission ? cl.completed_time : cl.time);
653         minutes = (int)(t / 60);
654         seconds = (int)(t - 60*floor(t/60));
655
656         // monsters and secrets are now both on the top row
657         if (cl.stats[STAT_TOTALMONSTERS])
658                 Sbar_DrawString(8, 4, va("Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]));
659         if (cl.stats[STAT_TOTALSECRETS])
660                 Sbar_DrawString(8+22*8, 4, va("Secrets:%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]));
661
662         // figure out the map's filename without path or extension
663         strlcpy(str, FS_FileWithoutPath(cl.worldmodel ? cl.worldmodel->name : ""), sizeof(str));
664         if (strrchr(str, '.'))
665                 *(strrchr(str, '.')) = 0;
666
667         // append a : separator and then the full title
668         strlcat(str, ":", sizeof(str));
669         strlcat(str, cl.levelname, sizeof(str));
670
671         // if there's a newline character, terminate the string there
672         if (strchr(str, '\n'))
673                 *(strchr(str, '\n')) = 0;
674
675         // make the time string
676         timelen = sprintf(timestr, " %i:%02i", minutes, seconds);
677
678         // truncate the level name if necessary to make room for time
679         max = 38 - timelen;
680         if ((int)strlen(str) > max)
681                 str[max] = 0;
682
683         // print the filename and message
684         Sbar_DrawString(8, 12, str);
685
686         // print the time
687         Sbar_DrawString(8 + max*8, 12, timestr);
688
689 #else
690         char    str[80];
691         int             minutes, seconds, tens, units;
692         int             l;
693
694         if (gamemode != GAME_NEXUIZ) {
695                 sprintf (str,"Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
696                 Sbar_DrawString (8, 4, str);
697
698                 sprintf (str,"Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
699                 Sbar_DrawString (8, 12, str);
700         }
701
702 // time
703         minutes = (int)(cl.time / 60);
704         seconds = (int)(cl.time - 60*minutes);
705         tens = seconds / 10;
706         units = seconds - 10*tens;
707         sprintf (str,"Time :%3i:%i%i", minutes, tens, units);
708         Sbar_DrawString (184, 4, str);
709
710 // draw level name
711         if (gamemode == GAME_NEXUIZ) {
712                 l = (int) strlen (cl.worldmodel->name);
713                 Sbar_DrawString (232 - l*4, 12, cl.worldmodel->name);
714         } else {
715                 l = (int) strlen (cl.levelname);
716                 Sbar_DrawString (232 - l*4, 12, cl.levelname);
717         }
718 #endif
719 }
720
721 /*
722 ===============
723 Sbar_DrawScoreboard
724 ===============
725 */
726 void Sbar_DrawScoreboard (void)
727 {
728         Sbar_SoloScoreboard ();
729         // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
730         //if (cl.gametype == GAME_DEATHMATCH)
731         if (!cl.islocalgame)
732                 Sbar_DeathmatchOverlay ();
733 }
734
735 //=============================================================================
736
737 // AK to make DrawInventory smaller
738 static void Sbar_DrawWeapon(int nr, float fade, int active)
739 {
740         if (sbar_hudselector.integer == 1)
741         {
742                 // width = 300, height = 100
743                 const int w_width = 32, w_height = 12, w_space = 2, font_size = 8;
744
745                 DrawQ_Pic((vid_conwidth.integer - w_width * 9) * 0.5 + w_width * nr, vid_conheight.integer - w_height, sb_weapons[0][nr], w_width, w_height, (active) ? 1 : 0.6, active ? 1 : 0.6, active ? 1 : 0.6, (active ? 1 : 0.6) * fade * sbar_alpha_fg.value, DRAWFLAG_NORMAL);
746                 DrawQ_String((vid_conwidth.integer - w_width * 9) * 0.5 + w_width * nr + w_space, vid_conheight.integer - w_height + w_space, va("%i",nr+1), 0, font_size, font_size, 1, 1, 0, sbar_alpha_fg.value, 0, NULL, true);
747         }
748         else
749         {
750                 // width = 300, height = 100
751                 const int w_width = 300, w_height = 100, w_space = 10;
752                 const float w_scale = 0.4;
753
754                 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_NORMAL);
755                 //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, NULL, true);
756         }
757 }
758
759 /*
760 ===============
761 Sbar_DrawInventory
762 ===============
763 */
764 void Sbar_DrawInventory (void)
765 {
766         int i;
767         char num[6];
768         float time;
769         int flashon;
770
771         if (gamemode == GAME_ROGUE)
772         {
773                 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
774                         Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], sbar_alpha_bg.value);
775                 else
776                         Sbar_DrawAlphaPic (0, -24, rsb_invbar[1], sbar_alpha_bg.value);
777         }
778         else
779                 Sbar_DrawAlphaPic (0, -24, sb_ibar, sbar_alpha_bg.value);
780
781         // weapons
782         for (i=0 ; i<7 ; i++)
783         {
784                 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<i) )
785                 {
786                         time = cl.item_gettime[i];
787                         flashon = (int)(max(0, cl.time - time)*10);
788                         if (flashon >= 10)
789                         {
790                                 if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i)  )
791                                         flashon = 1;
792                                 else
793                                         flashon = 0;
794                         }
795                         else
796                                 flashon = (flashon%5) + 2;
797
798                         Sbar_DrawAlphaPic (i*24, -16, sb_weapons[flashon][i], sbar_alpha_bg.value);
799                 }
800         }
801
802         // MED 01/04/97
803         // hipnotic weapons
804         if (gamemode == GAME_HIPNOTIC)
805         {
806                 int grenadeflashing=0;
807                 for (i=0 ; i<4 ; i++)
808                 {
809                         if (cl.stats[STAT_ITEMS] & (1<<hipweapons[i]) )
810                         {
811                                 time = max(0, cl.item_gettime[hipweapons[i]]);
812                                 flashon = (int)((cl.time - time)*10);
813                                 if (flashon >= 10)
814                                 {
815                                         if ( cl.stats[STAT_ACTIVEWEAPON] == (1<<hipweapons[i])  )
816                                                 flashon = 1;
817                                         else
818                                                 flashon = 0;
819                                 }
820                                 else
821                                         flashon = (flashon%5) + 2;
822
823                                 // check grenade launcher
824                                 if (i==2)
825                                 {
826                                         if (cl.stats[STAT_ITEMS] & HIT_PROXIMITY_GUN)
827                                         {
828                                                 if (flashon)
829                                                 {
830                                                         grenadeflashing = 1;
831                                                         Sbar_DrawPic (96, -16, hsb_weapons[flashon][2]);
832                                                 }
833                                         }
834                                 }
835                                 else if (i==3)
836                                 {
837                                         if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<4))
838                                         {
839                                                 if (!grenadeflashing)
840                                                         Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
841                                         }
842                                         else
843                                                 Sbar_DrawPic (96, -16, hsb_weapons[flashon][4]);
844                                 }
845                                 else
846                                         Sbar_DrawPic (176 + (i*24), -16, hsb_weapons[flashon][i]);
847                         }
848                 }
849         }
850
851         if (gamemode == GAME_ROGUE)
852         {
853                 // check for powered up weapon.
854                 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
855                         for (i=0;i<5;i++)
856                                 if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i))
857                                         Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]);
858         }
859
860         // ammo counts
861         for (i=0 ; i<4 ; i++)
862         {
863                 sprintf (num, "%3i",cl.stats[STAT_SHELLS+i] );
864                 if (num[0] != ' ')
865                         Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[0] - '0');
866                 if (num[1] != ' ')
867                         Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[1] - '0');
868                 if (num[2] != ' ')
869                         Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0');
870         }
871
872         // items
873         for (i=0 ; i<6 ; i++)
874                 if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
875                 {
876                         //MED 01/04/97 changed keys
877                         if (gamemode != GAME_HIPNOTIC || (i>1))
878                                 Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
879                 }
880
881         //MED 01/04/97 added hipnotic items
882         // hipnotic items
883         if (gamemode == GAME_HIPNOTIC)
884         {
885                 for (i=0 ; i<2 ; i++)
886                         if (cl.stats[STAT_ITEMS] & (1<<(24+i)))
887                                 Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
888         }
889
890         if (gamemode == GAME_ROGUE)
891         {
892                 // new rogue items
893                 for (i=0 ; i<2 ; i++)
894                         if (cl.stats[STAT_ITEMS] & (1<<(29+i)))
895                                 Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
896         }
897         else
898         {
899                 // sigils
900                 for (i=0 ; i<4 ; i++)
901                         if (cl.stats[STAT_ITEMS] & (1<<(28+i)))
902                                 Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
903         }
904 }
905
906 //=============================================================================
907
908 /*
909 ===============
910 Sbar_DrawFrags
911 ===============
912 */
913 void Sbar_DrawFrags (void)
914 {
915         int i, k, l, x, f;
916         char num[12];
917         scoreboard_t *s;
918         unsigned char *c;
919
920         Sbar_SortFrags ();
921
922         // draw the text
923         l = min(scoreboardlines, 4);
924
925         x = 23 * 8;
926
927         for (i = 0;i < l;i++)
928         {
929                 k = fragsort[i];
930                 s = &cl.scores[k];
931
932                 // draw background
933                 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
934                 DrawQ_Fill (sbar_x + x + 10, sbar_y     - 23, 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);
935                 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
936                 DrawQ_Fill (sbar_x + x + 10, sbar_y + 4 - 23, 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);
937
938                 // draw number
939                 f = s->frags;
940                 sprintf (num, "%3i",f);
941
942                 if (k == cl.viewentity - 1)
943                 {
944                         Sbar_DrawCharacter ( x      + 2, -24, 16);
945                         Sbar_DrawCharacter ( x + 32 - 4, -24, 17);
946                 }
947                 Sbar_DrawCharacter (x +  8, -24, num[0]);
948                 Sbar_DrawCharacter (x + 16, -24, num[1]);
949                 Sbar_DrawCharacter (x + 24, -24, num[2]);
950                 x += 32;
951         }
952 }
953
954 //=============================================================================
955
956
957 /*
958 ===============
959 Sbar_DrawFace
960 ===============
961 */
962 void Sbar_DrawFace (void)
963 {
964         int f;
965
966 // PGM 01/19/97 - team color drawing
967 // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
968         if (gamemode == GAME_ROGUE && !cl.islocalgame && (teamplay.integer > 3) && (teamplay.integer < 7))
969         {
970                 char num[12];
971                 scoreboard_t *s;
972                 unsigned char *c;
973
974                 s = &cl.scores[cl.viewentity - 1];
975                 // draw background
976                 Sbar_DrawPic (112, 0, rsb_teambord);
977                 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
978                 DrawQ_Fill (sbar_x + 113, vid_conheight.integer-SBAR_HEIGHT+3, 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);
979                 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
980                 DrawQ_Fill (sbar_x + 113, vid_conheight.integer-SBAR_HEIGHT+12, 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);
981
982                 // draw number
983                 f = s->frags;
984                 sprintf (num, "%3i",f);
985
986                 if ((s->colors & 0xf0)==0)
987                 {
988                         if (num[0] != ' ')
989                                 Sbar_DrawCharacter(109, 3, 18 + num[0] - '0');
990                         if (num[1] != ' ')
991                                 Sbar_DrawCharacter(116, 3, 18 + num[1] - '0');
992                         if (num[2] != ' ')
993                                 Sbar_DrawCharacter(123, 3, 18 + num[2] - '0');
994                 }
995                 else
996                 {
997                         Sbar_DrawCharacter ( 109, 3, num[0]);
998                         Sbar_DrawCharacter ( 116, 3, num[1]);
999                         Sbar_DrawCharacter ( 123, 3, num[2]);
1000                 }
1001
1002                 return;
1003         }
1004 // PGM 01/19/97 - team color drawing
1005
1006         if ( (cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
1007                 Sbar_DrawPic (112, 0, sb_face_invis_invuln);
1008         else if (cl.stats[STAT_ITEMS] & IT_QUAD)
1009                 Sbar_DrawPic (112, 0, sb_face_quad );
1010         else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
1011                 Sbar_DrawPic (112, 0, sb_face_invis );
1012         else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1013                 Sbar_DrawPic (112, 0, sb_face_invuln);
1014         else
1015         {
1016                 f = cl.stats[STAT_HEALTH] / 20;
1017                 f = bound(0, f, 4);
1018                 Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]);
1019         }
1020 }
1021
1022 void Sbar_ShowFPS(void)
1023 {
1024         float fps_x, fps_y, fps_scalex, fps_scaley, fps_height;
1025         char fpsstring[32];
1026         char timestring[32];
1027         char datestring[32];
1028         qboolean red = false;
1029         fpsstring[0] = 0;
1030         timestring[0] = 0;
1031         datestring[0] = 0;
1032         if (showfps.integer)
1033         {
1034                 float calc;
1035                 static double nexttime = 0, lasttime = 0;
1036                 static double framerate = 0;
1037                 static int framecount = 0;
1038                 double newtime;
1039                 newtime = realtime;
1040                 if (newtime >= nexttime)
1041                 {
1042                         framerate = framecount / (newtime - lasttime);
1043                         lasttime = newtime;
1044                         nexttime = max(nexttime + 1, lasttime - 1);
1045                         framecount = 0;
1046                 }
1047                 framecount++;
1048                 calc = framerate;
1049
1050                 if ((red = (calc < 1.0f)))
1051                         dpsnprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0f / calc + 0.5));
1052                 else
1053                         dpsnprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(calc + 0.5));
1054         }
1055         if (showtime.integer)
1056                 strlcpy(timestring, Sys_TimeString(showtime_format.string), sizeof(timestring));
1057         if (showdate.integer)
1058                 strlcpy(datestring, Sys_TimeString(showdate_format.string), sizeof(datestring));
1059         if (fpsstring[0] || timestring[0])
1060         {
1061                 fps_scalex = 12;
1062                 fps_scaley = 12;
1063                 fps_height = fps_scaley * ((fpsstring[0] != 0) + (timestring[0] != 0) + (datestring[0] != 0));
1064                 //fps_y = vid_conheight.integer - sb_lines; // yes this may draw over the sbar
1065                 //fps_y = bound(0, fps_y, vid_conheight.integer - fps_height);
1066                 fps_y = vid_conheight.integer - fps_height;
1067                 if (fpsstring[0])
1068                 {
1069                         fps_x = vid_conwidth.integer - fps_scalex * strlen(fpsstring);
1070                         DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(fpsstring), fps_scaley, 0, 0, 0, 0.5, 0);
1071                         if (red)
1072                                 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 0, 0, 1, 0, NULL, true);
1073                         else
1074                                 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true);
1075                         fps_y += fps_scaley;
1076                 }
1077                 if (timestring[0])
1078                 {
1079                         fps_x = vid_conwidth.integer - fps_scalex * strlen(timestring);
1080                         DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(timestring), fps_scaley, 0, 0, 0, 0.5, 0);
1081                         DrawQ_String(fps_x, fps_y, timestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true);
1082                         fps_y += fps_scaley;
1083                 }
1084                 if (datestring[0])
1085                 {
1086                         fps_x = vid_conwidth.integer - fps_scalex * strlen(datestring);
1087                         DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(datestring), fps_scaley, 0, 0, 0, 0.5, 0);
1088                         DrawQ_String(fps_x, fps_y, datestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0, NULL, true);
1089                         fps_y += fps_scaley;
1090                 }
1091         }
1092 }
1093
1094 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)
1095 {
1096         float r[5];
1097         c2 = bound(0, c2, 1);
1098         c1 = bound(0, c1, 1 - c2);
1099         r[0] = 0;
1100         r[1] = rangey + rangeheight * (c2 + c1);
1101         r[2] = rangey + rangeheight * (c2);
1102         r[3] = rangey;
1103         r[4] = height;
1104         if (r[1] > r[0])
1105                 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);
1106         if (r[2] > r[1])
1107                 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);
1108         if (r[3] > r[2])
1109                 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);
1110         if (r[4] > r[3])
1111                 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);
1112 }
1113
1114 /*
1115 ===============
1116 Sbar_Draw
1117 ===============
1118 */
1119 extern float v_dmg_time, v_dmg_roll, v_dmg_pitch;
1120 extern cvar_t v_kicktime;
1121 void Sbar_Score (void);
1122 void Sbar_Draw (void)
1123 {
1124         cachepic_t *pic;
1125
1126         if(cl.csqc_vidvars.drawenginesbar)      //[515]: csqc drawsbar
1127         {
1128                 if (sb_showscores)
1129                         Sbar_DrawScoreboard ();
1130                 else if (cl.intermission == 1)
1131                 {
1132                         if(gamemode == GAME_NEXUIZ) // display full scoreboard (that is, show scores + map name)
1133                         {
1134                                 Sbar_DrawScoreboard();
1135                                 return;
1136                         }
1137                         Sbar_IntermissionOverlay();
1138                 }
1139                 else if (cl.intermission == 2)
1140                         Sbar_FinaleOverlay();
1141                 else if (gamemode == GAME_NETHERWORLD)
1142                 {
1143                 }
1144                 else if (gamemode == GAME_SOM)
1145                 {
1146                         if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1147                                 Sbar_DrawScoreboard ();
1148                         else if (sb_lines)
1149                         {
1150                                 // this is the top left of the sbar area
1151                                 sbar_x = 0;
1152                                 sbar_y = vid_conheight.integer - 24*3;
1153
1154                                 // armor
1155                                 if (cl.stats[STAT_ARMOR])
1156                                 {
1157                                         if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1158                                                 Sbar_DrawPic(0, 0, somsb_armor[2]);
1159                                         else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1160                                                 Sbar_DrawPic(0, 0, somsb_armor[1]);
1161                                         else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1162                                                 Sbar_DrawPic(0, 0, somsb_armor[0]);
1163                                         Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1164                                 }
1165
1166                                 // health
1167                                 Sbar_DrawPic(0, 24, somsb_health);
1168                                 Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1169
1170                                 // ammo icon
1171                                 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1172                                         Sbar_DrawPic(0, 48, somsb_ammo[0]);
1173                                 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1174                                         Sbar_DrawPic(0, 48, somsb_ammo[1]);
1175                                 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1176                                         Sbar_DrawPic(0, 48, somsb_ammo[2]);
1177                                 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1178                                         Sbar_DrawPic(0, 48, somsb_ammo[3]);
1179                                 Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
1180                                 if (cl.stats[STAT_SHELLS])
1181                                         Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
1182                         }
1183                 }
1184                 else if (gamemode == GAME_NEXUIZ)
1185                 {
1186                         if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1187                         {
1188                                 sbar_x = (vid_conwidth.integer - 640)/2;
1189                                 sbar_y = vid_conheight.integer - 47;
1190                                 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1191                                 Sbar_DrawScoreboard ();
1192                         }
1193                         else if (sb_lines && sbar_hudselector.integer == 1)
1194                         {
1195                                 int i;
1196                                 float fade;
1197                                 int redflag, blueflag;
1198
1199                                 sbar_x = (vid_conwidth.integer - 320)/2;
1200                                 sbar_y = vid_conheight.integer - 24 - 16;
1201
1202                                 // calculate intensity to draw weapons bar at
1203                                 fade = 3.2 - 2 * (cl.time - cl.weapontime);
1204                                 fade = bound(0.7, fade, 1);
1205                                 for (i = 0; i < 8;i++)
1206                                         if (cl.stats[STAT_ITEMS] & (1 << i))
1207                                                 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1208                                 if((cl.stats[STAT_ITEMS] & (1<<12)))
1209                                         Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1210
1211                                 // flag icons
1212                                 redflag = ((cl.stats[STAT_ITEMS]>>15) & 3);
1213                                 blueflag = ((cl.stats[STAT_ITEMS]>>17) & 3);
1214                                 if (redflag == 3 && blueflag == 3)
1215                                 {
1216                                         // The Impossible Combination[tm]
1217                                         // Can only happen in Key Hunt mode...
1218                                         Sbar_DrawPic (10 - sbar_x, -179, sb_items[14]);
1219                                 }
1220                                 else
1221                                 {
1222                                         if (redflag)
1223                                                 Sbar_DrawPic (10 - sbar_x, -109, sb_items[redflag+10]);
1224                                         if (blueflag)
1225                                                 Sbar_DrawPic (10 - sbar_x, -169, sb_items[blueflag+14]);
1226                                 }
1227
1228                                 // armor
1229                                 if (cl.stats[STAT_ARMOR] > 0)
1230                                 {
1231                                         Sbar_DrawStretchPic (0, 0, sb_armor[0], sbar_alpha_fg.value, 24, 24);
1232                                         if(cl.stats[STAT_ARMOR] > 100)
1233                                                 Sbar_DrawXNum(24,0,cl.stats[STAT_ARMOR],3,24,1,1,0,1,0);
1234                                         else if(cl.stats[STAT_ARMOR] > 25)
1235                                                 Sbar_DrawXNum(24,0,cl.stats[STAT_ARMOR],3,24,0.6,0.7,0.8,1,0);
1236                                         else
1237                                                 Sbar_DrawXNum(24,0,cl.stats[STAT_ARMOR],3,24,0.7,0,0,1,0);
1238                                 }
1239
1240                                 // health
1241                                 if (cl.stats[STAT_HEALTH] != 0)
1242                                 {
1243                                         Sbar_DrawStretchPic (112, 0, sb_health, sbar_alpha_fg.value, 24, 24);
1244                                         if(cl.stats[STAT_HEALTH] > 100)
1245                                                 Sbar_DrawXNum(136,0,cl.stats[STAT_HEALTH],3,24,1,1,0,1,0);
1246                                         else if(cl.stats[STAT_HEALTH] > 25)
1247                                                 Sbar_DrawXNum(136,0,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1248                                         else
1249                                                 Sbar_DrawXNum(136,0,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1250                                 }
1251
1252                                 // ammo
1253                                 if ((cl.stats[STAT_ITEMS] & (NEX_IT_SHELLS | NEX_IT_BULLETS | NEX_IT_ROCKETS | NEX_IT_CELLS)) || cl.stats[STAT_AMMO] != 0)
1254                                 {
1255                                         if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1256                                                 Sbar_DrawStretchPic (224, 0, sb_ammo[0], sbar_alpha_fg.value, 24, 24);
1257                                         else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1258                                                 Sbar_DrawStretchPic (224, 0, sb_ammo[1], sbar_alpha_fg.value, 24, 24);
1259                                         else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1260                                                 Sbar_DrawStretchPic (224, 0, sb_ammo[2], sbar_alpha_fg.value, 24, 24);
1261                                         else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1262                                                 Sbar_DrawStretchPic (224, 0, sb_ammo[3], sbar_alpha_fg.value, 24, 24);
1263                                         if(cl.stats[STAT_AMMO] > 10)
1264                                                 Sbar_DrawXNum(248, 0, cl.stats[STAT_AMMO], 3, 24, 0.6,0.7,0.8,1,0);
1265                                         else
1266                                                 Sbar_DrawXNum(248, 0, cl.stats[STAT_AMMO], 3, 24, 0.7,0,0,1,0);
1267                                 }
1268
1269                                 if (sbar_x + 320 + 160 <= vid_conwidth.integer)
1270                                         Sbar_MiniDeathmatchOverlay (sbar_x + 320, sbar_y);
1271                                 if (sbar_x > 0)
1272                                         Sbar_Score();
1273                         }
1274                         else if (sb_lines)
1275                         {
1276                                 int i;
1277                                 float fade;
1278                                 int redflag, blueflag;
1279
1280                                 sbar_x = (vid_conwidth.integer - 640)/2;
1281                                 sbar_y = vid_conheight.integer - 47;
1282
1283                                 // calculate intensity to draw weapons bar at
1284                                 fade = 3 - 2 * (cl.time - cl.weapontime);
1285                                 if (fade > 0)
1286                                 {
1287                                         fade = min(fade, 1);
1288                                         for (i = 0; i < 8;i++)
1289                                                 if (cl.stats[STAT_ITEMS] & (1 << i))
1290                                                         Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1291
1292                                         if((cl.stats[STAT_ITEMS] & (1<<12)))
1293                                                 Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1294                                 }
1295
1296                                 //if (!cl.islocalgame)
1297                                 //      Sbar_DrawFrags ();
1298
1299                                 if (sb_lines > 24)
1300                                         Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1301                                 else
1302                                         Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1303
1304                                 // flag icons
1305                                 redflag = ((cl.stats[STAT_ITEMS]>>15) & 3);
1306                                 blueflag = ((cl.stats[STAT_ITEMS]>>17) & 3);
1307                                 if (redflag == 3 && blueflag == 3)
1308                                 {
1309                                         // The Impossible Combination[tm]
1310                                         // Can only happen in Key Hunt mode...
1311                                         Sbar_DrawPic (10 - sbar_x, -179, sb_items[14]);
1312                                 }
1313                                 else
1314                                 {
1315                                         if (redflag)
1316                                                 Sbar_DrawPic (10 - sbar_x, -109, sb_items[redflag+10]);
1317                                         if (blueflag)
1318                                                 Sbar_DrawPic (10 - sbar_x, -169, sb_items[blueflag+14]);
1319                                 }
1320
1321                                 // armor
1322                                 Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1323
1324                                 // health
1325                                 if(cl.stats[STAT_HEALTH] > 100)
1326                                         Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1327                                 else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1328                                         Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1329                                 else
1330                                         Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1331
1332                                 // AK dont draw ammo for the laser
1333                                 if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1334                                 {
1335                                         if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1336                                                 Sbar_DrawPic (519, 0, sb_ammo[0]);
1337                                         else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1338                                                 Sbar_DrawPic (519, 0, sb_ammo[1]);
1339                                         else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1340                                                 Sbar_DrawPic (519, 0, sb_ammo[2]);
1341                                         else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1342                                                 Sbar_DrawPic (519, 0, sb_ammo[3]);
1343
1344                                         if(cl.stats[STAT_AMMO] <= 10)
1345                                                 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1346                                         else
1347                                                 Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1348
1349                                 }
1350
1351                                 if (sb_lines > 24)
1352                                         DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1353
1354                                 if (sbar_x + 600 + 160 <= vid_conwidth.integer)
1355                                         Sbar_MiniDeathmatchOverlay (sbar_x + 600, sbar_y);
1356
1357                                 if (sbar_x > 0)
1358                                         Sbar_Score();
1359                         }
1360                 }
1361                 else if (gamemode == GAME_ZYMOTIC)
1362                 {
1363 #if 1
1364                         float scale = 64.0f / 256.0f;
1365                         float kickoffset[3];
1366                         VectorClear(kickoffset);
1367                         if (v_dmg_time > 0)
1368                         {
1369                                 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1370                                 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1371                         }
1372                         sbar_x = (int)((vid_conwidth.integer - 256 * scale)/2 + kickoffset[0]);
1373                         sbar_y = (int)((vid_conheight.integer - 256 * scale)/2 + kickoffset[1]);
1374                         // left1 16, 48 : 126 -66
1375                         // left2 16, 128 : 196 -66
1376                         // right 176, 48 : 196 -136
1377                         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);
1378                         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);
1379                         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);
1380                         DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1381 #else
1382                         float scale = 128.0f / 256.0f;
1383                         float healthstart, healthheight, healthstarttc, healthendtc;
1384                         float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1385                         float ammostart, ammoheight, ammostarttc, ammoendtc;
1386                         float clipstart, clipheight, clipstarttc, clipendtc;
1387                         float kickoffset[3], offset;
1388                         VectorClear(kickoffset);
1389                         if (v_dmg_time > 0)
1390                         {
1391                                 kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1392                                 kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1393                         }
1394                         sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1395                         sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1396                         offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1397                         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);
1398                         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);
1399                         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);
1400                         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);
1401                         healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1402                         shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1403                         healthstart = 204 - healthheight;
1404                         shieldstart = healthstart - shieldheight;
1405                         healthstarttc = healthstart * (1.0f / 256.0f);
1406                         healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1407                         shieldstarttc = shieldstart * (1.0f / 256.0f);
1408                         shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1409                         ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1410                         ammostart = 114 - ammoheight;
1411                         ammostarttc = ammostart * (1.0f / 256.0f);
1412                         ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1413                         clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1414                         clipstart = 190 - clipheight;
1415                         clipstarttc = clipstart * (1.0f / 256.0f);
1416                         clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1417                         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);
1418                         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);
1419                         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);
1420                         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);
1421                         DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1422                         DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1423 #endif
1424                 }
1425                 else // Quake and others
1426                 {
1427                         sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1428                         // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1429                         //if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1430                         if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1431                                 sbar_x = 0;
1432                         else
1433                                 sbar_x = (vid_conwidth.integer - 320)/2;
1434
1435                         if (sb_lines > 24)
1436                         {
1437                                 if (gamemode != GAME_GOODVSBAD2)
1438                                         Sbar_DrawInventory ();
1439                                 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1440                                         Sbar_DrawFrags ();
1441                         }
1442
1443                         if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1444                         {
1445                                 if (gamemode != GAME_GOODVSBAD2)
1446                                         Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1447                                 Sbar_DrawScoreboard ();
1448                         }
1449                         else if (sb_lines)
1450                         {
1451                                 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1452
1453                                 // keys (hipnotic only)
1454                                 //MED 01/04/97 moved keys here so they would not be overwritten
1455                                 if (gamemode == GAME_HIPNOTIC)
1456                                 {
1457                                         if (cl.stats[STAT_ITEMS] & IT_KEY1)
1458                                                 Sbar_DrawPic (209, 3, sb_items[0]);
1459                                         if (cl.stats[STAT_ITEMS] & IT_KEY2)
1460                                                 Sbar_DrawPic (209, 12, sb_items[1]);
1461                                 }
1462                                 // armor
1463                                 if (gamemode != GAME_GOODVSBAD2)
1464                                 {
1465                                         if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1466                                         {
1467                                                 Sbar_DrawNum (24, 0, 666, 3, 1);
1468                                                 Sbar_DrawPic (0, 0, sb_disc);
1469                                         }
1470                                         else
1471                                         {
1472                                                 if (gamemode == GAME_ROGUE)
1473                                                 {
1474                                                         Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1475                                                         if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1476                                                                 Sbar_DrawPic (0, 0, sb_armor[2]);
1477                                                         else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1478                                                                 Sbar_DrawPic (0, 0, sb_armor[1]);
1479                                                         else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1480                                                                 Sbar_DrawPic (0, 0, sb_armor[0]);
1481                                                 }
1482                                                 else
1483                                                 {
1484                                                         Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1485                                                         if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1486                                                                 Sbar_DrawPic (0, 0, sb_armor[2]);
1487                                                         else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1488                                                                 Sbar_DrawPic (0, 0, sb_armor[1]);
1489                                                         else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1490                                                                 Sbar_DrawPic (0, 0, sb_armor[0]);
1491                                                 }
1492                                         }
1493                                 }
1494
1495                                 // face
1496                                 Sbar_DrawFace ();
1497
1498                                 // health
1499                                 Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1500
1501                                 // ammo icon
1502                                 if (gamemode == GAME_ROGUE)
1503                                 {
1504                                         if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1505                                                 Sbar_DrawPic (224, 0, sb_ammo[0]);
1506                                         else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1507                                                 Sbar_DrawPic (224, 0, sb_ammo[1]);
1508                                         else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1509                                                 Sbar_DrawPic (224, 0, sb_ammo[2]);
1510                                         else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1511                                                 Sbar_DrawPic (224, 0, sb_ammo[3]);
1512                                         else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1513                                                 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1514                                         else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1515                                                 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1516                                         else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1517                                                 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1518                                 }
1519                                 else
1520                                 {
1521                                         if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1522                                                 Sbar_DrawPic (224, 0, sb_ammo[0]);
1523                                         else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1524                                                 Sbar_DrawPic (224, 0, sb_ammo[1]);
1525                                         else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1526                                                 Sbar_DrawPic (224, 0, sb_ammo[2]);
1527                                         else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1528                                                 Sbar_DrawPic (224, 0, sb_ammo[3]);
1529                                 }
1530
1531                                 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1532
1533                         }
1534
1535                         // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1536                         //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1537                         if (!cl.islocalgame && vid_conwidth.integer > 320)
1538                         {
1539                                 if (gamemode == GAME_TRANSFUSION)
1540                                         Sbar_MiniDeathmatchOverlay (0, 0);
1541                                 else
1542                                         Sbar_MiniDeathmatchOverlay (324, vid_conheight.integer - sb_lines);
1543                                 if (sbar_x > 0)
1544                                         Sbar_Score();
1545                         }
1546                 }
1547         }
1548
1549         Sbar_ShowFPS();
1550
1551         if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && crosshair.integer <= NUMCROSSHAIRS && !cl.intermission && !r_letterbox.value && (pic = r_crosshairs[crosshair.integer]))
1552                 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);
1553
1554         if (cl_prydoncursor.integer)
1555                 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);
1556 }
1557
1558 //=============================================================================
1559
1560 /*
1561 ==================
1562 Sbar_DeathmatchOverlay
1563
1564 ==================
1565 */
1566 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1567 {
1568         int minutes;
1569         qboolean myself = false;
1570         unsigned char *c;
1571         minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : cl.time - s->qw_entertime) / 60.0);
1572
1573         if((s - cl.scores) == cl.playerentity - 1)
1574                 myself = true;
1575         if((s - teams) >= 0 && (s - teams) < MAX_SCOREBOARD)
1576                 if((s->colors & 15) == (cl.scores[cl.playerentity - 1].colors & 15))
1577                         myself = true;
1578
1579         if (cls.protocol == PROTOCOL_QUAKEWORLD)
1580         {
1581                 if (s->qw_spectator)
1582                 {
1583                         if (s->qw_ping || s->qw_packetloss)
1584                                 DrawQ_String(x, y, va("%4i %3i %4i spectator  %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), minutes, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1585                         else
1586                                 DrawQ_String(x, y, va("         %4i spectator  %c%s", minutes, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1587                 }
1588                 else
1589                 {
1590                         // draw colors behind score
1591                         c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1592                         DrawQ_Fill(x + 14*8, y+1, 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);
1593                         c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1594                         DrawQ_Fill(x + 14*8, y+4, 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);
1595                         // print the text
1596                         //DrawQ_String(x, y, va("%c%4i %s", myself ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, true);
1597                         if (s->qw_ping || s->qw_packetloss)
1598                                 DrawQ_String(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 : "", myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1599                         else
1600                                 DrawQ_String(x, y, va("         %4i %5i %-4s %c%s", minutes,(int) s->frags, cl.qw_teamplay ? s->qw_team : "", myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1601                 }
1602         }
1603         else
1604         {
1605                 if (s->qw_spectator)
1606                 {
1607                         if (s->qw_ping || s->qw_packetloss)
1608                                 DrawQ_String(x, y, va("%4i %3i spect %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1609                         else
1610                                 DrawQ_String(x, y, va("         spect %c%s", myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1611                 }
1612                 else
1613                 {
1614                         // draw colors behind score
1615                         c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1616                         DrawQ_Fill(x + 9*8, y+1, 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);
1617                         c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1618                         DrawQ_Fill(x + 9*8, y+4, 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);
1619                         // print the text
1620                         //DrawQ_String(x, y, va("%c%4i %s", myself ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, true);
1621                         if (s->qw_ping || s->qw_packetloss)
1622                                 DrawQ_String(x, y, va("%4i %3i %5i %c%s", bound(0, s->qw_ping, 9999), bound(0, s->qw_packetloss, 99), (int) s->frags, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1623                         else
1624                                 DrawQ_String(x, y, va("         %5i %c%s", (int) s->frags, myself ? 13 : ' ', s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1625                 }
1626         }
1627         return 8;
1628 }
1629
1630 void Sbar_DeathmatchOverlay (void)
1631 {
1632         int i, x, y;
1633
1634         // request new ping times every two second
1635         if (cl.last_ping_request < realtime - 2 && cls.netcon)
1636         {
1637                 cl.last_ping_request = realtime;
1638                 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1639                 {
1640                         MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
1641                         MSG_WriteString(&cls.netcon->message, "pings");
1642                 }
1643                 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*/)
1644                 {
1645                         // 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
1646                         static int ping_anyway_counter = 0;
1647                         if(cl.parsingtextexpectingpingforscores == 1)
1648                         {
1649                                 Con_DPrintf("want to send ping, but still waiting for other reply\n");
1650                                 if(++ping_anyway_counter >= 5)
1651                                         cl.parsingtextexpectingpingforscores = 0;
1652                         }
1653                         if(cl.parsingtextexpectingpingforscores != 1)
1654                         {
1655                                 ping_anyway_counter = 0;
1656                                 cl.parsingtextexpectingpingforscores = 1; // hide the output of the next ping report
1657                                 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1658                                 MSG_WriteString(&cls.netcon->message, "ping");
1659                         }
1660                 }
1661                 else
1662                 {
1663                         // newer server definitely has pings command, so use it for more efficiency, avoids ping reports spamming the console if they are misparsed, and saves a little bandwidth
1664                         MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1665                         MSG_WriteString(&cls.netcon->message, "pings");
1666                 }
1667         }
1668
1669         DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1670
1671         // scores
1672         Sbar_SortFrags ();
1673         // draw the text
1674         y = 40;
1675         if (cls.protocol == PROTOCOL_QUAKEWORLD)
1676         {
1677                 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)
1678                 DrawQ_String(x, y, va("ping pl%% time frags team  name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1679         }
1680         else
1681         {
1682                 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)
1683                 DrawQ_String(x, y, va("ping pl%% frags  name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1684         }
1685         y += 8;
1686
1687         if (Sbar_IsTeammatch ())
1688         {
1689                 // show team scores first
1690                 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1691                         y += (int)Sbar_PrintScoreboardItem((teams + teamsort[i]), x, y);
1692                 y += 5;
1693         }
1694
1695         for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1696                 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1697 }
1698
1699 /*
1700 ==================
1701 Sbar_MiniDeathmatchOverlay
1702
1703 ==================
1704 */
1705 void Sbar_MiniDeathmatchOverlay (int x, int y)
1706 {
1707         int i, j, numlines, range_begin, range_end, myteam, teamsep;
1708
1709         // scores
1710         Sbar_SortFrags ();
1711
1712         // decide where to print
1713         if (gamemode == GAME_TRANSFUSION)
1714                 numlines = (vid_conwidth.integer - x + 127) / 128;
1715         else
1716                 numlines = (vid_conheight.integer - y + 7) / 8;
1717
1718         // give up if there isn't room
1719         if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1720                 return;
1721
1722         //find us
1723         for (i = 0; i < scoreboardlines; i++)
1724                 if (fragsort[i] == cl.playerentity - 1)
1725                         break;
1726
1727         range_begin = 0;
1728         range_end = scoreboardlines;
1729         teamsep = 0;
1730
1731         if (gamemode != GAME_TRANSFUSION)
1732                 if (Sbar_IsTeammatch ())
1733                 {
1734                         // reserve space for the team scores
1735                         numlines -= teamlines;
1736
1737                         // find first and last player of my team (only draw the team totals and my own team)
1738                         range_begin = range_end = i;
1739                         myteam = cl.scores[fragsort[i]].colors & 15;
1740                         while(range_begin > 0 && (cl.scores[fragsort[range_begin-1]].colors & 15) == myteam)
1741                                 --range_begin;
1742                         while(range_end < scoreboardlines && (cl.scores[fragsort[range_end]].colors & 15) == myteam)
1743                                 ++range_end;
1744
1745                         // looks better than two players
1746                         if(numlines == 2)
1747                         {
1748                                 teamsep = 8;
1749                                 numlines = 1;
1750                         }
1751                 }
1752
1753         // figure out start
1754         i -= numlines/2;
1755         i = min(i, range_end - numlines);
1756         i = max(i, range_begin);
1757
1758         if (gamemode == GAME_TRANSFUSION)
1759         {
1760                 for (;i < range_end && x < vid_conwidth.integer;i++)
1761                         x += 128 + (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1762         }
1763         else
1764         {
1765                 if(range_end - i < numlines) // won't draw to bottom?
1766                         y += 8 * (numlines - (range_end - i)); // bottom align
1767                 // show team scores first
1768                 for (j = 0;j < teamlines && y < vid_conheight.integer;j++)
1769                         y += (int)Sbar_PrintScoreboardItem((teams + teamsort[j]), x, y);
1770                 y += teamsep;
1771                 for (;i < range_end && y < vid_conheight.integer;i++)
1772                         y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1773         }
1774 }
1775
1776 void Sbar_Score (void)
1777 {
1778         int i, me, score, otherleader, place, distribution, minutes, seconds;
1779         double timeleft;
1780
1781         sbar_y = vid_conheight.value - (32+12);
1782         me = cl.playerentity - 1;
1783         if (me >= 0 && me < cl.maxclients)
1784         {
1785                 // find leading score other than ourselves, to calculate distribution
1786                 // find our place in the scoreboard
1787                 score = cl.scores[me].frags;
1788                 for (i = 0, otherleader = -1, place = 1;i < cl.maxclients;i++)
1789                 {
1790                         if (cl.scores[i].name[0] && i != me)
1791                         {
1792                                 if (otherleader == -1 || cl.scores[i].frags > cl.scores[otherleader].frags)
1793                                         otherleader = i;
1794                                 if (score < cl.scores[i].frags || (score == cl.scores[i].frags && i < me))
1795                                         place++;
1796                         }
1797                 }
1798                 distribution = otherleader >= 0 ? score - cl.scores[otherleader].frags : 0;
1799                 if (place == 1)
1800                         Sbar_DrawXNum(-3*12-24, -12, place, 3, 12, 0, 1, 1, 1, 0);
1801                 else if (place == 2)
1802                         Sbar_DrawXNum(-3*12-24, -12, place, 3, 12, 1, 1, 1, 1, 0);
1803                 else if (place == 3)
1804                         Sbar_DrawXNum(-3*12-24, -12, place, 3, 12, 1, 1, 0, 1, 0);
1805                 else
1806                         Sbar_DrawXNum(-3*12-24, -12, place, 3, 12, 1, 0, 0, 1, 0);
1807                 if (otherleader < 0)
1808                         Sbar_DrawXNum(-32*4-24,   0, score, 4, 32, 1, 1, 1, 1, 0);
1809                 else if (distribution >= 5)
1810                 {
1811                         Sbar_DrawXNum(-7*12-24, -12, distribution, 4, 12, 0, 1, 1, 1, 0);
1812                         Sbar_DrawXNum(-32*4-24,   0, score, 4, 32, 0, 1, 1, 1, 0);
1813                 }
1814                 else if (distribution >= 0)
1815                 {
1816                         Sbar_DrawXNum(-7*12-24, -12, distribution, 4, 12, 1, 1, 1, 1, 0);
1817                         Sbar_DrawXNum(-32*4-24,   0, score, 4, 32, 1, 1, 1, 1, 0);
1818                 }
1819                 else if (distribution >= -5)
1820                 {
1821                         Sbar_DrawXNum(-7*12-24, -12, distribution, 4, 12, 1, 1, 0, 1, 0);
1822                         Sbar_DrawXNum(-32*4-24,   0, score, 4, 32, 1, 1, 0, 1, 0);
1823                 }
1824                 else
1825                 {
1826                         Sbar_DrawXNum(-7*12-24, -12, distribution, 4, 12, 1, 0, 0, 1, 0);
1827                         Sbar_DrawXNum(-32*4-24,   0, score, 4, 32, 1, 0, 0, 1, 0);
1828                 }
1829         }
1830
1831         if (cl.statsf[STAT_TIMELIMIT])
1832         {
1833                 timeleft = max(0, cl.statsf[STAT_TIMELIMIT] * 60 - cl.time);
1834                 minutes = (int)floor(timeleft / 60);
1835                 seconds = (int)(floor(timeleft) - minutes * 60);
1836                 if (minutes >= 5)
1837                 {
1838                         Sbar_DrawXNum(-12*6-24, 32, minutes,  3, 12, 1, 1, 1, 1, 0);
1839                         Sbar_DrawXNum(-12*2-24, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
1840                 }
1841                 else if (minutes >= 1)
1842                 {
1843                         Sbar_DrawXNum(-12*6-24, 32, minutes,  3, 12, 1, 1, 0, 1, 0);
1844                         Sbar_DrawXNum(-12*2-24, 32, seconds, -2, 12, 1, 1, 0, 1, 0);
1845                 }
1846                 else if ((int)(timeleft * 4) & 1)
1847                         Sbar_DrawXNum(-12*2-24, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
1848                 else
1849                         Sbar_DrawXNum(-12*2-24, 32, seconds, -2, 12, 1, 0, 0, 1, 0);
1850         }
1851         else
1852         {
1853                 minutes = (int)floor(cl.time / 60);
1854                 seconds = (int)(floor(cl.time) - minutes * 60);
1855                 Sbar_DrawXNum(-12*6-24, 32, minutes,  3, 12, 0, 1, 1, 1, 0);
1856                 Sbar_DrawXNum(-12*2-24, 32, seconds, -2, 12, 0, 1, 1, 1, 0);
1857         }
1858 }
1859
1860 /*
1861 ==================
1862 Sbar_IntermissionOverlay
1863
1864 ==================
1865 */
1866 void Sbar_IntermissionOverlay (void)
1867 {
1868         int             dig;
1869         int             num;
1870
1871         // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1872         //if (cl.gametype == GAME_DEATHMATCH)
1873         if (!cl.islocalgame)
1874         {
1875                 Sbar_DeathmatchOverlay ();
1876                 return;
1877         }
1878
1879         sbar_x = (vid_conwidth.integer - 320) >> 1;
1880         sbar_y = (vid_conheight.integer - 200) >> 1;
1881
1882         DrawQ_Pic (sbar_x + 64, sbar_y + 24, sb_complete, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1883         DrawQ_Pic (sbar_x + 0, sbar_y + 56, sb_inter, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1884
1885 // time
1886         dig = (int)cl.completed_time / 60;
1887         Sbar_DrawNum (160, 64, dig, 3, 0);
1888         num = (int)cl.completed_time - dig*60;
1889         if (gamemode != GAME_NEXUIZ)
1890                 Sbar_DrawPic (234,64,sb_colon);
1891         Sbar_DrawPic (246,64,sb_nums[0][num/10]);
1892         Sbar_DrawPic (266,64,sb_nums[0][num%10]);
1893
1894         Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
1895         if (gamemode != GAME_NEXUIZ)
1896                 Sbar_DrawPic (232, 104, sb_slash);
1897         Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1898
1899         Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1900         if (gamemode != GAME_NEXUIZ)
1901                 Sbar_DrawPic (232, 144, sb_slash);
1902         Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1903
1904 }
1905
1906
1907 /*
1908 ==================
1909 Sbar_FinaleOverlay
1910
1911 ==================
1912 */
1913 void Sbar_FinaleOverlay (void)
1914 {
1915         DrawQ_Pic((vid_conwidth.integer - sb_finale->width)/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1916 }
1917