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