disable sbar in GAME_NETHERWORLD (it draws it using qc)
[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 typedef struct sbarpic_s
25 {
26         char name[32];
27 }
28 sbarpic_t;
29
30 static sbarpic_t sbarpics[256];
31 static int numsbarpics;
32
33 static sbarpic_t *Sbar_NewPic(const char *name)
34 {
35         strcpy(sbarpics[numsbarpics].name, name);
36         // precache it
37         // FIXME: precache on every renderer restart (or move this to client)
38         Draw_CachePic(sbarpics[numsbarpics].name, true);
39         return sbarpics + (numsbarpics++);
40 }
41
42 sbarpic_t *sb_disc;
43
44 #define STAT_MINUS 10 // num frame for '-' stats digit
45 sbarpic_t *sb_nums[2][11];
46 sbarpic_t *sb_colon, *sb_slash;
47 sbarpic_t *sb_ibar;
48 sbarpic_t *sb_sbar;
49 sbarpic_t *sb_scorebar;
50 // AK only used by NEX
51 sbarpic_t *sb_sbar_minimal;
52 sbarpic_t *sb_sbar_overlay;
53
54 // AK changed the bound to 9
55 sbarpic_t *sb_weapons[7][9]; // 0 is active, 1 is owned, 2-5 are flashes
56 sbarpic_t *sb_ammo[4];
57 sbarpic_t *sb_sigil[4];
58 sbarpic_t *sb_armor[3];
59 sbarpic_t *sb_items[32];
60
61 // 0-4 are based on health (in 20 increments)
62 // 0 is static, 1 is temporary animation
63 sbarpic_t *sb_faces[5][2];
64
65 sbarpic_t *sb_face_invis;
66 sbarpic_t *sb_face_quad;
67 sbarpic_t *sb_face_invuln;
68 sbarpic_t *sb_face_invis_invuln;
69
70 qboolean sb_showscores;
71
72 int sb_lines;                   // scan lines to draw
73
74 sbarpic_t *rsb_invbar[2];
75 sbarpic_t *rsb_weapons[5];
76 sbarpic_t *rsb_items[2];
77 sbarpic_t *rsb_ammo[3];
78 sbarpic_t *rsb_teambord;                // PGM 01/19/97 - team color border
79
80 //MED 01/04/97 added two more weapons + 3 alternates for grenade launcher
81 sbarpic_t *hsb_weapons[7][5];   // 0 is active, 1 is owned, 2-5 are flashes
82 //MED 01/04/97 added array to simplify weapon parsing
83 int hipweapons[4] = {HIT_LASER_CANNON_BIT,HIT_MJOLNIR_BIT,4,HIT_PROXIMITY_GUN_BIT};
84 //MED 01/04/97 added hipnotic items array
85 sbarpic_t *hsb_items[2];
86
87 //GAME_SOM stuff:
88 sbarpic_t *somsb_health;
89 sbarpic_t *somsb_ammo[4];
90 sbarpic_t *somsb_armor[3];
91
92 sbarpic_t *zymsb_crosshair_center;
93 sbarpic_t *zymsb_crosshair_line;
94 sbarpic_t *zymsb_crosshair_health;
95 sbarpic_t *zymsb_crosshair_ammo;
96 sbarpic_t *zymsb_crosshair_clip;
97 sbarpic_t *zymsb_crosshair_background;
98 sbarpic_t *zymsb_crosshair_left1;
99 sbarpic_t *zymsb_crosshair_left2;
100 sbarpic_t *zymsb_crosshair_right;
101
102 cvar_t  showfps = {CVAR_SAVE, "showfps", "0"};
103 cvar_t  showtime = {CVAR_SAVE, "showtime", "0"};
104 cvar_t  showtime_format = {CVAR_SAVE, "showtime_format", "%H:%M:%S"};
105 cvar_t  showdate = {CVAR_SAVE, "showdate", "0"};
106 cvar_t  showdate_format = {CVAR_SAVE, "showdate_format", "%Y-%m-%d"};
107 cvar_t  sbar_alpha_bg = {CVAR_SAVE, "sbar_alpha_bg", "0.4"};
108 cvar_t  sbar_alpha_fg = {CVAR_SAVE, "sbar_alpha_fg", "1"};
109
110 cvar_t  cl_deathscoreboard = {0, "cl_deathscoreboard", "1"};
111
112 void Sbar_MiniDeathmatchOverlay (int x, int y);
113 void Sbar_DeathmatchOverlay (void);
114 void Sbar_IntermissionOverlay (void);
115 void Sbar_FinaleOverlay (void);
116
117
118 /*
119 ===============
120 Sbar_ShowScores
121
122 Tab key down
123 ===============
124 */
125 void Sbar_ShowScores (void)
126 {
127         if (sb_showscores)
128                 return;
129         sb_showscores = true;
130 }
131
132 /*
133 ===============
134 Sbar_DontShowScores
135
136 Tab key up
137 ===============
138 */
139 void Sbar_DontShowScores (void)
140 {
141         sb_showscores = false;
142 }
143
144 void sbar_start(void)
145 {
146         int i;
147
148         numsbarpics = 0;
149
150         if (gamemode == GAME_NETHERWORLD)
151         {
152         }
153         else if (gamemode == GAME_SOM)
154         {
155                 sb_disc = Sbar_NewPic("gfx/disc");
156
157                 for (i = 0;i < 10;i++)
158                         sb_nums[0][i] = Sbar_NewPic (va("gfx/num_%i",i));
159
160                 somsb_health = Sbar_NewPic("gfx/hud_health");
161                 somsb_ammo[0] = Sbar_NewPic("gfx/sb_shells");
162                 somsb_ammo[1] = Sbar_NewPic("gfx/sb_nails");
163                 somsb_ammo[2] = Sbar_NewPic("gfx/sb_rocket");
164                 somsb_ammo[3] = Sbar_NewPic("gfx/sb_cells");
165                 somsb_armor[0] = Sbar_NewPic("gfx/sb_armor1");
166                 somsb_armor[1] = Sbar_NewPic("gfx/sb_armor2");
167                 somsb_armor[2] = Sbar_NewPic("gfx/sb_armor3");
168         }
169         else if (gamemode == GAME_NEXUIZ)
170         {
171                 for (i = 0;i < 10;i++)
172                         sb_nums[0][i] = Sbar_NewPic (va("gfx/num_%i",i));
173                 sb_nums[0][10] = Sbar_NewPic ("gfx/num_minus");
174
175                 sb_ammo[0] = Sbar_NewPic ("gfx/sb_shells");
176                 sb_ammo[1] = Sbar_NewPic ("gfx/sb_bullets");
177                 sb_ammo[2] = Sbar_NewPic ("gfx/sb_rocket");
178                 sb_ammo[3] = Sbar_NewPic ("gfx/sb_cells");
179
180                 sb_items[2] = Sbar_NewPic ("gfx/sb_slowmo");
181                 sb_items[3] = Sbar_NewPic ("gfx/sb_invinc");
182                 sb_items[4] = Sbar_NewPic ("gfx/sb_energy");
183                 sb_items[5] = Sbar_NewPic ("gfx/sb_str");
184
185                 sb_sbar = Sbar_NewPic("gfx/sbar");
186                 sb_sbar_minimal = Sbar_NewPic("gfx/sbar_minimal");
187                 sb_sbar_overlay = Sbar_NewPic("gfx/sbar_overlay");
188
189                 for(i = 0; i < 9;i++)
190                         sb_weapons[0][i] = Sbar_NewPic(va("gfx/inv_weapon%i",i));
191         }
192         else if (gamemode == GAME_ZYMOTIC)
193         {
194                 zymsb_crosshair_center = Sbar_NewPic ("gfx/hud/crosshair_center");
195                 zymsb_crosshair_line = Sbar_NewPic ("gfx/hud/crosshair_line");
196                 zymsb_crosshair_health = Sbar_NewPic ("gfx/hud/crosshair_health");
197                 zymsb_crosshair_clip = Sbar_NewPic ("gfx/hud/crosshair_clip");
198                 zymsb_crosshair_ammo = Sbar_NewPic ("gfx/hud/crosshair_ammo");
199                 zymsb_crosshair_background = Sbar_NewPic ("gfx/hud/crosshair_background");
200                 zymsb_crosshair_left1 = Sbar_NewPic ("gfx/hud/crosshair_left1");
201                 zymsb_crosshair_left2 = Sbar_NewPic ("gfx/hud/crosshair_left2");
202                 zymsb_crosshair_right = Sbar_NewPic ("gfx/hud/crosshair_right");
203         }
204         else
205         {
206                 sb_disc = Sbar_NewPic("gfx/disc");
207
208                 for (i = 0;i < 10;i++)
209                 {
210                         sb_nums[0][i] = Sbar_NewPic (va("gfx/num_%i",i));
211                         sb_nums[1][i] = Sbar_NewPic (va("gfx/anum_%i",i));
212                 }
213
214                 sb_nums[0][10] = Sbar_NewPic ("gfx/num_minus");
215                 sb_nums[1][10] = Sbar_NewPic ("gfx/anum_minus");
216
217                 sb_colon = Sbar_NewPic ("gfx/num_colon");
218                 sb_slash = Sbar_NewPic ("gfx/num_slash");
219
220                 sb_weapons[0][0] = Sbar_NewPic ("gfx/inv_shotgun");
221                 sb_weapons[0][1] = Sbar_NewPic ("gfx/inv_sshotgun");
222                 sb_weapons[0][2] = Sbar_NewPic ("gfx/inv_nailgun");
223                 sb_weapons[0][3] = Sbar_NewPic ("gfx/inv_snailgun");
224                 sb_weapons[0][4] = Sbar_NewPic ("gfx/inv_rlaunch");
225                 sb_weapons[0][5] = Sbar_NewPic ("gfx/inv_srlaunch");
226                 sb_weapons[0][6] = Sbar_NewPic ("gfx/inv_lightng");
227
228                 sb_weapons[1][0] = Sbar_NewPic ("gfx/inv2_shotgun");
229                 sb_weapons[1][1] = Sbar_NewPic ("gfx/inv2_sshotgun");
230                 sb_weapons[1][2] = Sbar_NewPic ("gfx/inv2_nailgun");
231                 sb_weapons[1][3] = Sbar_NewPic ("gfx/inv2_snailgun");
232                 sb_weapons[1][4] = Sbar_NewPic ("gfx/inv2_rlaunch");
233                 sb_weapons[1][5] = Sbar_NewPic ("gfx/inv2_srlaunch");
234                 sb_weapons[1][6] = Sbar_NewPic ("gfx/inv2_lightng");
235
236                 for (i = 0;i < 5;i++)
237                 {
238                         sb_weapons[2+i][0] = Sbar_NewPic (va("gfx/inva%i_shotgun",i+1));
239                         sb_weapons[2+i][1] = Sbar_NewPic (va("gfx/inva%i_sshotgun",i+1));
240                         sb_weapons[2+i][2] = Sbar_NewPic (va("gfx/inva%i_nailgun",i+1));
241                         sb_weapons[2+i][3] = Sbar_NewPic (va("gfx/inva%i_snailgun",i+1));
242                         sb_weapons[2+i][4] = Sbar_NewPic (va("gfx/inva%i_rlaunch",i+1));
243                         sb_weapons[2+i][5] = Sbar_NewPic (va("gfx/inva%i_srlaunch",i+1));
244                         sb_weapons[2+i][6] = Sbar_NewPic (va("gfx/inva%i_lightng",i+1));
245                 }
246
247                 sb_ammo[0] = Sbar_NewPic ("gfx/sb_shells");
248                 sb_ammo[1] = Sbar_NewPic ("gfx/sb_nails");
249                 sb_ammo[2] = Sbar_NewPic ("gfx/sb_rocket");
250                 sb_ammo[3] = Sbar_NewPic ("gfx/sb_cells");
251
252                 sb_armor[0] = Sbar_NewPic ("gfx/sb_armor1");
253                 sb_armor[1] = Sbar_NewPic ("gfx/sb_armor2");
254                 sb_armor[2] = Sbar_NewPic ("gfx/sb_armor3");
255
256                 sb_items[0] = Sbar_NewPic ("gfx/sb_key1");
257                 sb_items[1] = Sbar_NewPic ("gfx/sb_key2");
258                 sb_items[2] = Sbar_NewPic ("gfx/sb_invis");
259                 sb_items[3] = Sbar_NewPic ("gfx/sb_invuln");
260                 sb_items[4] = Sbar_NewPic ("gfx/sb_suit");
261                 sb_items[5] = Sbar_NewPic ("gfx/sb_quad");
262
263                 sb_sigil[0] = Sbar_NewPic ("gfx/sb_sigil1");
264                 sb_sigil[1] = Sbar_NewPic ("gfx/sb_sigil2");
265                 sb_sigil[2] = Sbar_NewPic ("gfx/sb_sigil3");
266                 sb_sigil[3] = Sbar_NewPic ("gfx/sb_sigil4");
267
268                 sb_faces[4][0] = Sbar_NewPic ("gfx/face1");
269                 sb_faces[4][1] = Sbar_NewPic ("gfx/face_p1");
270                 sb_faces[3][0] = Sbar_NewPic ("gfx/face2");
271                 sb_faces[3][1] = Sbar_NewPic ("gfx/face_p2");
272                 sb_faces[2][0] = Sbar_NewPic ("gfx/face3");
273                 sb_faces[2][1] = Sbar_NewPic ("gfx/face_p3");
274                 sb_faces[1][0] = Sbar_NewPic ("gfx/face4");
275                 sb_faces[1][1] = Sbar_NewPic ("gfx/face_p4");
276                 sb_faces[0][0] = Sbar_NewPic ("gfx/face5");
277                 sb_faces[0][1] = Sbar_NewPic ("gfx/face_p5");
278
279                 sb_face_invis = Sbar_NewPic ("gfx/face_invis");
280                 sb_face_invuln = Sbar_NewPic ("gfx/face_invul2");
281                 sb_face_invis_invuln = Sbar_NewPic ("gfx/face_inv2");
282                 sb_face_quad = Sbar_NewPic ("gfx/face_quad");
283
284                 sb_sbar = Sbar_NewPic ("gfx/sbar");
285                 sb_ibar = Sbar_NewPic ("gfx/ibar");
286                 sb_scorebar = Sbar_NewPic ("gfx/scorebar");
287
288         //MED 01/04/97 added new hipnotic weapons
289                 if (gamemode == GAME_HIPNOTIC)
290                 {
291                         hsb_weapons[0][0] = Sbar_NewPic ("gfx/inv_laser");
292                         hsb_weapons[0][1] = Sbar_NewPic ("gfx/inv_mjolnir");
293                         hsb_weapons[0][2] = Sbar_NewPic ("gfx/inv_gren_prox");
294                         hsb_weapons[0][3] = Sbar_NewPic ("gfx/inv_prox_gren");
295                         hsb_weapons[0][4] = Sbar_NewPic ("gfx/inv_prox");
296
297                         hsb_weapons[1][0] = Sbar_NewPic ("gfx/inv2_laser");
298                         hsb_weapons[1][1] = Sbar_NewPic ("gfx/inv2_mjolnir");
299                         hsb_weapons[1][2] = Sbar_NewPic ("gfx/inv2_gren_prox");
300                         hsb_weapons[1][3] = Sbar_NewPic ("gfx/inv2_prox_gren");
301                         hsb_weapons[1][4] = Sbar_NewPic ("gfx/inv2_prox");
302
303                         for (i = 0;i < 5;i++)
304                         {
305                                 hsb_weapons[2+i][0] = Sbar_NewPic (va("gfx/inva%i_laser",i+1));
306                                 hsb_weapons[2+i][1] = Sbar_NewPic (va("gfx/inva%i_mjolnir",i+1));
307                                 hsb_weapons[2+i][2] = Sbar_NewPic (va("gfx/inva%i_gren_prox",i+1));
308                                 hsb_weapons[2+i][3] = Sbar_NewPic (va("gfx/inva%i_prox_gren",i+1));
309                                 hsb_weapons[2+i][4] = Sbar_NewPic (va("gfx/inva%i_prox",i+1));
310                         }
311
312                         hsb_items[0] = Sbar_NewPic ("gfx/sb_wsuit");
313                         hsb_items[1] = Sbar_NewPic ("gfx/sb_eshld");
314                 }
315                 else if (gamemode == GAME_ROGUE)
316                 {
317                         rsb_invbar[0] = Sbar_NewPic ("gfx/r_invbar1");
318                         rsb_invbar[1] = Sbar_NewPic ("gfx/r_invbar2");
319
320                         rsb_weapons[0] = Sbar_NewPic ("gfx/r_lava");
321                         rsb_weapons[1] = Sbar_NewPic ("gfx/r_superlava");
322                         rsb_weapons[2] = Sbar_NewPic ("gfx/r_gren");
323                         rsb_weapons[3] = Sbar_NewPic ("gfx/r_multirock");
324                         rsb_weapons[4] = Sbar_NewPic ("gfx/r_plasma");
325
326                         rsb_items[0] = Sbar_NewPic ("gfx/r_shield1");
327                         rsb_items[1] = Sbar_NewPic ("gfx/r_agrav1");
328
329         // PGM 01/19/97 - team color border
330                         rsb_teambord = Sbar_NewPic ("gfx/r_teambord");
331         // PGM 01/19/97 - team color border
332
333                         rsb_ammo[0] = Sbar_NewPic ("gfx/r_ammolava");
334                         rsb_ammo[1] = Sbar_NewPic ("gfx/r_ammomulti");
335                         rsb_ammo[2] = Sbar_NewPic ("gfx/r_ammoplasma");
336                 }
337         }
338 }
339
340 void sbar_shutdown(void)
341 {
342 }
343
344 void sbar_newmap(void)
345 {
346 }
347
348 void Sbar_Init (void)
349 {
350         Cmd_AddCommand ("+showscores", Sbar_ShowScores);
351         Cmd_AddCommand ("-showscores", Sbar_DontShowScores);
352         Cvar_RegisterVariable (&showfps);
353         Cvar_RegisterVariable (&showtime);
354         Cvar_RegisterVariable (&showtime_format);
355         Cvar_RegisterVariable (&showdate);
356         Cvar_RegisterVariable (&showdate_format);
357         Cvar_RegisterVariable (&sbar_alpha_bg);
358         Cvar_RegisterVariable (&sbar_alpha_fg);
359         Cvar_RegisterVariable (&cl_deathscoreboard);
360
361         R_RegisterModule("sbar", sbar_start, sbar_shutdown, sbar_newmap);
362 }
363
364
365 //=============================================================================
366
367 // drawing routines are relative to the status bar location
368
369 int sbar_x, sbar_y;
370
371 /*
372 =============
373 Sbar_DrawPic
374 =============
375 */
376 void Sbar_DrawPic (int x, int y, sbarpic_t *sbarpic)
377 {
378         DrawQ_Pic (sbar_x + x, sbar_y + y, sbarpic->name, 0, 0, 1, 1, 1, sbar_alpha_fg.value, 0);
379 }
380
381 void Sbar_DrawAlphaPic (int x, int y, sbarpic_t *sbarpic, float alpha)
382 {
383         DrawQ_Pic (sbar_x + x, sbar_y + y, sbarpic->name, 0, 0, 1, 1, 1, alpha, 0);
384 }
385
386 /*
387 ================
388 Sbar_DrawCharacter
389
390 Draws one solid graphics character
391 ================
392 */
393 void Sbar_DrawCharacter (int x, int y, int num)
394 {
395         DrawQ_String (sbar_x + x + 4 , sbar_y + y, va("%c", num), 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0);
396 }
397
398 /*
399 ================
400 Sbar_DrawString
401 ================
402 */
403 void Sbar_DrawString (int x, int y, char *str)
404 {
405         DrawQ_String (sbar_x + x, sbar_y + y, str, 0, 8, 8, 1, 1, 1, sbar_alpha_fg.value, 0);
406 }
407
408 /*
409 =============
410 Sbar_DrawNum
411 =============
412 */
413 void Sbar_DrawNum (int x, int y, int num, int digits, int color)
414 {
415         char str[32], *ptr;
416         int l, frame;
417
418         l = sprintf(str, "%i", num);
419         ptr = str;
420         if (l > digits)
421                 ptr += (l-digits);
422         if (l < digits)
423                 x += (digits-l)*24;
424
425         while (*ptr)
426         {
427                 if (*ptr == '-')
428                         frame = STAT_MINUS;
429                 else
430                         frame = *ptr -'0';
431
432                 Sbar_DrawPic (x, y, sb_nums[color][frame]);
433                 x += 24;
434
435                 ptr++;
436         }
437 }
438
439 /*
440 =============
441 Sbar_DrawXNum
442 =============
443 */
444
445 void Sbar_DrawXNum (int x, int y, int num, int digits, int lettersize, float r, float g, float b, float a, int flags)
446 {
447         char str[32], *ptr;
448         int l, frame;
449
450         l = sprintf(str, "%i", num);
451         ptr = str;
452         if (l > digits)
453                 ptr += (l-digits);
454         if (l < digits)
455                 x += (digits-l) * lettersize;
456
457         while (*ptr)
458         {
459                 if (*ptr == '-')
460                         frame = STAT_MINUS;
461                 else
462                         frame = *ptr -'0';
463
464                 DrawQ_Pic (sbar_x + x, sbar_y + y, sb_nums[0][frame]->name,lettersize,lettersize,r,g,b,a * sbar_alpha_fg.value,flags);
465                 x += lettersize;
466
467                 ptr++;
468         }
469 }
470
471 //=============================================================================
472
473
474 /*
475 ===============
476 Sbar_SortFrags
477 ===============
478 */
479 static int fragsort[MAX_SCOREBOARD];
480 static int scoreboardlines;
481 void Sbar_SortFrags (void)
482 {
483         int             i, j, k;
484
485 // sort by frags
486         scoreboardlines = 0;
487         for (i=0 ; i<cl.maxclients ; i++)
488         {
489                 if (cl.scores[i].name[0])
490                 {
491                         fragsort[scoreboardlines] = i;
492                         scoreboardlines++;
493                 }
494         }
495
496         for (i=0 ; i<scoreboardlines ; i++)
497                 for (j=0 ; j<scoreboardlines-1-i ; j++)
498                         if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j+1]].frags)
499                         {
500                                 k = fragsort[j];
501                                 fragsort[j] = fragsort[j+1];
502                                 fragsort[j+1] = k;
503                         }
504 }
505
506 /*
507 ===============
508 Sbar_SoloScoreboard
509 ===============
510 */
511 void Sbar_SoloScoreboard (void)
512 {
513         char    str[80];
514         int             minutes, seconds, tens, units;
515         int             l;
516
517         if (gamemode != GAME_NEXUIZ) {
518                 sprintf (str,"Monsters:%3i /%3i", cl.stats[STAT_MONSTERS], cl.stats[STAT_TOTALMONSTERS]);
519                 Sbar_DrawString (8, 4, str);
520
521                 sprintf (str,"Secrets :%3i /%3i", cl.stats[STAT_SECRETS], cl.stats[STAT_TOTALSECRETS]);
522                 Sbar_DrawString (8, 12, str);
523         }
524
525 // time
526         minutes = cl.time / 60;
527         seconds = cl.time - 60*minutes;
528         tens = seconds / 10;
529         units = seconds - 10*tens;
530         sprintf (str,"Time :%3i:%i%i", minutes, tens, units);
531         Sbar_DrawString (184, 4, str);
532
533 // draw level name
534         if (gamemode == GAME_NEXUIZ) {
535                 l = (int) strlen (cl.worldmodel->name);
536                 Sbar_DrawString (232 - l*4, 12, cl.worldmodel->name);
537         } else {
538                 l = (int) strlen (cl.levelname);
539                 Sbar_DrawString (232 - l*4, 12, cl.levelname);
540         }
541 }
542
543 /*
544 ===============
545 Sbar_DrawScoreboard
546 ===============
547 */
548 void Sbar_DrawScoreboard (void)
549 {
550         Sbar_SoloScoreboard ();
551         if (cl.gametype == GAME_DEATHMATCH)
552                 Sbar_DeathmatchOverlay ();
553 }
554
555 //=============================================================================
556
557 // AK to make DrawInventory smaller
558 static void Sbar_DrawWeapon(int nr, float fade, int active)
559 {
560         // width = 300, height = 100
561         const int w_width = 300, w_height = 100, w_space = 10;
562         const float w_scale = 0.4;
563
564         DrawQ_Pic(vid_conwidth.integer - (w_width + w_space) * w_scale, (w_height + w_space) * w_scale * nr + w_space, sb_weapons[0][nr]->name, w_width * w_scale, w_height * w_scale, (active) ? 1 : 0.6, active ? 1 : 0.6, active ? 1 : 1, fade * sbar_alpha_fg.value, DRAWFLAG_ADDITIVE);
565         //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);
566
567         if (active)
568                 DrawQ_Fill(vid_conwidth.integer - (w_width + w_space) * w_scale, (w_height + w_space) * w_scale * nr + w_space, w_width * w_scale, w_height * w_scale, 0.3, 0.3, 0.3, fade * sbar_alpha_fg.value, DRAWFLAG_ADDITIVE);
569 }
570
571 /*
572 ===============
573 Sbar_DrawInventory
574 ===============
575 */
576 void Sbar_DrawInventory (void)
577 {
578         int i;
579         char num[6];
580         float time;
581         int flashon;
582
583         if (gamemode == GAME_ROGUE)
584         {
585                 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
586                         Sbar_DrawAlphaPic (0, -24, rsb_invbar[0], sbar_alpha_bg.value);
587                 else
588                         Sbar_DrawAlphaPic (0, -24, rsb_invbar[1], sbar_alpha_bg.value);
589         }
590         else
591                 Sbar_DrawAlphaPic (0, -24, sb_ibar, sbar_alpha_bg.value);
592
593         // weapons
594         for (i=0 ; i<7 ; i++)
595         {
596                 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<i) )
597                 {
598                         time = cl.item_gettime[i];
599                         flashon = (int)((cl.time - time)*10);
600                         if (flashon >= 10)
601                         {
602                                 if ( cl.stats[STAT_ACTIVEWEAPON] == (IT_SHOTGUN<<i)  )
603                                         flashon = 1;
604                                 else
605                                         flashon = 0;
606                         }
607                         else
608                                 flashon = (flashon%5) + 2;
609
610                         Sbar_DrawAlphaPic (i*24, -16, sb_weapons[flashon][i], sbar_alpha_bg.value);
611                 }
612         }
613
614         // MED 01/04/97
615         // hipnotic weapons
616         if (gamemode == GAME_HIPNOTIC)
617         {
618                 int grenadeflashing=0;
619                 for (i=0 ; i<4 ; i++)
620                 {
621                         if (cl.stats[STAT_ITEMS] & (1<<hipweapons[i]) )
622                         {
623                                 time = cl.item_gettime[hipweapons[i]];
624                                 flashon = (int)((cl.time - time)*10);
625                                 if (flashon >= 10)
626                                 {
627                                         if ( cl.stats[STAT_ACTIVEWEAPON] == (1<<hipweapons[i])  )
628                                                 flashon = 1;
629                                         else
630                                                 flashon = 0;
631                                 }
632                                 else
633                                         flashon = (flashon%5) + 2;
634
635                                 // check grenade launcher
636                                 if (i==2)
637                                 {
638                                         if (cl.stats[STAT_ITEMS] & HIT_PROXIMITY_GUN)
639                                         {
640                                                 if (flashon)
641                                                 {
642                                                         grenadeflashing = 1;
643                                                         Sbar_DrawPic (96, -16, hsb_weapons[flashon][2]);
644                                                 }
645                                         }
646                                 }
647                                 else if (i==3)
648                                 {
649                                         if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN<<4))
650                                         {
651                                                 if (!grenadeflashing)
652                                                         Sbar_DrawPic (96, -16, hsb_weapons[flashon][3]);
653                                         }
654                                         else
655                                                 Sbar_DrawPic (96, -16, hsb_weapons[flashon][4]);
656                                 }
657                                 else
658                                         Sbar_DrawPic (176 + (i*24), -16, hsb_weapons[flashon][i]);
659                         }
660                 }
661         }
662
663         if (gamemode == GAME_ROGUE)
664         {
665                 // check for powered up weapon.
666                 if ( cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN )
667                         for (i=0;i<5;i++)
668                                 if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i))
669                                         Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]);
670         }
671
672         // ammo counts
673         for (i=0 ; i<4 ; i++)
674         {
675                 sprintf (num, "%3i",cl.stats[STAT_SHELLS+i] );
676                 if (num[0] != ' ')
677                         Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[0] - '0');
678                 if (num[1] != ' ')
679                         Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[1] - '0');
680                 if (num[2] != ' ')
681                         Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0');
682         }
683
684         // items
685         for (i=0 ; i<6 ; i++)
686                 if (cl.stats[STAT_ITEMS] & (1<<(17+i)))
687                 {
688                         //MED 01/04/97 changed keys
689                         if (gamemode != GAME_HIPNOTIC || (i>1))
690                                 Sbar_DrawPic (192 + i*16, -16, sb_items[i]);
691                 }
692
693         //MED 01/04/97 added hipnotic items
694         // hipnotic items
695         if (gamemode == GAME_HIPNOTIC)
696         {
697                 for (i=0 ; i<2 ; i++)
698                         if (cl.stats[STAT_ITEMS] & (1<<(24+i)))
699                                 Sbar_DrawPic (288 + i*16, -16, hsb_items[i]);
700         }
701
702         if (gamemode == GAME_ROGUE)
703         {
704                 // new rogue items
705                 for (i=0 ; i<2 ; i++)
706                         if (cl.stats[STAT_ITEMS] & (1<<(29+i)))
707                                 Sbar_DrawPic (288 + i*16, -16, rsb_items[i]);
708         }
709         else
710         {
711                 // sigils
712                 for (i=0 ; i<4 ; i++)
713                         if (cl.stats[STAT_ITEMS] & (1<<(28+i)))
714                                 Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]);
715         }
716 }
717
718 //=============================================================================
719
720 /*
721 ===============
722 Sbar_DrawFrags
723 ===============
724 */
725 void Sbar_DrawFrags (void)
726 {
727         int i, k, l, x, f;
728         char num[12];
729         scoreboard_t *s;
730         unsigned char *c;
731
732         Sbar_SortFrags ();
733
734         // draw the text
735         l = min(scoreboardlines, 4);
736
737         x = 23 * 8;
738
739         for (i = 0;i < l;i++)
740         {
741                 k = fragsort[i];
742                 s = &cl.scores[k];
743
744                 // draw background
745                 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
746                 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);
747                 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
748                 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);
749
750                 // draw number
751                 f = s->frags;
752                 sprintf (num, "%3i",f);
753
754                 if (k == cl.viewentity - 1)
755                 {
756                         Sbar_DrawCharacter ( x      + 2, -24, 16);
757                         Sbar_DrawCharacter ( x + 32 - 4, -24, 17);
758                 }
759                 Sbar_DrawCharacter (x +  8, -24, num[0]);
760                 Sbar_DrawCharacter (x + 16, -24, num[1]);
761                 Sbar_DrawCharacter (x + 24, -24, num[2]);
762                 x += 32;
763         }
764 }
765
766 //=============================================================================
767
768
769 /*
770 ===============
771 Sbar_DrawFace
772 ===============
773 */
774 void Sbar_DrawFace (void)
775 {
776         int f;
777
778 // PGM 01/19/97 - team color drawing
779 // PGM 03/02/97 - fixed so color swatch only appears in CTF modes
780         if (gamemode == GAME_ROGUE && !cl.islocalgame && (teamplay.integer > 3) && (teamplay.integer < 7))
781         {
782                 char num[12];
783                 scoreboard_t *s;
784                 unsigned char *c;
785
786                 s = &cl.scores[cl.viewentity - 1];
787                 // draw background
788                 Sbar_DrawPic (112, 0, rsb_teambord);
789                 c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
790                 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);
791                 c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
792                 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);
793
794                 // draw number
795                 f = s->frags;
796                 sprintf (num, "%3i",f);
797
798                 if ((s->colors & 0xf0)==0)
799                 {
800                         if (num[0] != ' ')
801                                 Sbar_DrawCharacter(109, 3, 18 + num[0] - '0');
802                         if (num[1] != ' ')
803                                 Sbar_DrawCharacter(116, 3, 18 + num[1] - '0');
804                         if (num[2] != ' ')
805                                 Sbar_DrawCharacter(123, 3, 18 + num[2] - '0');
806                 }
807                 else
808                 {
809                         Sbar_DrawCharacter ( 109, 3, num[0]);
810                         Sbar_DrawCharacter ( 116, 3, num[1]);
811                         Sbar_DrawCharacter ( 123, 3, num[2]);
812                 }
813
814                 return;
815         }
816 // PGM 01/19/97 - team color drawing
817
818         if ( (cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY) ) == (IT_INVISIBILITY | IT_INVULNERABILITY) )
819                 Sbar_DrawPic (112, 0, sb_face_invis_invuln);
820         else if (cl.stats[STAT_ITEMS] & IT_QUAD)
821                 Sbar_DrawPic (112, 0, sb_face_quad );
822         else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
823                 Sbar_DrawPic (112, 0, sb_face_invis );
824         else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
825                 Sbar_DrawPic (112, 0, sb_face_invuln);
826         else
827         {
828                 f = cl.stats[STAT_HEALTH] / 20;
829                 f = bound(0, f, 4);
830                 Sbar_DrawPic (112, 0, sb_faces[f][cl.time <= cl.faceanimtime]);
831         }
832 }
833
834 void Sbar_ShowFPS(void)
835 {
836         float fps_x, fps_y, fps_scalex, fps_scaley, fps_height;
837         char fpsstring[32];
838         char timestring[32];
839         char datestring[32];
840         qboolean red = false;
841         fpsstring[0] = 0;
842         timestring[0] = 0;
843         datestring[0] = 0;
844         if (showfps.integer)
845         {
846                 float calc;
847                 if (showfps.integer > 1)
848                 {
849                         static double currtime, frametimes[32];
850                         double newtime, total;
851                         int count, i;
852                         static int framecycle = 0;
853
854                         newtime = Sys_DoubleTime();
855                         frametimes[framecycle] = newtime - currtime;
856                         total = 0;
857                         count = 0;
858                         while(total < 0.2 && count < 32 && frametimes[i = (framecycle - count) & 31])
859                         {
860                                 total += frametimes[i];
861                                 count++;
862                         }
863                         framecycle++;
864                         framecycle &= 31;
865                         if (showfps.integer == 2)
866                                 calc = (((double)count / total) + 0.5);
867                         else // showfps 3, rapid update
868                                 calc = ((1.0 / (newtime - currtime)) + 0.5);
869                         currtime = newtime;
870                 }
871                 else
872                 {
873                         static double nexttime = 0, lasttime = 0;
874                         static float framerate = 0;
875                         static int framecount = 0;
876                         double newtime;
877                         newtime = Sys_DoubleTime();
878                         if (newtime >= nexttime)
879                         {
880                                 framerate = ((float)framecount / (newtime - lasttime) + 0.5);
881                                 lasttime = newtime;
882                                 nexttime = max(nexttime + 1, lasttime - 1);
883                                 framecount = 0;
884                         }
885                         framecount++;
886                         calc = framerate;
887                 }
888
889                 if ((red = (calc < 1.0f)))
890                         dpsnprintf(fpsstring, sizeof(fpsstring), "%4i spf", (int)(1.0f / calc + 0.5));
891                 else
892                         dpsnprintf(fpsstring, sizeof(fpsstring), "%4i fps", (int)(calc + 0.5));
893         }
894         if (showtime.integer)
895                 strlcpy(timestring, Sys_TimeString(showtime_format.string), sizeof(timestring));
896         if (showdate.integer)
897                 strlcpy(datestring, Sys_TimeString(showdate_format.string), sizeof(datestring));
898         if (fpsstring[0] || timestring[0])
899         {
900                 fps_scalex = 12;
901                 fps_scaley = 12;
902                 fps_height = fps_scaley * ((fpsstring[0] != 0) + (timestring[0] != 0) + (datestring[0] != 0));
903                 //fps_y = vid_conheight.integer - sb_lines; // yes this may draw over the sbar
904                 //fps_y = bound(0, fps_y, vid_conheight.integer - fps_height);
905                 fps_y = vid_conheight.integer - fps_height;
906                 if (fpsstring[0])
907                 {
908                         fps_x = vid_conwidth.integer - fps_scalex * strlen(fpsstring);
909                         DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(fpsstring), fps_scaley, 0, 0, 0, 0.5, 0);
910                         if (red)
911                                 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 0, 0, 1, 0);
912                         else
913                                 DrawQ_String(fps_x, fps_y, fpsstring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
914                         fps_y += fps_scaley;
915                 }
916                 if (timestring[0])
917                 {
918                         fps_x = vid_conwidth.integer - fps_scalex * strlen(timestring);
919                         DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(timestring), fps_scaley, 0, 0, 0, 0.5, 0);
920                         DrawQ_String(fps_x, fps_y, timestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
921                         fps_y += fps_scaley;
922                 }
923                 if (datestring[0])
924                 {
925                         fps_x = vid_conwidth.integer - fps_scalex * strlen(datestring);
926                         DrawQ_Fill(fps_x, fps_y, fps_scalex * strlen(datestring), fps_scaley, 0, 0, 0, 0.5, 0);
927                         DrawQ_String(fps_x, fps_y, datestring, 0, fps_scalex, fps_scaley, 1, 1, 1, 1, 0);
928                         fps_y += fps_scaley;
929                 }
930         }
931 }
932
933 void Sbar_DrawGauge(float x, float y, const char *picname, 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)
934 {
935         float r[5];
936         c2 = bound(0, c2, 1);
937         c1 = bound(0, c1, 1 - c2);
938         r[0] = 0;
939         r[1] = rangey + rangeheight * (c2 + c1);
940         r[2] = rangey + rangeheight * (c2);
941         r[3] = rangey;
942         r[4] = height;
943         if (r[1] > r[0])
944                 DrawQ_SuperPic(x, y + r[0], picname, 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);
945         if (r[2] > r[1])
946                 DrawQ_SuperPic(x, y + r[1], picname, 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);
947         if (r[3] > r[2])
948                 DrawQ_SuperPic(x, y + r[2], picname, 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);
949         if (r[4] > r[3])
950                 DrawQ_SuperPic(x, y + r[3], picname, 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);
951 }
952
953 /*
954 ===============
955 Sbar_Draw
956 ===============
957 */
958 extern float v_dmg_time, v_dmg_roll, v_dmg_pitch;
959 extern cvar_t v_kicktime;
960 void Sbar_Draw (void)
961 {
962         if (cl.intermission == 1)
963         {
964                 Sbar_IntermissionOverlay();
965                 return;
966         }
967         else if (cl.intermission == 2)
968         {
969                 Sbar_FinaleOverlay();
970                 return;
971         }
972
973         if (gamemode == GAME_NETHERWORLD)
974         {
975         }
976         else if (gamemode == GAME_SOM)
977         {
978                 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
979                         Sbar_DrawScoreboard ();
980                 else if (sb_lines)
981                 {
982                         // this is the top left of the sbar area
983                         sbar_x = 0;
984                         sbar_y = vid_conheight.integer - 24*3;
985
986                         // armor
987                         if (cl.stats[STAT_ARMOR])
988                         {
989                                 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
990                                         Sbar_DrawPic(0, 0, somsb_armor[2]);
991                                 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
992                                         Sbar_DrawPic(0, 0, somsb_armor[1]);
993                                 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
994                                         Sbar_DrawPic(0, 0, somsb_armor[0]);
995                                 Sbar_DrawNum(24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
996                         }
997
998                         // health
999                         Sbar_DrawPic(0, 24, somsb_health);
1000                         Sbar_DrawNum(24, 24, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1001
1002                         // ammo icon
1003                         if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1004                                 Sbar_DrawPic(0, 48, somsb_ammo[0]);
1005                         else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1006                                 Sbar_DrawPic(0, 48, somsb_ammo[1]);
1007                         else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1008                                 Sbar_DrawPic(0, 48, somsb_ammo[2]);
1009                         else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1010                                 Sbar_DrawPic(0, 48, somsb_ammo[3]);
1011                         Sbar_DrawNum(24, 48, cl.stats[STAT_AMMO], 3, false);
1012                         if (cl.stats[STAT_SHELLS])
1013                                 Sbar_DrawNum(24 + 3*24, 48, cl.stats[STAT_SHELLS], 1, true);
1014                 }
1015         }
1016         else if (gamemode == GAME_NEXUIZ)
1017         {
1018                 sbar_y = vid_conheight.integer - 47;
1019                 sbar_x = (vid_conwidth.integer - 640)/2;
1020
1021                 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1022                 {
1023                         Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1024                         Sbar_DrawScoreboard ();
1025                 }
1026                 else if (sb_lines)
1027                 {
1028                         int i;
1029                         double time;
1030                         float fade;
1031
1032                         // we have a max time 2s (min time = 0)
1033                         if ((time = cl.time - cl.weapontime) < 2)
1034                         {
1035                                 fade = (1.0 - 0.5 * time);
1036                                 fade *= fade;
1037                                 for (i = 0; i < 8;i++)
1038                                         if (cl.stats[STAT_ITEMS] & (1 << i))
1039                                                 Sbar_DrawWeapon(i + 1, fade, (i + 2 == cl.stats[STAT_ACTIVEWEAPON]));
1040
1041                                 if((cl.stats[STAT_ITEMS] & (1<<12)))
1042                                         Sbar_DrawWeapon(0, fade, (cl.stats[STAT_ACTIVEWEAPON] == 1));
1043                         }
1044
1045                         //if (!cl.islocalgame)
1046                         //      Sbar_DrawFrags ();
1047
1048                         if (sb_lines > 24)
1049                                 Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_fg.value);
1050                         else
1051                                 Sbar_DrawAlphaPic (0, 0, sb_sbar_minimal, sbar_alpha_fg.value);
1052
1053                         // special items
1054                         if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1055                         {
1056                                 // Nexuiz has no anum pics
1057                                 //Sbar_DrawNum (36, 0, 666, 3, 1);
1058                                 // Nexuiz has no disc pic
1059                                 //Sbar_DrawPic (0, 0, sb_disc);
1060                         }
1061
1062                         // armor
1063                         Sbar_DrawXNum ((340-3*24), 12, cl.stats[STAT_ARMOR], 3, 24, 0.6,0.7,0.8,1,0);
1064
1065                         // health
1066                         if(cl.stats[STAT_HEALTH] > 100)
1067                                 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,1,1,1,1,0);
1068                         else if(cl.stats[STAT_HEALTH] <= 25 && cl.time - (int)cl.time > 0.5)
1069                                 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.7,0,0,1,0);
1070                         else
1071                                 Sbar_DrawXNum((154-3*24),12,cl.stats[STAT_HEALTH],3,24,0.6,0.7,0.8,1,0);
1072
1073                         // AK dont draw ammo for the laser
1074                         if(cl.stats[STAT_ACTIVEWEAPON] != 12)
1075                         {
1076                                 if (cl.stats[STAT_ITEMS] & NEX_IT_SHELLS)
1077                                         Sbar_DrawPic (519, 0, sb_ammo[0]);
1078                                 else if (cl.stats[STAT_ITEMS] & NEX_IT_BULLETS)
1079                                         Sbar_DrawPic (519, 0, sb_ammo[1]);
1080                                 else if (cl.stats[STAT_ITEMS] & NEX_IT_ROCKETS)
1081                                         Sbar_DrawPic (519, 0, sb_ammo[2]);
1082                                 else if (cl.stats[STAT_ITEMS] & NEX_IT_CELLS)
1083                                         Sbar_DrawPic (519, 0, sb_ammo[3]);
1084
1085                                 if(cl.stats[STAT_AMMO] <= 10)
1086                                         Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.7, 0,0,1,0);
1087                                 else
1088                                         Sbar_DrawXNum ((519-3*24), 12, cl.stats[STAT_AMMO], 3, 24, 0.6, 0.7,0.8,1,0);
1089
1090                         }
1091
1092                         if (sb_lines > 24)
1093                                 DrawQ_Pic(sbar_x,sbar_y,sb_sbar_overlay->name,0,0,1,1,1,1,DRAWFLAG_MODULATE);
1094                 }
1095
1096                 //if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1097                 //      Sbar_MiniDeathmatchOverlay (0, 17);
1098         }
1099         else if (gamemode == GAME_ZYMOTIC)
1100         {
1101 #if 1
1102                 float scale = 64.0f / 256.0f;
1103                 float kickoffset[3];
1104                 VectorClear(kickoffset);
1105                 if (v_dmg_time > 0)
1106                 {
1107                         kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1108                         kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1109                 }
1110                 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1111                 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1112                 // left1 16, 48 : 126 -66
1113                 // left2 16, 128 : 196 -66
1114                 // right 176, 48 : 196 -136
1115                 Sbar_DrawGauge(sbar_x +  16 * scale, sbar_y +  48 * scale, zymsb_crosshair_left1->name, 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);
1116                 Sbar_DrawGauge(sbar_x +  16 * scale, sbar_y + 128 * scale, zymsb_crosshair_left2->name, 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);
1117                 Sbar_DrawGauge(sbar_x + 176 * scale, sbar_y +  48 * scale, zymsb_crosshair_right->name, 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);
1118                 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center->name, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1119 #else
1120                 float scale = 128.0f / 256.0f;
1121                 float healthstart, healthheight, healthstarttc, healthendtc;
1122                 float shieldstart, shieldheight, shieldstarttc, shieldendtc;
1123                 float ammostart, ammoheight, ammostarttc, ammoendtc;
1124                 float clipstart, clipheight, clipstarttc, clipendtc;
1125                 float kickoffset[3], offset;
1126                 VectorClear(kickoffset);
1127                 if (v_dmg_time > 0)
1128                 {
1129                         kickoffset[0] = (v_dmg_time/v_kicktime.value*v_dmg_roll) * 10 * scale;
1130                         kickoffset[1] = (v_dmg_time/v_kicktime.value*v_dmg_pitch) * 10 * scale;
1131                 }
1132                 sbar_x = (vid_conwidth.integer - 256 * scale)/2 + kickoffset[0];
1133                 sbar_y = (vid_conheight.integer - 256 * scale)/2 + kickoffset[1];
1134                 offset = 0; // TODO: offset should be controlled by recoil (question: how to detect firing?)
1135                 DrawQ_SuperPic(sbar_x +  120           * scale, sbar_y + ( 88 - offset) * scale, zymsb_crosshair_line->name, 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);
1136                 DrawQ_SuperPic(sbar_x + (132 + offset) * scale, sbar_y + 120            * scale, zymsb_crosshair_line->name, 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);
1137                 DrawQ_SuperPic(sbar_x +  120           * scale, sbar_y + (132 + offset) * scale, zymsb_crosshair_line->name, 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);
1138                 DrawQ_SuperPic(sbar_x + ( 88 - offset) * scale, sbar_y + 120            * scale, zymsb_crosshair_line->name, 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);
1139                 healthheight = cl.stats[STAT_HEALTH] * (152.0f / 300.0f);
1140                 shieldheight = cl.stats[STAT_ARMOR] * (152.0f / 300.0f);
1141                 healthstart = 204 - healthheight;
1142                 shieldstart = healthstart - shieldheight;
1143                 healthstarttc = healthstart * (1.0f / 256.0f);
1144                 healthendtc = (healthstart + healthheight) * (1.0f / 256.0f);
1145                 shieldstarttc = shieldstart * (1.0f / 256.0f);
1146                 shieldendtc = (shieldstart + shieldheight) * (1.0f / 256.0f);
1147                 ammoheight = cl.stats[STAT_SHELLS] * (62.0f / 200.0f);
1148                 ammostart = 114 - ammoheight;
1149                 ammostarttc = ammostart * (1.0f / 256.0f);
1150                 ammoendtc = (ammostart + ammoheight) * (1.0f / 256.0f);
1151                 clipheight = cl.stats[STAT_AMMO] * (122.0f / 200.0f);
1152                 clipstart = 190 - clipheight;
1153                 clipstarttc = clipstart * (1.0f / 256.0f);
1154                 clipendtc = (clipstart + clipheight) * (1.0f / 256.0f);
1155                 if (healthheight > 0) DrawQ_SuperPic(sbar_x + 0 * scale, sbar_y + healthstart * scale, zymsb_crosshair_health->name, 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);
1156                 if (shieldheight > 0) DrawQ_SuperPic(sbar_x + 0 * scale, sbar_y + shieldstart * scale, zymsb_crosshair_health->name, 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);
1157                 if (ammoheight > 0)   DrawQ_SuperPic(sbar_x + 0 * scale, sbar_y + ammostart   * scale, zymsb_crosshair_ammo->name,   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);
1158                 if (clipheight > 0)   DrawQ_SuperPic(sbar_x + 0 * scale, sbar_y + clipstart   * scale, zymsb_crosshair_clip->name,   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);
1159                 DrawQ_Pic(sbar_x + 0 * scale, sbar_y + 0 * scale, zymsb_crosshair_background->name, 256 * scale, 256 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1160                 DrawQ_Pic(sbar_x + 120 * scale, sbar_y + 120 * scale, zymsb_crosshair_center->name, 16 * scale, 16 * scale, 1, 1, 1, 1, DRAWFLAG_NORMAL);
1161 #endif
1162         }
1163         else // Quake and others
1164         {
1165                 sbar_y = vid_conheight.integer - SBAR_HEIGHT;
1166                 if (cl.gametype == GAME_DEATHMATCH && gamemode != GAME_TRANSFUSION)
1167                         sbar_x = 0;
1168                 else
1169                         sbar_x = (vid_conwidth.integer - 320)/2;
1170
1171                 if (sb_lines > 24)
1172                 {
1173                         if (gamemode != GAME_GOODVSBAD2)
1174                                 Sbar_DrawInventory ();
1175                         if (!cl.islocalgame && gamemode != GAME_TRANSFUSION)
1176                                 Sbar_DrawFrags ();
1177                 }
1178
1179                 if (sb_showscores || (cl.stats[STAT_HEALTH] <= 0 && cl_deathscoreboard.integer))
1180                 {
1181                         if (gamemode != GAME_GOODVSBAD2)
1182                                 Sbar_DrawAlphaPic (0, 0, sb_scorebar, sbar_alpha_bg.value);
1183                         Sbar_DrawScoreboard ();
1184                 }
1185                 else if (sb_lines)
1186                 {
1187                         Sbar_DrawAlphaPic (0, 0, sb_sbar, sbar_alpha_bg.value);
1188
1189                         // keys (hipnotic only)
1190                         //MED 01/04/97 moved keys here so they would not be overwritten
1191                         if (gamemode == GAME_HIPNOTIC)
1192                         {
1193                                 if (cl.stats[STAT_ITEMS] & IT_KEY1)
1194                                         Sbar_DrawPic (209, 3, sb_items[0]);
1195                                 if (cl.stats[STAT_ITEMS] & IT_KEY2)
1196                                         Sbar_DrawPic (209, 12, sb_items[1]);
1197                         }
1198                         // armor
1199                         if (gamemode != GAME_GOODVSBAD2)
1200                         {
1201                                 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY)
1202                                 {
1203                                         Sbar_DrawNum (24, 0, 666, 3, 1);
1204                                         Sbar_DrawPic (0, 0, sb_disc);
1205                                 }
1206                                 else
1207                                 {
1208                                         if (gamemode == GAME_ROGUE)
1209                                         {
1210                                                 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1211                                                 if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
1212                                                         Sbar_DrawPic (0, 0, sb_armor[2]);
1213                                                 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
1214                                                         Sbar_DrawPic (0, 0, sb_armor[1]);
1215                                                 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
1216                                                         Sbar_DrawPic (0, 0, sb_armor[0]);
1217                                         }
1218                                         else
1219                                         {
1220                                                 Sbar_DrawNum (24, 0, cl.stats[STAT_ARMOR], 3, cl.stats[STAT_ARMOR] <= 25);
1221                                                 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
1222                                                         Sbar_DrawPic (0, 0, sb_armor[2]);
1223                                                 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
1224                                                         Sbar_DrawPic (0, 0, sb_armor[1]);
1225                                                 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
1226                                                         Sbar_DrawPic (0, 0, sb_armor[0]);
1227                                         }
1228                                 }
1229                         }
1230
1231                         // face
1232                         Sbar_DrawFace ();
1233
1234                         // health
1235                         Sbar_DrawNum (154, 0, cl.stats[STAT_HEALTH], 3, cl.stats[STAT_HEALTH] <= 25);
1236
1237                         // ammo icon
1238                         if (gamemode == GAME_ROGUE)
1239                         {
1240                                 if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
1241                                         Sbar_DrawPic (224, 0, sb_ammo[0]);
1242                                 else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
1243                                         Sbar_DrawPic (224, 0, sb_ammo[1]);
1244                                 else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
1245                                         Sbar_DrawPic (224, 0, sb_ammo[2]);
1246                                 else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
1247                                         Sbar_DrawPic (224, 0, sb_ammo[3]);
1248                                 else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
1249                                         Sbar_DrawPic (224, 0, rsb_ammo[0]);
1250                                 else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
1251                                         Sbar_DrawPic (224, 0, rsb_ammo[1]);
1252                                 else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
1253                                         Sbar_DrawPic (224, 0, rsb_ammo[2]);
1254                         }
1255                         else
1256                         {
1257                                 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
1258                                         Sbar_DrawPic (224, 0, sb_ammo[0]);
1259                                 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
1260                                         Sbar_DrawPic (224, 0, sb_ammo[1]);
1261                                 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
1262                                         Sbar_DrawPic (224, 0, sb_ammo[2]);
1263                                 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
1264                                         Sbar_DrawPic (224, 0, sb_ammo[3]);
1265                         }
1266
1267                         Sbar_DrawNum (248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
1268
1269                 }
1270
1271                 if (vid_conwidth.integer > 320 && cl.gametype == GAME_DEATHMATCH)
1272                 {
1273                         if (gamemode == GAME_TRANSFUSION)
1274                                 Sbar_MiniDeathmatchOverlay (0, 0);
1275                         else
1276                                 Sbar_MiniDeathmatchOverlay (324, vid_conheight.integer - sb_lines);
1277                 }
1278         }
1279
1280         Sbar_ShowFPS();
1281
1282         R_Draw2DCrosshair();
1283
1284         if (cl_prydoncursor.integer)
1285                 DrawQ_Pic((cl.cmd.cursor_screen[0] + 1) * 0.5 * vid_conwidth.integer, (cl.cmd.cursor_screen[1] + 1) * 0.5 * vid_conheight.integer, va("gfx/prydoncursor%03i", cl_prydoncursor.integer), 0, 0, 1, 1, 1, 1, 0);
1286 }
1287
1288 //=============================================================================
1289
1290 /*
1291 ==================
1292 Sbar_DeathmatchOverlay
1293
1294 ==================
1295 */
1296 float Sbar_PrintScoreboardItem(scoreboard_t *s, float x, float y)
1297 {
1298         unsigned char *c;
1299         // draw colors behind score
1300         c = (unsigned char *)&palette_complete[(s->colors & 0xf0) + 8];
1301         DrawQ_Fill(x + 8, y+1, 32, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
1302         c = (unsigned char *)&palette_complete[((s->colors & 15)<<4) + 8];
1303         DrawQ_Fill(x + 8, y+4, 32, 3, c[0] * (1.0f / 255.0f), c[1] * (1.0f / 255.0f), c[2] * (1.0f / 255.0f), c[3] * (1.0f / 255.0f) * sbar_alpha_fg.value, 0);
1304         // print the text
1305         //DrawQ_String(x, y, va("%c%4i %s", (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1306         // FIXME: use a constant for this color tag instead
1307         DrawQ_ColoredString(x, y, va("%c%4i %s" STRING_COLOR_DEFAULT_STR, (s - cl.scores) == cl.playerentity - 1 ? 13 : ' ', (int) s->frags, s->name), 0, 8, 8, 1, 1, 1, 1 * sbar_alpha_fg.value, 0, NULL );
1308         return 8;
1309 }
1310
1311 void Sbar_DeathmatchOverlay (void)
1312 {
1313         int i, x, y;
1314         cachepic_t *pic;
1315
1316         pic = Draw_CachePic ("gfx/ranking", true);
1317         DrawQ_Pic ((vid_conwidth.integer - pic->width)/2, 8, "gfx/ranking", 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1318
1319         // scores
1320         Sbar_SortFrags ();
1321         // draw the text
1322         x = (vid_conwidth.integer - (6 + 15) * 8) / 2;
1323         y = 40;
1324         for (i = 0;i < scoreboardlines && y < vid_conheight.integer;i++)
1325                 y += Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1326 }
1327
1328 /*
1329 ==================
1330 Sbar_DeathmatchOverlay
1331
1332 ==================
1333 */
1334 void Sbar_MiniDeathmatchOverlay (int x, int y)
1335 {
1336         int i, numlines;
1337
1338         // decide where to print
1339         if (gamemode == GAME_TRANSFUSION)
1340                 numlines = (vid_conwidth.integer - x + 127) / 128;
1341         else
1342                 numlines = (vid_conheight.integer - y + 7) / 8;
1343
1344         // give up if there isn't room
1345         if (x >= vid_conwidth.integer || y >= vid_conheight.integer || numlines < 1)
1346                 return;
1347
1348         // scores
1349         Sbar_SortFrags ();
1350
1351         //find us
1352         for (i = 0; i < scoreboardlines; i++)
1353                 if (fragsort[i] == cl.playerentity - 1)
1354                         break;
1355
1356         // figure out start
1357         i -= numlines/2;
1358         i = min(i, scoreboardlines - numlines);
1359         i = max(i, 0);
1360
1361         if (gamemode == GAME_TRANSFUSION)
1362         {
1363                 for (;i < scoreboardlines && x < vid_conwidth.integer;i++)
1364                         x += 128 + Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1365         }
1366         else
1367         {
1368                 for (;i < scoreboardlines && y < vid_conheight.integer;i++)
1369                         y += Sbar_PrintScoreboardItem(cl.scores + fragsort[i], x, y);
1370         }
1371 }
1372
1373 /*
1374 ==================
1375 Sbar_IntermissionOverlay
1376
1377 ==================
1378 */
1379 void Sbar_IntermissionOverlay (void)
1380 {
1381         int             dig;
1382         int             num;
1383
1384         if (cl.gametype == GAME_DEATHMATCH)
1385         {
1386                 Sbar_DeathmatchOverlay ();
1387                 return;
1388         }
1389
1390         sbar_x = (vid_conwidth.integer - 320) >> 1;
1391         sbar_y = (vid_conheight.integer - 200) >> 1;
1392
1393         DrawQ_Pic (sbar_x + 64, sbar_y + 24, "gfx/complete", 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1394         DrawQ_Pic (sbar_x + 0, sbar_y + 56, "gfx/inter", 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1395
1396 // time
1397         dig = cl.completed_time/60;
1398         Sbar_DrawNum (160, 64, dig, 3, 0);
1399         num = cl.completed_time - dig*60;
1400         if (gamemode != GAME_NEXUIZ)
1401                 Sbar_DrawPic (234,64,sb_colon);
1402         Sbar_DrawPic (246,64,sb_nums[0][num/10]);
1403         Sbar_DrawPic (266,64,sb_nums[0][num%10]);
1404
1405         Sbar_DrawNum (160, 104, cl.stats[STAT_SECRETS], 3, 0);
1406         if (gamemode != GAME_NEXUIZ)
1407                 Sbar_DrawPic (232, 104, sb_slash);
1408         Sbar_DrawNum (240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1409
1410         Sbar_DrawNum (160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1411         if (gamemode != GAME_NEXUIZ)
1412                 Sbar_DrawPic (232, 144, sb_slash);
1413         Sbar_DrawNum (240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1414
1415 }
1416
1417
1418 /*
1419 ==================
1420 Sbar_FinaleOverlay
1421
1422 ==================
1423 */
1424 void Sbar_FinaleOverlay (void)
1425 {
1426         cachepic_t      *pic;
1427
1428         pic = Draw_CachePic ("gfx/finale", true);
1429         DrawQ_Pic((vid_conwidth.integer - pic->width)/2, 16, "gfx/finale", 0, 0, 1, 1, 1, 1 * sbar_alpha_fg.value, 0);
1430 }
1431