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