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