]> icculus.org git repositories - divverent/darkplaces.git/blob - sbar.c
slight simplification/optimization of an if statement (no change in
[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_x = (vid_conwidth.integer - 320)/2;
1428                         sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1429                         // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1430                         //if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1431
1432                         if (sb_lines > 24)
1433                         {
1434                                 if (gamemode != GAME_GOODVSBAD2)
1435                                         Sbar_DrawInventory ();
1436                                 if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1437                                         Sbar_DrawFrags ();
1438                         }
1439
1440                         if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1441                         {
1442                                 if (gamemode != GAME_GOODVSBAD2)
1443                                         Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1444                                 Sbar_DrawScoreboard ();
1445                         }
1446                         else if (sb_lines)
1447                         {
1448                                 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1449
1450                                 // keys (hipnotic only)
1451                                 //MED 01/04/97 moved keys here so they would not be overwritten
1452                                 if (gamemode == GAME_HIPNOTIC)
1453                                 {
1454                                         if (cl.stats[STAT_ITEMS] & IT_KEY1)
1455                                                 Sbar_DrawPic (209, 3, sb_items[0]);
1456                                         if (cl.stats[STAT_ITEMS] & IT_KEY2)
1457                                                 Sbar_DrawPic (209, 12, sb_items[1]);
1458                                 }
1459                                 // armor
1460                                 if (gamemode != GAME_GOODVSBAD2)
1461                                 {
1462                                         if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1463                                         {
1464                                                 Sbar_DrawNum (24, 0, 666, 3, 1);
1465                                                 Sbar_DrawPic (0, 0, sb_disc);
1466                                         }
1467                                         else
1468                                         {
1469                                                 if (gamemode == GAME_ROGUE)
1470                                                 {
1471                                                         Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1472                                                         if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1473                                                                 Sbar_DrawPic (0, 0, sb_armor[2]);
1474                                                         else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1475                                                                 Sbar_DrawPic (0, 0, sb_armor[1]);
1476                                                         else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1477                                                                 Sbar_DrawPic (0, 0, sb_armor[0]);
1478                                                 }
1479                                                 else
1480                                                 {
1481                                                         Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1482                                                         if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1483                                                                 Sbar_DrawPic (0, 0, sb_armor[2]);
1484                                                         else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1485                                                                 Sbar_DrawPic (0, 0, sb_armor[1]);
1486                                                         else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1487                                                                 Sbar_DrawPic (0, 0, sb_armor[0]);
1488                                                 }
1489                                         }
1490                                 }
1491
1492                                 // face
1493                                 Sbar_DrawFace ();
1494
1495                                 // health
1496                                 Sbar_DrawNum (136, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1497
1498                                 // ammo icon
1499                                 if (gamemode == GAME_ROGUE)
1500                                 {
1501                                         if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1502                                                 Sbar_DrawPic (224, 0, sb_ammo[0]);
1503                                         else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1504                                                 Sbar_DrawPic (224, 0, sb_ammo[1]);
1505                                         else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1506                                                 Sbar_DrawPic (224, 0, sb_ammo[2]);
1507                                         else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1508                                                 Sbar_DrawPic (224, 0, sb_ammo[3]);
1509                                         else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1510                                                 Sbar_DrawPic (224, 0, rsb_ammo[0]);
1511                                         else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1512                                                 Sbar_DrawPic (224, 0, rsb_ammo[1]);
1513                                         else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1514                                                 Sbar_DrawPic (224, 0, rsb_ammo[2]);
1515                                 }
1516                                 else
1517                                 {
1518                                         if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1519                                                 Sbar_DrawPic (224, 0, sb_ammo[0]);
1520                                         else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1521                                                 Sbar_DrawPic (224, 0, sb_ammo[1]);
1522                                         else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1523                                                 Sbar_DrawPic (224, 0, sb_ammo[2]);
1524                                         else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1525                                                 Sbar_DrawPic (224, 0, sb_ammo[3]);
1526                                 }
1527
1528                                 Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1529
1530                         }
1531
1532                         // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1533                         if ((!cl.islocalgame || cl.gametype != GAME_COOP))
1534                         {
1535                                 if (gamemode == GAME_TRANSFUSION)
1536                                         Sbar_MiniDeathmatchOverlay (0, 0);
1537                                 else
1538                                         Sbar_MiniDeathmatchOverlay (sbar_x + 324, vid_conheight.integer - 8*8);
1539                                 Sbar_Score();
1540                         }
1541                 }
1542         }
1543
1544         Sbar_ShowFPS();
1545
1546         if (cl.csqc_vidvars.drawcrosshair && crosshair.integer >= 1 && crosshair.integer <= NUMCROSSHAIRS && !cl.intermission && !r_letterbox.value && (pic = r_crosshairs[crosshair.integer]))
1547                 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);
1548
1549         if (cl_prydoncursor.integer)
1550                 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);
1551 }
1552
1553 //=============================================================================
1554
1555 /*
1556 ==================
1557 Sbar_DeathmatchOverlay
1558
1559 ==================
1560 */
1561 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1562 {
1563         int minutes;
1564         qboolean myself = false;
1565         unsigned char *c;
1566         minutes = (int)((cl.intermission ? cl.completed_time - s->qw_entertime : cl.time - s->qw_entertime) / 60.0);
1567
1568         if((s - cl.scores) == cl.playerentity - 1)
1569                 myself = true;
1570         if((s - teams) >= 0 && (s - teams) < MAX_SCOREBOARD)
1571                 if((s->colors & 15) == (cl.scores[cl.playerentity - 1].colors & 15))
1572                         myself = true;
1573
1574         if (cls.protocol == PROTOCOL_QUAKEWORLD)
1575         {
1576                 if (s->qw_spectator)
1577                 {
1578                         if (s->qw_ping || s->qw_packetloss)
1579                                 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 );
1580                         else
1581                                 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 );
1582                 }
1583                 else
1584                 {
1585                         // draw colors behind score
1586                         c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1587                         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);
1588                         c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1589                         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);
1590                         // print the text
1591                         //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);
1592                         if (s->qw_ping || s->qw_packetloss)
1593                                 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 );
1594                         else
1595                                 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 );
1596                 }
1597         }
1598         else
1599         {
1600                 if (s->qw_spectator)
1601                 {
1602                         if (s->qw_ping || s->qw_packetloss)
1603                                 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 );
1604                         else
1605                                 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 );
1606                 }
1607                 else
1608                 {
1609                         // draw colors behind score
1610                         c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1611                         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);
1612                         c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1613                         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);
1614                         // print the text
1615                         //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);
1616                         if (s->qw_ping || s->qw_packetloss)
1617                                 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 );
1618                         else
1619                                 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 );
1620                 }
1621         }
1622         return 8;
1623 }
1624
1625 void Sbar_DeathmatchOverlay (void)
1626 {
1627         int i, x, y;
1628
1629         // request new ping times every two second
1630         if (cl.last_ping_request < realtime - 2 && cls.netcon)
1631         {
1632                 cl.last_ping_request = realtime;
1633                 if (cls.protocol == PROTOCOL_QUAKEWORLD)
1634                 {
1635                         MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
1636                         MSG_WriteString(&cls.netcon->message, "pings");
1637                 }
1638                 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*/)
1639                 {
1640                         // 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
1641                         static int ping_anyway_counter = 0;
1642                         if(cl.parsingtextexpectingpingforscores == 1)
1643                         {
1644                                 Con_DPrintf("want to send ping, but still waiting for other reply\n");
1645                                 if(++ping_anyway_counter >= 5)
1646                                         cl.parsingtextexpectingpingforscores = 0;
1647                         }
1648                         if(cl.parsingtextexpectingpingforscores != 1)
1649                         {
1650                                 ping_anyway_counter = 0;
1651                                 cl.parsingtextexpectingpingforscores = 1; // hide the output of the next ping report
1652                                 MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1653                                 MSG_WriteString(&cls.netcon->message, "ping");
1654                         }
1655                 }
1656                 else
1657                 {
1658                         // 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
1659                         MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
1660                         MSG_WriteString(&cls.netcon->message, "pings");
1661                 }
1662         }
1663
1664         DrawQ_Pic ((vid_conwidth.integer - sb_ranking->width)/2, 8, sb_ranking, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1665
1666         // scores
1667         Sbar_SortFrags ();
1668         // draw the text
1669         y = 40;
1670         if (cls.protocol == PROTOCOL_QUAKEWORLD)
1671         {
1672                 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)
1673                 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 );
1674         }
1675         else
1676         {
1677                 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)
1678                 DrawQ_String(x, y, va("ping pl%% frags  name"), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL, false );
1679         }
1680         y += 8;
1681
1682         if (Sbar_IsTeammatch ())
1683         {
1684                 // show team scores first
1685                 for (i = 0;i < teamlines && y < vid_conheight.integer;i++)
1686                         y += (int)Sbar_PrintScoreboardItem((teams + teamsort[i]), x, y);
1687                 y += 5;
1688         }
1689
1690         for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1691                 y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1692 }
1693
1694 /*
1695 ==================
1696 Sbar_MiniDeathmatchOverlay
1697
1698 ==================
1699 */
1700 void Sbar_MiniDeathmatchOverlay (int x, int y)
1701 {
1702         int i, j, numlines, range_begin, range_end, myteam, teamsep;
1703
1704         // scores
1705         Sbar_SortFrags ();
1706
1707         // decide where to print
1708         if (gamemode == GAME_TRANSFUSION)
1709                 numlines = (vid_conwidth.integer - x + 127) / 128;
1710         else
1711                 numlines = (vid_conheight.integer - y + 7) / 8;
1712
1713         // give up if there isn't room
1714         if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1715                 return;
1716
1717         //find us
1718         for (i = 0; i < scoreboardlines; i++)
1719                 if (fragsort[i] == cl.playerentity - 1)
1720                         break;
1721
1722         range_begin = 0;
1723         range_end = scoreboardlines;
1724         teamsep = 0;
1725
1726         if (gamemode != GAME_TRANSFUSION)
1727                 if (Sbar_IsTeammatch ())
1728                 {
1729                         // reserve space for the team scores
1730                         numlines -= teamlines;
1731
1732                         // find first and last player of my team (only draw the team totals and my own team)
1733                         range_begin = range_end = i;
1734                         myteam = cl.scores[fragsort[i]].colors & 15;
1735                         while(range_begin > 0 && (cl.scores[fragsort[range_begin-1]].colors & 15) == myteam)
1736                                 --range_begin;
1737                         while(range_end < scoreboardlines && (cl.scores[fragsort[range_end]].colors & 15) == myteam)
1738                                 ++range_end;
1739
1740                         // looks better than two players
1741                         if(numlines == 2)
1742                         {
1743                                 teamsep = 8;
1744                                 numlines = 1;
1745                         }
1746                 }
1747
1748         // figure out start
1749         i -= numlines/2;
1750         i = min(i, range_end - numlines);
1751         i = max(i, range_begin);
1752
1753         if (gamemode == GAME_TRANSFUSION)
1754         {
1755                 for (;i < range_end && x < vid_conwidth.integer;i++)
1756                         x += 128 + (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1757         }
1758         else
1759         {
1760                 if(range_end - i < numlines) // won't draw to bottom?
1761                         y += 8 * (numlines - (range_end - i)); // bottom align
1762                 // show team scores first
1763                 for (j = 0;j < teamlines && y < vid_conheight.integer;j++)
1764                         y += (int)Sbar_PrintScoreboardItem((teams + teamsort[j]), x, y);
1765                 y += teamsep;
1766                 for (;i < range_end && y < vid_conheight.integer;i++)
1767                         y += (int)Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1768         }
1769 }
1770
1771 void Sbar_Score (void)
1772 {
1773         int i, me, score, otherleader, place, distribution, minutes, seconds;
1774         double timeleft;
1775
1776         sbar_y = vid_conheight.value - (32+12);
1777         me = cl.playerentity - 1;
1778         if (me >= 0 && me < cl.maxclients)
1779         {
1780                 // find leading score other than ourselves, to calculate distribution
1781                 // find our place in the scoreboard
1782                 score = cl.scores[me].frags;
1783                 for (i = 0, otherleader = -1, place = 1;i < cl.maxclients;i++)
1784                 {
1785                         if (cl.scores[i].name[0] && i != me)
1786                         {
1787                                 if (otherleader == -1 || cl.scores[i].frags > cl.scores[otherleader].frags)
1788                                         otherleader = i;
1789                                 if (score < cl.scores[i].frags || (score == cl.scores[i].frags && i < me))
1790                                         place++;
1791                         }
1792                 }
1793                 distribution = otherleader >= 0 ? score - cl.scores[otherleader].frags : 0;
1794                 if (place == 1)
1795                         Sbar_DrawXNum(-3*12-24, -12, place, 3, 12, 1, 1, 1, 1, 0);
1796                 else if (place == 2)
1797                         Sbar_DrawXNum(-3*12-24, -12, place, 3, 12, 1, 1, 0, 1, 0);
1798                 else
1799                         Sbar_DrawXNum(-3*12-24, -12, place, 3, 12, 1, 0, 0, 1, 0);
1800                 if (otherleader < 0)
1801                         Sbar_DrawXNum(-32*4-24,   0, score, 4, 32, 1, 1, 1, 1, 0);
1802                 if (distribution >= 0)
1803                 {
1804                         Sbar_DrawXNum(-7*12-24, -12, distribution, 4, 12, 1, 1, 1, 1, 0);
1805                         Sbar_DrawXNum(-32*4-24,   0, score, 4, 32, 1, 1, 1, 1, 0);
1806                 }
1807                 else if (distribution >= -5)
1808                 {
1809                         Sbar_DrawXNum(-7*12-24, -12, distribution, 4, 12, 1, 1, 0, 1, 0);
1810                         Sbar_DrawXNum(-32*4-24,   0, score, 4, 32, 1, 1, 0, 1, 0);
1811                 }
1812                 else
1813                 {
1814                         Sbar_DrawXNum(-7*12-24, -12, distribution, 4, 12, 1, 0, 0, 1, 0);
1815                         Sbar_DrawXNum(-32*4-24,   0, score, 4, 32, 1, 0, 0, 1, 0);
1816                 }
1817         }
1818
1819         if (cl.statsf[STAT_TIMELIMIT])
1820         {
1821                 timeleft = max(0, cl.statsf[STAT_TIMELIMIT] * 60 - cl.time);
1822                 minutes = (int)floor(timeleft / 60);
1823                 seconds = (int)(floor(timeleft) - minutes * 60);
1824                 if (minutes >= 5)
1825                 {
1826                         Sbar_DrawXNum(-12*6-24, 32, minutes,  3, 12, 1, 1, 1, 1, 0);
1827                         Sbar_DrawXNum(-12*2-24, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
1828                 }
1829                 else if (minutes >= 1)
1830                 {
1831                         Sbar_DrawXNum(-12*6-24, 32, minutes,  3, 12, 1, 1, 0, 1, 0);
1832                         Sbar_DrawXNum(-12*2-24, 32, seconds, -2, 12, 1, 1, 0, 1, 0);
1833                 }
1834                 else if ((int)(timeleft * 4) & 1)
1835                         Sbar_DrawXNum(-12*2-24, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
1836                 else
1837                         Sbar_DrawXNum(-12*2-24, 32, seconds, -2, 12, 1, 0, 0, 1, 0);
1838         }
1839         else
1840         {
1841                 minutes = (int)floor(cl.time / 60);
1842                 seconds = (int)(floor(cl.time) - minutes * 60);
1843                 Sbar_DrawXNum(-12*6-24, 32, minutes,  3, 12, 1, 1, 1, 1, 0);
1844                 Sbar_DrawXNum(-12*2-24, 32, seconds, -2, 12, 1, 1, 1, 1, 0);
1845         }
1846 }
1847
1848 /*
1849 ==================
1850 Sbar_IntermissionOverlay
1851
1852 ==================
1853 */
1854 void Sbar_IntermissionOverlay (void)
1855 {
1856         int             dig;
1857         int             num;
1858
1859         // LordHavoc: changed to draw the deathmatch overlays in any multiplayer mode
1860         //if (cl.gametype == GAME_DEATHMATCH)
1861         if (!cl.islocalgame)
1862         {
1863                 Sbar_DeathmatchOverlay ();
1864                 return;
1865         }
1866
1867         sbar_x = (vid_conwidth.integer - 320) >> 1;
1868         sbar_y = (vid_conheight.integer - 200) >> 1;
1869
1870         DrawQ_Pic (sbar_x + 64, sbar_y + 24, sb_complete, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1871         DrawQ_Pic (sbar_x + 0, sbar_y + 56, sb_inter, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1872
1873 // time
1874         dig = (int)cl.completed_time / 60;
1875         Sbar_DrawNum (160, 64, dig, 3, 0);
1876         num = (int)cl.completed_time - dig*60;
1877         if (gamemode != GAME_NEXUIZ)
1878                 Sbar_DrawPic (234,64,sb_colon);
1879         Sbar_DrawPic (246,64,sb_nums[0][num/10]);
1880         Sbar_DrawPic (266,64,sb_nums[0][num%10]);
1881
1882         Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
1883         if (gamemode != GAME_NEXUIZ)
1884                 Sbar_DrawPic (232, 104, sb_slash);
1885         Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1886
1887         Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1888         if (gamemode != GAME_NEXUIZ)
1889                 Sbar_DrawPic (232, 144, sb_slash);
1890         Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1891
1892 }
1893
1894
1895 /*
1896 ==================
1897 Sbar_FinaleOverlay
1898
1899 ==================
1900 */
1901 void Sbar_FinaleOverlay (void)
1902 {
1903         DrawQ_Pic((vid_conwidth.integer - sb_finale->width)/2, 16, sb_finale, 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1904 }
1905