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