1 /*
2 sbar.c
3
4 Status bar
5
6 Copyright (C) 1996-1997 Id Software, Inc.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
17 See the GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to:
21
22 Free Software Foundation, Inc.
23 59 Temple Place - Suite 330
24 Boston, MA 02111-1307, USA
25
26 */
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #ifdef HAVE_STRING_H
32 # include <string.h>
33 #endif
34 #ifdef HAVE_STRINGS_H
35 # include <strings.h>
36 #endif
37
38 #include <time.h>
39
40 #include "QF/cmd.h"
41 #include "QF/console.h"
42 #include "QF/cvar.h"
43 #include "QF/draw.h"
44 #include "QF/dstring.h"
45 #include "QF/gib.h"
46 #include "QF/screen.h"
47 #include "QF/sys.h"
48 #include "QF/va.h"
49 #include "QF/vid.h"
50 #include "QF/view.h"
51 #include "QF/wad.h"
52
53 #include "QF/plugin/console.h"
54 #include "QF/plugin/vid_render.h"
55
56 #include "client.h"
57 #include "compat.h"
58 #include "game.h"
59 #include "sbar.h"
60 #include "server.h"
61
62 int sb_updates; // if >= vid.numpages, no update needed
63
64 #define STAT_MINUS 10 // num frame for '-' stats digit
65
66 qpic_t *sb_nums[2][11];
67 qpic_t *sb_colon, *sb_slash;
68 qpic_t *sb_ibar;
69 qpic_t *sb_sbar;
70 qpic_t *sb_scorebar;
71
72 qpic_t *sb_weapons[7][8]; // 0 is active, 1 is owned, 2-5 are flashes
73 qpic_t *sb_ammo[4];
74 qpic_t *sb_sigil[4];
75 qpic_t *sb_armor[3];
76 qpic_t *sb_items[32];
77
78 qpic_t *sb_faces[7][2]; // 0 is gibbed, 1 is dead, 2-6 are alive
79 // 0 is static, 1 is temporary animation
80 qpic_t *sb_face_invis;
81 qpic_t *sb_face_quad;
82 qpic_t *sb_face_invuln;
83 qpic_t *sb_face_invis_invuln;
84
85 qboolean sb_showscores;
86
87 int sb_lines; // scan lines to draw
88 qboolean hudswap;
89
90 qpic_t *rsb_invbar[2];
91 qpic_t *rsb_weapons[5];
92 qpic_t *rsb_items[2];
93 qpic_t *rsb_ammo[3];
94 qpic_t *rsb_teambord; // PGM 01/19/97 - team color border
95
96 // MED 01/04/97 added two more weapons + 3
97 // alternates for grenade launcher
98 qpic_t *hsb_weapons[7][5]; // 0 is active, 1 is owned, 2-5 are flashes
99
100 // MED 01/04/97 added array to simplify
101 // weapon parsing
102 int hipweapons[4] =
103 { HIT_LASER_CANNON_BIT, HIT_MJOLNIR_BIT, 4, HIT_PROXIMITY_GUN_BIT };
104 qpic_t *hsb_items[2]; // MED 01/04/97 added hipnotic items array
105
106 cvar_t *hud_sbar;
107 cvar_t *hud_swap;
108 cvar_t *hud_scoreboard_gravity;
109 cvar_t *scr_centertime;
110 cvar_t *scr_printspeed;
111
112 static view_t *sbar_view;
113 static view_t *sbar_inventory_view;
114 static view_t *sbar_frags_view;
115
116 static view_t *hud_view;
117 static view_t *hud_inventory_view;
118 static view_t *hud_armament_view;
119 static view_t *hud_frags_view;
120
121 static view_t *overlay_view;
122 static view_t *stuff_view;
123 static view_t *main_view;
124
125 static void
hud_swap_f(cvar_t * var)126 hud_swap_f (cvar_t *var)
127 {
128 hudswap = var->int_val;
129 if (var->int_val) {
130 hud_armament_view->gravity = grav_southwest;
131 hud_armament_view->children[0]->gravity = grav_northwest;
132 hud_armament_view->children[1]->gravity = grav_southeast;
133 stuff_view->gravity = grav_southeast;
134 } else {
135 hud_armament_view->gravity = grav_southeast;
136 hud_armament_view->children[0]->gravity = grav_northeast;
137 hud_armament_view->children[1]->gravity = grav_southwest;
138 stuff_view->gravity = grav_southwest;
139 }
140 view_move (hud_armament_view, hud_armament_view->xpos,
141 hud_armament_view->ypos);
142 view_move (stuff_view, stuff_view->xpos, stuff_view->ypos);
143 }
144
145 static void
hud_scoreboard_gravity_f(cvar_t * var)146 hud_scoreboard_gravity_f (cvar_t *var)
147 {
148 grav_t grav;
149
150 if (strequal (var->string, "center"))
151 grav = grav_center;
152 else if (strequal (var->string, "northwest"))
153 grav = grav_northwest;
154 else if (strequal (var->string, "north"))
155 grav = grav_north;
156 else if (strequal (var->string, "northeast"))
157 grav = grav_northeast;
158 else if (strequal (var->string, "west"))
159 grav = grav_west;
160 else if (strequal (var->string, "east"))
161 grav = grav_east;
162 else if (strequal (var->string, "southwest"))
163 grav = grav_southwest;
164 else if (strequal (var->string, "south"))
165 grav = grav_south;
166 else if (strequal (var->string, "southeast"))
167 grav = grav_southeast;
168 else
169 grav = grav_center;
170 overlay_view->gravity = grav;
171 view_move (overlay_view, overlay_view->xpos, overlay_view->ypos);
172 }
173
174 static void
calc_sb_lines(cvar_t * var)175 calc_sb_lines (cvar_t *var)
176 {
177 int stuff_y;
178
179 if (var->int_val >= 120) {
180 sb_lines = 0;
181 stuff_y = 0;
182 } else if (var->int_val >= 110) {
183 sb_lines = 24;
184 sbar_inventory_view->visible = 0;
185 hud_inventory_view->visible = 0;
186 hud_armament_view->visible = 0;
187 stuff_y = 32;
188 } else {
189 sb_lines = 48;
190 sbar_inventory_view->visible = 1;
191 hud_inventory_view->visible = 1;
192 hud_armament_view->visible = 1;
193 stuff_y = 48;
194 }
195 if (sb_lines) {
196 sbar_view->visible = 1;
197 hud_view->visible = 1;
198 view_resize (sbar_view, sbar_view->xlen, sb_lines);
199 view_resize (hud_view, hud_view->xlen, sb_lines);
200 } else {
201 sbar_view->visible = 0;
202 hud_view->visible = 0;
203 }
204 view_move (stuff_view, stuff_view->xpos, stuff_y);
205 }
206
207 static void
hud_sbar_f(cvar_t * var)208 hud_sbar_f (cvar_t *var)
209 {
210 r_data->vid->recalc_refdef = true;
211 if (r_data->scr_viewsize)
212 calc_sb_lines (r_data->scr_viewsize);
213 r_data->lineadj = var->int_val ? sb_lines : 0;
214 if (var->int_val) {
215 view_remove (main_view, main_view->children[0]);
216 view_insert (main_view, sbar_view, 0);
217 } else {
218 view_remove (main_view, main_view->children[0]);
219 view_insert (main_view, hud_view, 0);
220 }
221 }
222
223 static void
viewsize_f(cvar_t * var)224 viewsize_f (cvar_t *var)
225 {
226 calc_sb_lines (var);
227 if (hud_sbar)
228 r_data->lineadj = hud_sbar->int_val ? sb_lines : 0;
229 }
230
231
232 static int
Sbar_ColorForMap(int m)233 Sbar_ColorForMap (int m)
234 {
235 return (bound (0, m, 13) * 16) + 8;
236 }
237
238 static void
Sbar_ShowScores(void)239 Sbar_ShowScores (void)
240 {
241 if (sb_showscores)
242 return;
243
244 sb_showscores = true;
245 sb_updates = 0;
246 }
247
248 static void
Sbar_DontShowScores(void)249 Sbar_DontShowScores (void)
250 {
251 sb_showscores = false;
252 sb_updates = 0;
253 }
254
255 void
Sbar_Changed(void)256 Sbar_Changed (void)
257 {
258 sb_updates = 0; // update next frame
259 }
260
261 static void
draw_pic(view_t * view,int x,int y,qpic_t * pic)262 draw_pic (view_t *view, int x, int y, qpic_t *pic)
263 {
264 r_funcs->Draw_Pic (view->xabs + x, view->yabs + y, pic);
265 }
266
267 static inline void
draw_cachepic(view_t * view,int x,int y,const char * name,int cent)268 draw_cachepic (view_t *view, int x, int y, const char *name, int cent)
269 {
270 qpic_t *pic = r_funcs->Draw_CachePic (name, true);
271 if (cent)
272 x += (view->xlen - pic->width) / 2;
273 r_funcs->Draw_Pic (view->xabs + x, view->yabs + y, pic);
274 }
275
276 static inline void
draw_subpic(view_t * view,int x,int y,qpic_t * pic,int srcx,int srcy,int width,int height)277 draw_subpic (view_t *view, int x, int y, qpic_t *pic,
278 int srcx, int srcy, int width, int height)
279 {
280 r_funcs->Draw_SubPic (view->xabs + x, view->yabs + y, pic,
281 srcx, srcy, width, height);
282 }
283
284 static inline void
draw_transpic(view_t * view,int x,int y,qpic_t * pic)285 draw_transpic (view_t *view, int x, int y, qpic_t *pic)
286 {
287 r_funcs->Draw_Pic (view->xabs + x, view->yabs + y, pic);
288 }
289
290
291 // drawing routines are reletive to the status bar location
292
293 static inline void
draw_character(view_t * view,int x,int y,int c)294 draw_character (view_t *view, int x, int y, int c)
295 {
296 r_funcs->Draw_Character (view->xabs + x, view->yabs + y, c);
297 }
298
299 static inline void
draw_string(view_t * view,int x,int y,const char * str)300 draw_string (view_t *view, int x, int y, const char *str)
301 {
302 r_funcs->Draw_String (view->xabs + x, view->yabs + y, str);
303 }
304
305 static inline void
draw_altstring(view_t * view,int x,int y,const char * str)306 draw_altstring (view_t *view, int x, int y, const char *str)
307 {
308 r_funcs->Draw_AltString (view->xabs + x, view->yabs + y, str);
309 }
310
311 static inline void
draw_nstring(view_t * view,int x,int y,const char * str,int n)312 draw_nstring (view_t *view, int x, int y, const char *str, int n)
313 {
314 r_funcs->Draw_nString (view->xabs + x, view->yabs + y, str, n);
315 }
316
317 static inline void
draw_fill(view_t * view,int x,int y,int w,int h,int col)318 draw_fill (view_t *view, int x, int y, int w, int h, int col)
319 {
320 r_funcs->Draw_Fill (view->xabs + x, view->yabs + y, w, h, col);
321 }
322
323 static void
draw_num(view_t * view,int x,int y,int num,int digits,int color)324 draw_num (view_t *view, int x, int y, int num, int digits, int color)
325 {
326 char str[12];
327 char *ptr;
328 int l, frame;
329
330 if (num > 999999999)
331 num = 999999999;
332
333 l = snprintf (str, sizeof (str), "%d", num);
334 ptr = str;
335 if (l > digits)
336 ptr += (l - digits);
337 if (l < digits)
338 x += (digits - l) * 24;
339
340 while (*ptr) {
341 if (*ptr == '-')
342 frame = STAT_MINUS;
343 else
344 frame = *ptr - '0';
345
346 draw_transpic (view, x, y, sb_nums[color][frame]);
347 x += 24;
348 ptr++;
349 }
350 }
351
352 static inline void
draw_smallnum(view_t * view,int x,int y,int n,int packed,int colored)353 draw_smallnum (view_t *view, int x, int y, int n, int packed, int colored)
354 {
355 char num[4];
356
357 packed = packed != 0; // ensure 0 or 1
358
359 if (n > 999)
360 n = 999;
361
362 snprintf (num, sizeof (num), "%3d", n);
363 if (colored) {
364 if (num[0] != ' ')
365 num[0] = 18 + num[0] - '0';
366 if (num[1] != ' ')
367 num[1] = 18 + num[1] - '0';
368 if (num[2] != ' ')
369 num[2] = 18 + num[2] - '0';
370 }
371 draw_character (view, x + packed, y, num[0]);
372 draw_character (view, x + 8, y, num[1]);
373 draw_character (view, x + 16 - packed, y, num[2]);
374 }
375
376 static void
draw_tile(view_t * view)377 draw_tile (view_t *view)
378 {
379 r_funcs->Draw_TileClear (view->xabs, view->yabs, view->xlen, view->ylen);
380 }
381
382 static void
draw_ammo_sbar(view_t * view)383 draw_ammo_sbar (view_t *view)
384 {
385 int i, count;
386
387 // ammo counts
388 for (i = 0; i < 4; i++) {
389 count = cl.stats[STAT_SHELLS + i];
390 draw_smallnum (view, (6 * i + 1) * 8 + 2, 0, count, 0, 1);
391 }
392 }
393
394 static void
draw_ammo_hud(view_t * view)395 draw_ammo_hud (view_t *view)
396 {
397 int i, count;
398
399 // ammo counts
400 for (i = 0; i < 4; i++) {
401 count = cl.stats[STAT_SHELLS + i];
402 draw_subpic (view, 0, i * 11, sb_ibar, 3 + (i * 48), 0, 42, 11);
403 draw_smallnum (view, 7, i * 11, count, 0, 1);
404 }
405 }
406
407 static int
calc_flashon(float time,int mask)408 calc_flashon (float time, int mask)
409 {
410 int flashon;
411
412 flashon = (int) ((cl.time - time) * 10);
413 if (flashon < 0)
414 flashon = 0;
415 if (flashon >= 10) {
416 if (cl.stats[STAT_ACTIVEWEAPON] == mask)
417 flashon = 1;
418 else
419 flashon = 0;
420 } else
421 flashon = (flashon % 5) + 2;
422 return flashon;
423 }
424
425 static void
draw_weapons_sbar(view_t * view)426 draw_weapons_sbar (view_t *view)
427 {
428 int flashon, i;
429
430 for (i = 0; i < 7; i++) {
431 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN << i)) {
432 flashon = calc_flashon (cl.item_gettime[i], IT_SHOTGUN << i);
433 draw_pic (view, i * 24, 0, sb_weapons[flashon][i]);
434 if (flashon > 1)
435 sb_updates = 0; // force update to remove flash
436 }
437 }
438 }
439
440 static void
draw_weapons_hud(view_t * view)441 draw_weapons_hud (view_t *view)
442 {
443 int flashon, i, x = 0;
444
445 if (view->parent->gravity == grav_southeast)
446 x = view->xlen - 24;
447
448 for (i = r_data->vid->conheight < 204; i < 7; i++) {
449 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN << i)) {
450 flashon = calc_flashon (cl.item_gettime[i], IT_SHOTGUN << i);
451 draw_subpic (view, x, i * 16, sb_weapons[flashon][i], 0, 0, 24, 16);
452 if (flashon > 1)
453 sb_updates = 0; // force update to remove flash
454 }
455 }
456 }
457
458 static void
draw_items(view_t * view)459 draw_items (view_t *view)
460 {
461 float time;
462 int flashon = 0, i;
463
464 for (i = 0; i < 6; i++) {
465 if (cl.stats[STAT_ITEMS] & (1 << (17 + i))) {
466 time = cl.item_gettime[17 + i];
467 if (time && time > cl.time - 2 && flashon) { // Flash frame
468 sb_updates = 0;
469 } else {
470 draw_pic (view, i * 16, 0, sb_items[i]);
471 }
472 if (time && time > cl.time - 2)
473 sb_updates = 0;
474 }
475 }
476 }
477
478 static void
draw_sigils(view_t * view)479 draw_sigils (view_t *view)
480 {
481 float time;
482 int flashon = 0, i;
483
484 for (i = 0; i < 4; i++) {
485 if (cl.stats[STAT_ITEMS] & (1 << (28 + i))) {
486 time = cl.item_gettime[28 + i];
487 if (time && time > cl.time - 2 && flashon) { // flash frame
488 sb_updates = 0;
489 } else {
490 draw_pic (view, i * 8, 0, sb_sigil[i]);
491 }
492 if (time && time > cl.time - 2)
493 sb_updates = 0;
494 }
495 }
496 }
497
498 static void
draw_inventory_sbar(view_t * view)499 draw_inventory_sbar (view_t *view)
500 {
501 draw_pic (view, 0, 0, sb_ibar);
502 view_draw (view);
503 }
504
505
506 int fragsort[MAX_SCOREBOARD];
507 char scoreboardtext[MAX_SCOREBOARD][20];
508 int scoreboardtop[MAX_SCOREBOARD];
509 int scoreboardbottom[MAX_SCOREBOARD];
510 int scoreboardcount[MAX_SCOREBOARD];
511 int scoreboardlines;
512
513
514 static void
Sbar_SortFrags(void)515 Sbar_SortFrags (void)
516 {
517 int i, j, k;
518
519 // sort by frags
520 scoreboardlines = 0;
521 for (i = 0; i < cl.maxclients; i++) {
522 if (cl.scores[i].name->value[0]) {
523 fragsort[scoreboardlines] = i;
524 scoreboardlines++;
525 }
526 }
527
528 for (i = 0; i < scoreboardlines; i++) {
529 for (j = 0; j < (scoreboardlines - 1 - i); j++) {
530 if (cl.scores[fragsort[j]].frags < cl.scores[fragsort[j + 1]].frags) {
531 k = fragsort[j];
532 fragsort[j] = fragsort[j + 1];
533 fragsort[j + 1] = k;
534 }
535 }
536 }
537 }
538
539
540 static void
draw_solo(view_t * view)541 draw_solo (view_t *view)
542 {
543 char str[80];
544 int minutes, seconds, tens, units;
545 int l;
546
547 draw_pic (view, 0, 0, sb_scorebar);
548
549 snprintf (str, sizeof (str), "Monsters:%3i /%3i", cl.stats[STAT_MONSTERS],
550 cl.stats[STAT_TOTALMONSTERS]);
551 draw_string (view, 8, 4, str);
552
553 snprintf (str, sizeof (str), "Secrets :%3i /%3i", cl.stats[STAT_SECRETS],
554 cl.stats[STAT_TOTALSECRETS]);
555 draw_string (view, 8, 12, str);
556
557 // time
558 minutes = cl.time / 60;
559 seconds = cl.time - (60 * minutes);
560 tens = seconds / 10;
561 units = seconds - (10 * tens);
562 snprintf (str, sizeof (str), "Time :%3i:%i%i", minutes, tens, units);
563 draw_string (view, 184, 4, str);
564
565 // draw level name
566 l = strlen (cl.levelname);
567 l = 232 - l * 4;
568 draw_string (view, max (l, 152), 12, cl.levelname);
569 }
570
571 static void
draw_frags(view_t * view)572 draw_frags (view_t *view)
573 {
574 int i, k, l, p = -1;
575 int top, bottom;
576 int x;
577 scoreboard_t *s;
578
579 if (cl.maxclients == 1)
580 return;
581
582 Sbar_SortFrags ();
583
584 // draw the text
585 l = scoreboardlines <= 4 ? scoreboardlines : 4;
586
587 x = 0;
588
589 for (i = 0; i < l; i++) {
590 k = fragsort[i];
591 s = &cl.scores[k];
592 if (!s->name->value[0])
593 continue;
594
595 // draw background
596 top = Sbar_ColorForMap (s->topcolor);
597 bottom = Sbar_ColorForMap (s->bottomcolor);
598
599 draw_fill (view, x + 4, 1, 28, 4, top);
600 draw_fill (view, x + 4, 5, 28, 3, bottom);
601
602 draw_smallnum (view, x + 6, 0, s->frags, 0, 0);
603
604 if (k == cl.viewentity - 1)
605 p = i;
606
607 x += 32;
608 }
609 if (p != -1) {
610 draw_character (view, p * 32, 0, 16);
611 draw_character (view, p * 32 + 26, 0, 17);
612 }
613 }
614
615 static void
draw_face(view_t * view)616 draw_face (view_t *view)
617 {
618 int f, anim;
619
620 if ((cl.stats[STAT_ITEMS] & (IT_INVISIBILITY | IT_INVULNERABILITY))
621 == (IT_INVISIBILITY | IT_INVULNERABILITY)) {
622 draw_pic (view, 112, 0, sb_face_invis_invuln);
623 return;
624 }
625 if (cl.stats[STAT_ITEMS] & IT_QUAD) {
626 draw_pic (view, 112, 0, sb_face_quad);
627 return;
628 }
629 if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY) {
630 draw_pic (view, 112, 0, sb_face_invis);
631 return;
632 }
633 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY) {
634 draw_pic (view, 112, 0, sb_face_invuln);
635 return;
636 }
637
638 if (cl.stats[STAT_HEALTH] >= 100)
639 f = 4;
640 else
641 f = cl.stats[STAT_HEALTH] / 20;
642
643 if (cl.time <= cl.faceanimtime) {
644 anim = 1;
645 sb_updates = 0; // make sure the anim gets drawn over
646 } else
647 anim = 0;
648 draw_pic (view, 112, 0, sb_faces[f][anim]);
649 }
650
651 static void
draw_status_bar(view_t * view)652 draw_status_bar (view_t *view)
653 {
654 draw_pic (view, 0, 0, sb_sbar);
655 }
656
657 static inline void
draw_armor(view_t * view)658 draw_armor (view_t *view)
659 {
660 if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY) {
661 draw_num (view, 24, 0, 666, 3, 1);
662 } else {
663 draw_num (view, 24, 0, cl.stats[STAT_ARMOR], 3,
664 cl.stats[STAT_ARMOR] <= 25);
665 if (cl.stats[STAT_ITEMS] & IT_ARMOR3)
666 draw_pic (view, 0, 0, sb_armor[2]);
667 else if (cl.stats[STAT_ITEMS] & IT_ARMOR2)
668 draw_pic (view, 0, 0, sb_armor[1]);
669 else if (cl.stats[STAT_ITEMS] & IT_ARMOR1)
670 draw_pic (view, 0, 0, sb_armor[0]);
671 }
672 }
673
674 static inline void
draw_health(view_t * view)675 draw_health (view_t *view)
676 {
677 draw_num (view, 136, 0, cl.stats[STAT_HEALTH], 3,
678 cl.stats[STAT_HEALTH] <= 25);
679 }
680
681 static inline void
draw_ammo(view_t * view)682 draw_ammo (view_t *view)
683 {
684 if (cl.stats[STAT_ITEMS] & IT_SHELLS)
685 draw_pic (view, 224, 0, sb_ammo[0]);
686 else if (cl.stats[STAT_ITEMS] & IT_NAILS)
687 draw_pic (view, 224, 0, sb_ammo[1]);
688 else if (cl.stats[STAT_ITEMS] & IT_ROCKETS)
689 draw_pic (view, 224, 0, sb_ammo[2]);
690 else if (cl.stats[STAT_ITEMS] & IT_CELLS)
691 draw_pic (view, 224, 0, sb_ammo[3]);
692
693 draw_num (view, 248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
694 }
695
696 static void
draw_status(view_t * view)697 draw_status (view_t *view)
698 {
699 if (sb_showscores || cl.stats[STAT_HEALTH] <= 0) {
700 draw_solo (view);
701 return;
702 }
703
704 draw_armor (view);
705 draw_face (view);
706 draw_health (view);
707 draw_ammo (view);
708 }
709
710 static void
draw_rogue_weapons_sbar(view_t * view)711 draw_rogue_weapons_sbar (view_t *view)
712 {
713 int i;
714
715 draw_weapons_sbar (view);
716
717 // check for powered up weapon.
718 if (cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN) {
719 for (i = 0; i < 5; i++) {
720 if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << i)) {
721 draw_pic (view, (i + 2) * 24, 0, rsb_weapons[i]);
722 }
723 }
724 }
725 }
726
727 static void
draw_rogue_weapons_hud(view_t * view)728 draw_rogue_weapons_hud (view_t *view)
729 {
730 int flashon, i, j;
731 qpic_t *pic;
732
733 for (i = r_data->vid->conheight < 204; i < 7; i++) {
734 if (cl.stats[STAT_ITEMS] & (IT_SHOTGUN << i)) {
735 flashon = calc_flashon (cl.item_gettime[i], IT_SHOTGUN << i);
736 if (i >= 2) {
737 j = i - 2;
738 if (cl.stats[STAT_ACTIVEWEAPON] == (RIT_LAVA_NAILGUN << j))
739 pic = rsb_weapons[j];
740 else
741 pic = sb_weapons[flashon][i];
742 } else {
743 pic = sb_weapons[flashon][i];
744 }
745 draw_subpic (view, 0, i * 16, pic, 0, 0, 24, 16);
746 if (flashon > 1)
747 sb_updates = 0; // force update to remove flash
748 }
749 }
750 }
751
752 static void
draw_rogue_ammo_hud(view_t * view)753 draw_rogue_ammo_hud (view_t *view)
754 {
755 int i, count;
756 qpic_t *pic;
757
758 if (cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN)
759 pic = rsb_invbar[0];
760 else
761 pic = rsb_invbar[1];
762
763 for (i = 0; i < 4; i++) {
764 count = cl.stats[STAT_SHELLS + i];
765 draw_subpic (view, 0, i * 11, pic, 3 + (i * 48), 0, 42, 11);
766 draw_smallnum (view, 7, i * 11, count, 0, 1);
767 }
768 }
769
770 static void
draw_rogue_items(view_t * view)771 draw_rogue_items (view_t *view)
772 {
773 int i;
774 float time;
775
776 draw_items (view);
777
778 for (i = 0; i < 2; i++) {
779 if (cl.stats[STAT_ITEMS] & (1 << (29 + i))) {
780 time = cl.item_gettime[29 + i];
781 draw_pic (view, 96 + i * 16, 0, rsb_items[i]);
782 if (time && time > (cl.time - 2))
783 sb_updates = 0;
784 }
785 }
786 }
787
788 static void
draw_rogue_inventory_sbar(view_t * view)789 draw_rogue_inventory_sbar (view_t *view)
790 {
791 if (cl.stats[STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN)
792 draw_pic (view, 0, 0, rsb_invbar[0]);
793 else
794 draw_pic (view, 0, 0, rsb_invbar[1]);
795
796 view_draw (view);
797 }
798
799 static void
draw_rogue_face(view_t * view)800 draw_rogue_face (view_t *view)
801 {
802 int top, bottom;
803 scoreboard_t *s;
804
805 // PGM 01/19/97 - team color drawing
806
807 s = &cl.scores[cl.viewentity - 1];
808
809 top = Sbar_ColorForMap (s->topcolor);
810 bottom = Sbar_ColorForMap (s->bottomcolor);
811
812 draw_pic (view, 112, 0, rsb_teambord);
813 draw_fill (view, 113, 3, 22, 9, top);
814 draw_fill (view, 113, 12, 22, 9, bottom);
815
816 draw_smallnum (view, 108, 3, s->frags, 1, top == 8);
817 }
818
819 static void
draw_rogue_status(view_t * view)820 draw_rogue_status (view_t *view)
821 {
822 if (sb_showscores || cl.stats[STAT_HEALTH] <= 0) {
823 draw_solo (view);
824 return;
825 }
826
827 draw_num (view, 24, 0, cl.stats[STAT_ARMOR], 3,
828 cl.stats[STAT_ARMOR] <= 25);
829 if (cl.stats[STAT_ITEMS] & RIT_ARMOR3)
830 draw_pic (view, 0, 0, sb_armor[2]);
831 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR2)
832 draw_pic (view, 0, 0, sb_armor[1]);
833 else if (cl.stats[STAT_ITEMS] & RIT_ARMOR1)
834 draw_pic (view, 0, 0, sb_armor[0]);
835
836 // PGM 03/02/97 - fixed so color swatch appears in only CTF modes
837 if (cl.maxclients != 1 && teamplay->int_val > 3 && teamplay->int_val < 7)
838 draw_rogue_face (view);
839 else
840 draw_face (view);
841
842 draw_health (view);
843
844 if (cl.stats[STAT_ITEMS] & RIT_SHELLS)
845 draw_pic (view, 224, 0, sb_ammo[0]);
846 else if (cl.stats[STAT_ITEMS] & RIT_NAILS)
847 draw_pic (view, 224, 0, sb_ammo[1]);
848 else if (cl.stats[STAT_ITEMS] & RIT_ROCKETS)
849 draw_pic (view, 224, 0, sb_ammo[2]);
850 else if (cl.stats[STAT_ITEMS] & RIT_CELLS)
851 draw_pic (view, 224, 0, sb_ammo[3]);
852 else if (cl.stats[STAT_ITEMS] & RIT_LAVA_NAILS)
853 draw_pic (view, 224, 0, rsb_ammo[0]);
854 else if (cl.stats[STAT_ITEMS] & RIT_PLASMA_AMMO)
855 draw_pic (view, 224, 0, rsb_ammo[1]);
856 else if (cl.stats[STAT_ITEMS] & RIT_MULTI_ROCKETS)
857 draw_pic (view, 224, 0, rsb_ammo[2]);
858 draw_num (view, 248, 0, cl.stats[STAT_AMMO], 3, cl.stats[STAT_AMMO] <= 10);
859 }
860
861 static void
draw_hipnotic_weapons_sbar(view_t * view)862 draw_hipnotic_weapons_sbar (view_t *view)
863 {
864 static int x[] = {0, 24, 48, 72, 96, 120, 144, 176, 200, 96};
865 static int h[] = {0, 1, 3};
866 int flashon, i;
867 qpic_t *pic;
868 int mask;
869 float time;
870
871 for (i = 0; i < 10; i++) {
872 if (i < 7) {
873 mask = IT_SHOTGUN << i;
874 time = cl.item_gettime[i];
875 } else {
876 mask = 1 << hipweapons[h[i - 7]];
877 time = cl.item_gettime[hipweapons[h[i - 7]]];
878 }
879 if (cl.stats[STAT_ITEMS] & mask) {
880 flashon = calc_flashon (time, mask);
881
882 if (i == 4 && cl.stats[STAT_ACTIVEWEAPON] == (1 << hipweapons[3]))
883 continue;
884 if (i == 9 && cl.stats[STAT_ACTIVEWEAPON] != (1 << hipweapons[3]))
885 continue;
886 if (i < 7) {
887 pic = sb_weapons[flashon][i];
888 } else {
889 pic = hsb_weapons[flashon][h[i - 7]];
890 }
891
892 draw_subpic (view, x[i], 0, pic, 0, 0, 24, 16);
893
894 if (flashon > 1)
895 sb_updates = 0; // force update to remove flash
896 }
897 }
898 }
899
900 static void
draw_hipnotic_weapons_hud(view_t * view)901 draw_hipnotic_weapons_hud (view_t *view)
902 {
903 int flashon, i;
904 static int y[] = {0, 16, 32, 48, 64, 96, 112, 128, 144, 80};
905 static int h[] = {0, 1, 3};
906 qpic_t *pic;
907 int mask;
908 float time;
909
910 for (i = 0; i < 10; i++) {
911 if (i < 7) {
912 mask = IT_SHOTGUN << i;
913 time = cl.item_gettime[i];
914 } else {
915 mask = 1 << hipweapons[h[i - 7]];
916 time = cl.item_gettime[hipweapons[h[i - 7]]];
917 }
918 if (cl.stats[STAT_ITEMS] & mask) {
919 flashon = calc_flashon (time, mask);
920
921 if (i < 7) {
922 pic = sb_weapons[flashon][i];
923 } else {
924 pic = hsb_weapons[flashon][h[i - 7]];
925 }
926
927 draw_subpic (view, 0, y[i], pic, 0, 0, 24, 16);
928
929 if (flashon > 1)
930 sb_updates = 0; // force update to remove flash
931 }
932 }
933 }
934
935 static void
draw_hipnotic_items(view_t * view)936 draw_hipnotic_items (view_t *view)
937 {
938 int i;
939 float time;
940
941 // items
942 for (i = 2; i < 6; i++) {
943 if (cl.stats[STAT_ITEMS] & (1 << (17 + i))) {
944 time = cl.item_gettime[17 + i];
945 draw_pic (view, 192 + i * 16, 0, sb_items[i]);
946 if (time && time > cl.time - 2)
947 sb_updates = 0;
948 }
949 }
950
951 // hipnotic items
952 for (i = 0; i < 2; i++) {
953 if (cl.stats[STAT_ITEMS] & (1 << (24 + i))) {
954 time = cl.item_gettime[24 + i];
955 draw_pic (view, 288 + i * 16, 0, hsb_items[i]);
956 if (time && time > (cl.time - 2))
957 sb_updates = 0;
958 }
959 }
960 }
961
962 static void
draw_hipnotic_inventory_sbar(view_t * view)963 draw_hipnotic_inventory_sbar (view_t *view)
964 {
965 draw_pic (view, 0, 0, sb_ibar);
966 view_draw (view);
967 }
968
969 static void
draw_hipnotic_status(view_t * view)970 draw_hipnotic_status (view_t *view)
971 {
972 if (sb_showscores || cl.stats[STAT_HEALTH] <= 0) {
973 draw_solo (view);
974 return;
975 }
976
977 draw_armor (view);
978 draw_face (view);
979 draw_health (view);
980 draw_ammo (view);
981
982 if (cl.stats[STAT_ITEMS] & IT_KEY1)
983 draw_pic (view, 209, 3, sb_items[0]);
984 if (cl.stats[STAT_ITEMS] & IT_KEY2)
985 draw_pic (view, 209, 12, sb_items[1]);
986 }
987
988 static void
sbar_update_vis(void)989 sbar_update_vis (void)
990 {
991 qboolean headsup;
992
993 if (r_data->scr_copyeverything)
994 Sbar_Changed ();
995
996 sbar_view->visible = 0;
997
998 headsup = !(hud_sbar->int_val || r_data->scr_viewsize->int_val < 100);
999
1000 if ((sb_updates >= r_data->vid->numpages) && !headsup)
1001 return;
1002
1003 if (con_module &&
1004 con_module->data->console->lines == r_data->vid->conheight)
1005 return; // console is full screen
1006
1007 if (cls.state == ca_active
1008 && ((cl.stats[STAT_HEALTH] <= 0) || sb_showscores))
1009 overlay_view->visible = 1;
1010 else
1011 overlay_view->visible = 0;
1012
1013 if (!sb_lines)
1014 return;
1015
1016 sbar_view->visible = 1;
1017
1018 r_data->scr_copyeverything = 1;
1019 sb_updates++;
1020 }
1021
1022 void
Sbar_Draw(void)1023 Sbar_Draw (void)
1024 {
1025 sbar_update_vis ();
1026 main_view->draw (main_view);
1027 }
1028
1029 static void
Sbar_DeathmatchOverlay(view_t * view)1030 Sbar_DeathmatchOverlay (view_t *view)
1031 {
1032 int i, k, l;
1033 int top, bottom;
1034 int x, y;
1035 scoreboard_t *s;
1036
1037 r_data->scr_copyeverything = 1;
1038 r_data->scr_fullupdate = 0;
1039
1040 draw_cachepic (view, 0, 0, "gfx/ranking.lmp", 1);
1041
1042 // scores
1043 Sbar_SortFrags ();
1044
1045 // draw the text
1046 l = scoreboardlines;
1047
1048 x = 80;
1049 y = 40;
1050 for (i = 0; i < l; i++) {
1051 k = fragsort[i];
1052 s = &cl.scores[k];
1053 if (!s->name->value[0])
1054 continue;
1055
1056 // draw background
1057 top = Sbar_ColorForMap (s->topcolor);
1058 bottom = Sbar_ColorForMap (s->bottomcolor);
1059
1060 draw_fill (view, x, y, 40, 4, top);
1061 draw_fill (view, x, y + 4, 40, 4, bottom);
1062
1063 draw_smallnum (view, x + 12, y, s->frags, 0, 0);
1064
1065 if (k == cl.viewentity - 1)
1066 draw_character (view, x - 4, y, 12);
1067
1068 // draw name
1069 draw_string (view, x + 64, y, s->name->value);
1070
1071 y += 10;
1072 }
1073 }
1074
1075 static void
Sbar_DrawScoreboard(void)1076 Sbar_DrawScoreboard (void)
1077 {
1078 //Sbar_SoloScoreboard ();
1079 if (cl.gametype == GAME_DEATHMATCH)
1080 Sbar_DeathmatchOverlay (overlay_view);
1081 }
1082
1083 static void
draw_overlay(view_t * view)1084 draw_overlay (view_t *view)
1085 {
1086 if (sb_showscores || cl.stats[STAT_HEALTH] <= 0) {
1087 Sbar_DrawScoreboard ();
1088 }
1089 }
1090
1091 static void
draw_time(view_t * view)1092 draw_time (view_t *view)
1093 {
1094 struct tm *local = NULL;
1095 time_t utc = 0;
1096 const char *timefmt = NULL;
1097 char st[80]; //FIXME: overflow
1098
1099 // Get local time
1100 utc = time (NULL);
1101 local = localtime (&utc);
1102
1103 if (hud_time->int_val == 1) { // Use international format
1104 timefmt = "%k:%M";
1105 } else if (hud_time->int_val >= 2) { // US AM/PM display
1106 timefmt = "%l:%M %P";
1107 }
1108
1109 strftime (st, sizeof (st), timefmt, local);
1110 draw_string (view, 8, 0, st);
1111 }
1112
1113 static void
draw_fps(view_t * view)1114 draw_fps (view_t *view)
1115 {
1116 static char st[80];
1117 double t;
1118 static double lastframetime;
1119 static double lastfps;
1120
1121 t = Sys_DoubleTime ();
1122 if ((t - lastframetime) >= 0.2) {
1123 lastfps = fps_count / (t - lastframetime);
1124 fps_count = 0;
1125 lastframetime = t;
1126 snprintf (st, sizeof (st), "%5.1f FPS", lastfps);
1127 }
1128 draw_string (view, 80, 8, st);
1129 }
1130
1131 static void
draw_stuff(view_t * view)1132 draw_stuff (view_t *view)
1133 {
1134 if (hud_time->int_val > 0)
1135 draw_time (view);
1136 if (hud_fps->int_val > 0)
1137 draw_fps (view);
1138 }
1139
1140 static void
draw_intermission(view_t * view)1141 draw_intermission (view_t *view)
1142 {
1143 int dig;
1144 int num;
1145
1146 r_data->scr_copyeverything = 1;
1147 r_data->scr_fullupdate = 0;
1148
1149 draw_cachepic (view, 64, 24, "gfx/complete.lmp", 0);
1150
1151 draw_cachepic (view, 0, 56, "gfx/inter.lmp", 0);
1152
1153 // time
1154 dig = cl.completed_time / 60;
1155 draw_num (view, 160, 64, dig, 3, 0);
1156 num = cl.completed_time - dig * 60;
1157 draw_pic (view, 234, 64, sb_colon);
1158 draw_pic (view, 246, 64, sb_nums[0][num / 10]);
1159 draw_pic (view, 266, 64, sb_nums[0][num % 10]);
1160
1161 draw_num (view, 160, 104, cl.stats[STAT_SECRETS], 3, 0);
1162 draw_pic (view, 232, 104, sb_slash);
1163 draw_num (view, 240, 104, cl.stats[STAT_TOTALSECRETS], 3, 0);
1164
1165 draw_num (view, 160, 144, cl.stats[STAT_MONSTERS], 3, 0);
1166 draw_pic (view, 232, 144, sb_slash);
1167 draw_num (view, 240, 144, cl.stats[STAT_TOTALMONSTERS], 3, 0);
1168 }
1169
1170 void
Sbar_IntermissionOverlay(void)1171 Sbar_IntermissionOverlay (void)
1172 {
1173 r_data->scr_copyeverything = 1;
1174 r_data->scr_fullupdate = 0;
1175
1176 if (cl.gametype == GAME_DEATHMATCH) {
1177 Sbar_DeathmatchOverlay (overlay_view);
1178 return;
1179 }
1180 draw_intermission (overlay_view);
1181 }
1182
1183 /* CENTER PRINTING */
1184 static dstring_t center_string = {&dstring_default_mem};
1185 static float centertime_start; // for slow victory printing
1186 static float centertime_off;
1187 static int center_lines;
1188
1189 /*
1190 Called for important messages that should stay in the center of the screen
1191 for a few moments
1192 */
1193 void
Sbar_CenterPrint(const char * str)1194 Sbar_CenterPrint (const char *str)
1195 {
1196 if (!str) {
1197 centertime_off = 0;
1198 dstring_clearstr (¢er_string);
1199 return;
1200 }
1201
1202 dstring_copystr (¢er_string, str);
1203
1204 centertime_off = scr_centertime->value;
1205 centertime_start = realtime;
1206
1207 // count the number of lines for centering
1208 center_lines = 1;
1209 while (*str) {
1210 if (*str == '\n')
1211 center_lines++;
1212 str++;
1213 }
1214 }
1215
1216 static void
Sbar_DrawCenterString(view_t * view,int remaining)1217 Sbar_DrawCenterString (view_t *view, int remaining)
1218 {
1219 const char *start;
1220 int j, l, x, y;
1221
1222 start = center_string.str;
1223
1224 if (center_lines <= 4)
1225 y = view->yabs + view->ylen * 0.35;
1226 else
1227 y = view->yabs + 48;
1228
1229 do {
1230 // scan the width of the line
1231 for (l = 0; l < 40; l++)
1232 if (start[l] == '\n' || !start[l])
1233 break;
1234 x = view->xabs + (view->xlen - l * 8) / 2;
1235 for (j = 0; j < l; j++, x += 8) {
1236 r_funcs->Draw_Character (x, y, start[j]);
1237 if (!remaining--)
1238 return;
1239 }
1240
1241 y += 8;
1242
1243 while (*start && *start != '\n')
1244 start++;
1245 if (!*start)
1246 break;
1247 start++; // skip the \n
1248 } while (1);
1249 }
1250
1251 void
Sbar_FinaleOverlay(void)1252 Sbar_FinaleOverlay (void)
1253 {
1254 int remaining;
1255
1256 r_data->scr_copyeverything = 1;
1257
1258 draw_cachepic (overlay_view, 0, 16, "gfx/finale.lmp", 1);
1259 // the finale prints the characters one at a time
1260 remaining = scr_printspeed->value * (realtime - centertime_start);
1261 Sbar_DrawCenterString (overlay_view, remaining);
1262 }
1263
1264 void
Sbar_DrawCenterPrint(void)1265 Sbar_DrawCenterPrint (void)
1266 {
1267 r_data->scr_copytop = 1;
1268
1269 centertime_off -= r_data->frametime;
1270 if (centertime_off <= 0)
1271 return;
1272
1273 Sbar_DrawCenterString (overlay_view, -1);
1274 }
1275
1276 static void
init_sbar_views(void)1277 init_sbar_views (void)
1278 {
1279 view_t *view;
1280
1281 sbar_view = view_new (0, 0, 320, 48, grav_south);
1282
1283 sbar_frags_view = view_new (0, 0, 130, 8, grav_northeast);
1284 sbar_frags_view->draw = draw_frags;
1285
1286 sbar_inventory_view = view_new (0, 0, 320, 24, grav_northwest);
1287 sbar_inventory_view->draw = draw_inventory_sbar;
1288
1289 view = view_new (0, 0, 32, 16, grav_southwest);
1290 view->draw = draw_weapons_sbar;
1291 view_add (sbar_inventory_view, view);
1292
1293 view = view_new (0, 0, 32, 8, grav_northwest);
1294 view->draw = draw_ammo_sbar;
1295 view_add (sbar_inventory_view, view);
1296
1297 view = view_new (32, 0, 96, 16, grav_southeast);
1298 view->draw = draw_items;
1299 view_add (sbar_inventory_view, view);
1300
1301 view = view_new (0, 0, 32, 16, grav_southeast);
1302 view->draw = draw_sigils;
1303 view_add (sbar_inventory_view, view);
1304
1305 if (sbar_frags_view)
1306 view_add (sbar_inventory_view, sbar_frags_view);
1307
1308 view_add (sbar_view, sbar_inventory_view);
1309
1310 view = view_new (0, 0, 320, 24, grav_southwest);
1311 view->draw = draw_status_bar;
1312 view_add (sbar_view, view);
1313
1314 view = view_new (0, 0, 320, 24, grav_southwest);
1315 view->draw = draw_status;
1316 view_add (sbar_view, view);
1317
1318 if (r_data->vid->conwidth > 320) {
1319 int l = (r_data->vid->conwidth - 320) / 2;
1320
1321 view = view_new (-l, 0, l, 48, grav_southwest);
1322 view->draw = draw_tile;
1323 view->resize_y = 1;
1324 view_add (sbar_view, view);
1325
1326 view = view_new (-l, 0, l, 48, grav_southeast);
1327 view->draw = draw_tile;
1328 view->resize_y = 1;
1329 view_add (sbar_view, view);
1330 }
1331 }
1332
1333 static void
init_hud_views(void)1334 init_hud_views (void)
1335 {
1336 view_t *view;
1337
1338 hud_view = view_new (0, 0, 320, 48, grav_south);
1339 hud_frags_view = view_new (0, 0, 130, 8, grav_northeast);
1340 hud_frags_view->draw = draw_frags;
1341
1342 hud_view->resize_y = 1;
1343
1344 hud_armament_view = view_new (0, 48, 42, 156, grav_southeast);
1345
1346 view = view_new (0, 0, 24, 112, grav_northeast);
1347 view->draw = draw_weapons_hud;
1348 view_add (hud_armament_view, view);
1349
1350 view = view_new (0, 0, 42, 44, grav_southeast);
1351 view->draw = draw_ammo_hud;
1352 view_add (hud_armament_view, view);
1353
1354 hud_inventory_view = view_new (0, 0, 320, 24, grav_northwest);
1355 view_add (hud_view, hud_inventory_view);
1356
1357 view = view_new (0, 0, 320, 24, grav_southwest);
1358 view->draw = draw_status;
1359 view_add (hud_view, view);
1360
1361 view = view_new (32, 0, 96, 16, grav_southeast);
1362 view->draw = draw_items;
1363 view_add (hud_inventory_view, view);
1364
1365 view = view_new (0, 0, 32, 16, grav_southeast);
1366 view->draw = draw_sigils;
1367 view_add (hud_inventory_view, view);
1368
1369 if (hud_frags_view)
1370 view_add (hud_inventory_view, hud_frags_view);
1371
1372 view = view_new (0, 0, r_data->vid->conwidth, 48, grav_south);
1373 view_add (view, hud_view);
1374 hud_view = view;
1375
1376 view_add (hud_view, hud_armament_view);
1377
1378 view_insert (main_view, hud_view, 0);
1379 }
1380
1381 static void
init_hipnotic_sbar_views(void)1382 init_hipnotic_sbar_views (void)
1383 {
1384 view_t *view;
1385
1386 sbar_view = view_new (0, 0, 320, 48, grav_south);
1387
1388 sbar_frags_view = view_new (0, 0, 130, 8, grav_northeast);
1389 sbar_frags_view->draw = draw_frags;
1390
1391 sbar_inventory_view = view_new (0, 0, 320, 24, grav_northwest);
1392 sbar_inventory_view->draw = draw_hipnotic_inventory_sbar;
1393
1394 view = view_new (0, 0, 224, 16, grav_southwest);
1395 view->draw = draw_hipnotic_weapons_sbar;
1396 view_add (sbar_inventory_view, view);
1397
1398 view = view_new (0, 0, 32, 8, grav_northwest);
1399 view->draw = draw_ammo_sbar;
1400 view_add (sbar_inventory_view, view);
1401
1402 view = view_new (0, 0, 96, 16, grav_southeast);
1403 view->draw = draw_hipnotic_items;
1404 view_add (sbar_inventory_view, view);
1405
1406 view = view_new (0, 0, 32, 16, grav_southeast);
1407 view->draw = draw_sigils;
1408 view_add (sbar_inventory_view, view);
1409
1410 if (sbar_frags_view)
1411 view_add (sbar_inventory_view, sbar_frags_view);
1412
1413 view_add (sbar_view, sbar_inventory_view);
1414
1415 view = view_new (0, 0, 320, 24, grav_southwest);
1416 view->draw = draw_status_bar;
1417 view_add (sbar_view, view);
1418
1419 view = view_new (0, 0, 320, 24, grav_southwest);
1420 view->draw = draw_hipnotic_status;
1421 view_add (sbar_view, view);
1422
1423 if (r_data->vid->conwidth > 320) {
1424 int l = (r_data->vid->conwidth - 320) / 2;
1425
1426 view = view_new (-l, 0, l, 48, grav_southwest);
1427 view->draw = draw_tile;
1428 view->resize_y = 1;
1429 view_add (sbar_view, view);
1430
1431 view = view_new (-l, 0, l, 48, grav_southeast);
1432 view->draw = draw_tile;
1433 view->resize_y = 1;
1434 view_add (sbar_view, view);
1435 }
1436 }
1437
1438 static void
init_hipnotic_hud_views(void)1439 init_hipnotic_hud_views (void)
1440 {
1441 view_t *view;
1442
1443 hud_view = view_new (0, 0, 320, 48, grav_south);
1444 hud_frags_view = view_new (0, 0, 130, 8, grav_northeast);
1445 hud_frags_view->draw = draw_frags;
1446
1447 hud_view->resize_y = 1;
1448
1449 if (r_data->vid->conheight < 252) {
1450 hud_armament_view = view_new (0,
1451 min (r_data->vid->conheight - 160, 48),
1452 66, 160, grav_southeast);
1453 } else {
1454 hud_armament_view = view_new (0, 48, 42, 204, grav_southeast);
1455 }
1456
1457 view = view_new (0, 0, 24, 160, grav_northeast);
1458 view->draw = draw_hipnotic_weapons_hud;
1459 view_add (hud_armament_view, view);
1460
1461 view = view_new (0, 0, 42, 44, grav_southeast);
1462 view->draw = draw_ammo_hud;
1463 view_add (hud_armament_view, view);
1464
1465 hud_inventory_view = view_new (0, 0, 320, 24, grav_northwest);
1466 view_add (hud_view, hud_inventory_view);
1467
1468 view = view_new (0, 0, 320, 24, grav_southwest);
1469 view->draw = draw_hipnotic_status;
1470 view_add (hud_view, view);
1471
1472 view = view_new (0, 0, 96, 16, grav_southeast);
1473 view->draw = draw_hipnotic_items;
1474 view_add (hud_inventory_view, view);
1475
1476 view = view_new (0, 0, 32, 16, grav_southeast);
1477 view->draw = draw_sigils;
1478 view_add (hud_inventory_view, view);
1479
1480 if (hud_frags_view)
1481 view_add (hud_inventory_view, hud_frags_view);
1482
1483 view = view_new (0, 0, r_data->vid->conwidth, 48, grav_south);
1484 view_add (view, hud_view);
1485 hud_view = view;
1486
1487 view_add (hud_view, hud_armament_view);
1488
1489 view_insert (main_view, hud_view, 0);
1490 }
1491
1492 static void
init_rogue_sbar_views(void)1493 init_rogue_sbar_views (void)
1494 {
1495 view_t *view;
1496
1497 sbar_view = view_new (0, 0, 320, 48, grav_south);
1498
1499 sbar_frags_view = view_new (0, 0, 130, 8, grav_northeast);
1500 sbar_frags_view->draw = draw_frags;
1501
1502 sbar_inventory_view = view_new (0, 0, 320, 24, grav_northwest);
1503 sbar_inventory_view->draw = draw_rogue_inventory_sbar;
1504
1505 view = view_new (0, 0, 224, 16, grav_southwest);
1506 view->draw = draw_rogue_weapons_sbar;
1507 view_add (sbar_inventory_view, view);
1508
1509 view = view_new (0, 0, 32, 8, grav_northwest);
1510 view->draw = draw_ammo_sbar;
1511 view_add (sbar_inventory_view, view);
1512
1513 view = view_new (0, 0, 128, 16, grav_southeast);
1514 view->draw = draw_rogue_items;
1515 view_add (sbar_inventory_view, view);
1516
1517 if (sbar_frags_view)
1518 view_add (sbar_inventory_view, sbar_frags_view);
1519
1520 view_add (sbar_view, sbar_inventory_view);
1521
1522 view = view_new (0, 0, 320, 24, grav_southwest);
1523 view->draw = draw_status_bar;
1524 view_add (sbar_view, view);
1525
1526 view = view_new (0, 0, 320, 24, grav_southwest);
1527 view->draw = draw_rogue_status;
1528 view_add (sbar_view, view);
1529
1530 if (r_data->vid->conwidth > 320) {
1531 int l = (r_data->vid->conwidth - 320) / 2;
1532
1533 view = view_new (-l, 0, l, 48, grav_southwest);
1534 view->draw = draw_tile;
1535 view->resize_y = 1;
1536 view_add (sbar_view, view);
1537
1538 view = view_new (-l, 0, l, 48, grav_southeast);
1539 view->draw = draw_tile;
1540 view->resize_y = 1;
1541 view_add (sbar_view, view);
1542 }
1543 }
1544
1545 static void
init_rogue_hud_views(void)1546 init_rogue_hud_views (void)
1547 {
1548 view_t *view;
1549
1550 hud_view = view_new (0, 0, 320, 48, grav_south);
1551 hud_frags_view = view_new (0, 0, 130, 8, grav_northeast);
1552 hud_frags_view->draw = draw_frags;
1553
1554 hud_view->resize_y = 1;
1555
1556 hud_armament_view = view_new (0, 48, 42, 156, grav_southeast);
1557
1558 view = view_new (0, 0, 24, 112, grav_northeast);
1559 view->draw = draw_rogue_weapons_hud;
1560 view_add (hud_armament_view, view);
1561
1562 view = view_new (0, 0, 42, 44, grav_southeast);
1563 view->draw = draw_rogue_ammo_hud;
1564 view_add (hud_armament_view, view);
1565
1566 hud_inventory_view = view_new (0, 0, 320, 24, grav_northwest);
1567 view_add (hud_view, hud_inventory_view);
1568
1569 view = view_new (0, 0, 320, 24, grav_southwest);
1570 view->draw = draw_rogue_status;
1571 view_add (hud_view, view);
1572
1573 view = view_new (0, 0, 128, 16, grav_southeast);
1574 view->draw = draw_rogue_items;
1575 view_add (hud_inventory_view, view);
1576
1577 if (hud_frags_view)
1578 view_add (hud_inventory_view, hud_frags_view);
1579
1580 view = view_new (0, 0, r_data->vid->conwidth, 48, grav_south);
1581 view_add (view, hud_view);
1582 hud_view = view;
1583
1584 view_add (hud_view, hud_armament_view);
1585
1586 view_insert (main_view, hud_view, 0);
1587 }
1588
1589 static void
init_views(void)1590 init_views (void)
1591 {
1592 main_view = view_new (0, 0, r_data->vid->conwidth, r_data->vid->conheight,
1593 grav_northwest);
1594 if (con_module)
1595 view_insert (con_module->data->console->view, main_view, 0);
1596 main_view->resize_x = 1; // get resized if the 2d view resizes
1597 main_view->resize_y = 1;
1598 main_view->visible = 0; // but don't let the console draw our stuff
1599 if (r_data->vid->conheight > 300)
1600 overlay_view = view_new (0, 0, 320, 300, grav_center);
1601 else
1602 overlay_view = view_new (0, 0, 320, r_data->vid->conheight,
1603 grav_center);
1604 overlay_view->draw = draw_overlay;
1605 overlay_view->visible = 0;
1606
1607 stuff_view = view_new (0, 48, 152, 16, grav_southwest);
1608 stuff_view->draw = draw_stuff;
1609
1610 view_insert (main_view, overlay_view, 0);
1611 view_insert (main_view, stuff_view, 0);
1612
1613 if (!strcmp (qfs_gamedir->hudtype, "hipnotic")) {
1614 init_hipnotic_sbar_views ();
1615 init_hipnotic_hud_views ();
1616 } else if (!strcmp (qfs_gamedir->hudtype, "rogue")) {
1617 init_rogue_sbar_views ();
1618 init_rogue_hud_views ();
1619 } else {
1620 init_sbar_views ();
1621 init_hud_views ();
1622 }
1623 }
1624
1625 static void
Sbar_GIB_Print_Center_f(void)1626 Sbar_GIB_Print_Center_f (void)
1627 {
1628 if (GIB_Argc () != 2) {
1629 GIB_USAGE ("text");
1630 } else
1631 Sbar_CenterPrint (GIB_Argv(1));
1632 }
1633
1634 static void
sbar_keydest_callback(keydest_t kd)1635 sbar_keydest_callback (keydest_t kd)
1636 {
1637 overlay_view->visible = kd == key_game;
1638 }
1639
1640 void
Sbar_Init(void)1641 Sbar_Init (void)
1642 {
1643 int i;
1644
1645 init_views ();
1646
1647 Key_KeydestCallback (sbar_keydest_callback);
1648
1649 for (i = 0; i < 10; i++) {
1650 sb_nums[0][i] = r_funcs->Draw_PicFromWad (va ("num_%i", i));
1651 sb_nums[1][i] = r_funcs->Draw_PicFromWad (va ("anum_%i", i));
1652 }
1653
1654 sb_nums[0][10] = r_funcs->Draw_PicFromWad ("num_minus");
1655 sb_nums[1][10] = r_funcs->Draw_PicFromWad ("anum_minus");
1656
1657 sb_colon = r_funcs->Draw_PicFromWad ("num_colon");
1658 sb_slash = r_funcs->Draw_PicFromWad ("num_slash");
1659
1660 sb_weapons[0][0] = r_funcs->Draw_PicFromWad ("inv_shotgun");
1661 sb_weapons[0][1] = r_funcs->Draw_PicFromWad ("inv_sshotgun");
1662 sb_weapons[0][2] = r_funcs->Draw_PicFromWad ("inv_nailgun");
1663 sb_weapons[0][3] = r_funcs->Draw_PicFromWad ("inv_snailgun");
1664 sb_weapons[0][4] = r_funcs->Draw_PicFromWad ("inv_rlaunch");
1665 sb_weapons[0][5] = r_funcs->Draw_PicFromWad ("inv_srlaunch");
1666 sb_weapons[0][6] = r_funcs->Draw_PicFromWad ("inv_lightng");
1667
1668 sb_weapons[1][0] = r_funcs->Draw_PicFromWad ("inv2_shotgun");
1669 sb_weapons[1][1] = r_funcs->Draw_PicFromWad ("inv2_sshotgun");
1670 sb_weapons[1][2] = r_funcs->Draw_PicFromWad ("inv2_nailgun");
1671 sb_weapons[1][3] = r_funcs->Draw_PicFromWad ("inv2_snailgun");
1672 sb_weapons[1][4] = r_funcs->Draw_PicFromWad ("inv2_rlaunch");
1673 sb_weapons[1][5] = r_funcs->Draw_PicFromWad ("inv2_srlaunch");
1674 sb_weapons[1][6] = r_funcs->Draw_PicFromWad ("inv2_lightng");
1675
1676 for (i = 0; i < 5; i++) {
1677 sb_weapons[2 + i][0] =
1678 r_funcs->Draw_PicFromWad (va ("inva%i_shotgun", i + 1));
1679 sb_weapons[2 + i][1] =
1680 r_funcs->Draw_PicFromWad (va ("inva%i_sshotgun", i + 1));
1681 sb_weapons[2 + i][2] =
1682 r_funcs->Draw_PicFromWad (va ("inva%i_nailgun", i + 1));
1683 sb_weapons[2 + i][3] =
1684 r_funcs->Draw_PicFromWad (va ("inva%i_snailgun", i + 1));
1685 sb_weapons[2 + i][4] =
1686 r_funcs->Draw_PicFromWad (va ("inva%i_rlaunch", i + 1));
1687 sb_weapons[2 + i][5] =
1688 r_funcs->Draw_PicFromWad (va ("inva%i_srlaunch", i + 1));
1689 sb_weapons[2 + i][6] =
1690 r_funcs->Draw_PicFromWad (va ("inva%i_lightng", i + 1));
1691 }
1692
1693 sb_ammo[0] = r_funcs->Draw_PicFromWad ("sb_shells");
1694 sb_ammo[1] = r_funcs->Draw_PicFromWad ("sb_nails");
1695 sb_ammo[2] = r_funcs->Draw_PicFromWad ("sb_rocket");
1696 sb_ammo[3] = r_funcs->Draw_PicFromWad ("sb_cells");
1697
1698 sb_armor[0] = r_funcs->Draw_PicFromWad ("sb_armor1");
1699 sb_armor[1] = r_funcs->Draw_PicFromWad ("sb_armor2");
1700 sb_armor[2] = r_funcs->Draw_PicFromWad ("sb_armor3");
1701
1702 sb_items[0] = r_funcs->Draw_PicFromWad ("sb_key1");
1703 sb_items[1] = r_funcs->Draw_PicFromWad ("sb_key2");
1704 sb_items[2] = r_funcs->Draw_PicFromWad ("sb_invis");
1705 sb_items[3] = r_funcs->Draw_PicFromWad ("sb_invuln");
1706 sb_items[4] = r_funcs->Draw_PicFromWad ("sb_suit");
1707 sb_items[5] = r_funcs->Draw_PicFromWad ("sb_quad");
1708
1709 sb_sigil[0] = r_funcs->Draw_PicFromWad ("sb_sigil1");
1710 sb_sigil[1] = r_funcs->Draw_PicFromWad ("sb_sigil2");
1711 sb_sigil[2] = r_funcs->Draw_PicFromWad ("sb_sigil3");
1712 sb_sigil[3] = r_funcs->Draw_PicFromWad ("sb_sigil4");
1713
1714 sb_faces[4][0] = r_funcs->Draw_PicFromWad ("face1");
1715 sb_faces[4][1] = r_funcs->Draw_PicFromWad ("face_p1");
1716 sb_faces[3][0] = r_funcs->Draw_PicFromWad ("face2");
1717 sb_faces[3][1] = r_funcs->Draw_PicFromWad ("face_p2");
1718 sb_faces[2][0] = r_funcs->Draw_PicFromWad ("face3");
1719 sb_faces[2][1] = r_funcs->Draw_PicFromWad ("face_p3");
1720 sb_faces[1][0] = r_funcs->Draw_PicFromWad ("face4");
1721 sb_faces[1][1] = r_funcs->Draw_PicFromWad ("face_p4");
1722 sb_faces[0][0] = r_funcs->Draw_PicFromWad ("face5");
1723 sb_faces[0][1] = r_funcs->Draw_PicFromWad ("face_p5");
1724
1725 sb_face_invis = r_funcs->Draw_PicFromWad ("face_invis");
1726 sb_face_invuln = r_funcs->Draw_PicFromWad ("face_invul2");
1727 sb_face_invis_invuln = r_funcs->Draw_PicFromWad ("face_inv2");
1728 sb_face_quad = r_funcs->Draw_PicFromWad ("face_quad");
1729
1730 Cmd_AddCommand ("+showscores", Sbar_ShowScores,
1731 "Display information on everyone playing");
1732 Cmd_AddCommand ("-showscores", Sbar_DontShowScores,
1733 "Stop displaying information on everyone playing");
1734
1735 sb_sbar = r_funcs->Draw_PicFromWad ("sbar");
1736 sb_ibar = r_funcs->Draw_PicFromWad ("ibar");
1737 sb_scorebar = r_funcs->Draw_PicFromWad ("scorebar");
1738
1739 // MED 01/04/97 added new hipnotic weapons
1740 if (!strcmp (qfs_gamedir->hudtype, "hipnotic")) {
1741 hsb_weapons[0][0] = r_funcs->Draw_PicFromWad ("inv_laser");
1742 hsb_weapons[0][1] = r_funcs->Draw_PicFromWad ("inv_mjolnir");
1743 hsb_weapons[0][2] = r_funcs->Draw_PicFromWad ("inv_gren_prox");
1744 hsb_weapons[0][3] = r_funcs->Draw_PicFromWad ("inv_prox_gren");
1745 hsb_weapons[0][4] = r_funcs->Draw_PicFromWad ("inv_prox");
1746
1747 hsb_weapons[1][0] = r_funcs->Draw_PicFromWad ("inv2_laser");
1748 hsb_weapons[1][1] = r_funcs->Draw_PicFromWad ("inv2_mjolnir");
1749 hsb_weapons[1][2] = r_funcs->Draw_PicFromWad ("inv2_gren_prox");
1750 hsb_weapons[1][3] = r_funcs->Draw_PicFromWad ("inv2_prox_gren");
1751 hsb_weapons[1][4] = r_funcs->Draw_PicFromWad ("inv2_prox");
1752
1753 for (i = 0; i < 5; i++) {
1754 hsb_weapons[2 + i][0] =
1755 r_funcs->Draw_PicFromWad (va ("inva%i_laser", i + 1));
1756 hsb_weapons[2 + i][1] =
1757 r_funcs->Draw_PicFromWad (va ("inva%i_mjolnir", i + 1));
1758 hsb_weapons[2 + i][2] =
1759 r_funcs->Draw_PicFromWad (va ("inva%i_gren_prox", i + 1));
1760 hsb_weapons[2 + i][3] =
1761 r_funcs->Draw_PicFromWad (va ("inva%i_prox_gren", i + 1));
1762 hsb_weapons[2 + i][4] =
1763 r_funcs->Draw_PicFromWad (va ("inva%i_prox", i + 1));
1764 }
1765
1766 hsb_items[0] = r_funcs->Draw_PicFromWad ("sb_wsuit");
1767 hsb_items[1] = r_funcs->Draw_PicFromWad ("sb_eshld");
1768 }
1769
1770 // FIXME: MISSIONHUD
1771 if (!strcmp (qfs_gamedir->hudtype, "rogue")) {
1772 rsb_invbar[0] = r_funcs->Draw_PicFromWad ("r_invbar1");
1773 rsb_invbar[1] = r_funcs->Draw_PicFromWad ("r_invbar2");
1774
1775 rsb_weapons[0] = r_funcs->Draw_PicFromWad ("r_lava");
1776 rsb_weapons[1] = r_funcs->Draw_PicFromWad ("r_superlava");
1777 rsb_weapons[2] = r_funcs->Draw_PicFromWad ("r_gren");
1778 rsb_weapons[3] = r_funcs->Draw_PicFromWad ("r_multirock");
1779 rsb_weapons[4] = r_funcs->Draw_PicFromWad ("r_plasma");
1780
1781 rsb_items[0] = r_funcs->Draw_PicFromWad ("r_shield1");
1782 rsb_items[1] = r_funcs->Draw_PicFromWad ("r_agrav1");
1783
1784 // PGM 01/19/97 - team color border
1785 rsb_teambord = r_funcs->Draw_PicFromWad ("r_teambord");
1786 // PGM 01/19/97 - team color border
1787
1788 rsb_ammo[0] = r_funcs->Draw_PicFromWad ("r_ammolava");
1789 rsb_ammo[1] = r_funcs->Draw_PicFromWad ("r_ammomulti");
1790 rsb_ammo[2] = r_funcs->Draw_PicFromWad ("r_ammoplasma");
1791 }
1792
1793 r_data->viewsize_callback = viewsize_f;
1794 hud_sbar = Cvar_Get ("hud_sbar", "0", CVAR_ARCHIVE, hud_sbar_f,
1795 "status bar mode: 0 = hud, 1 = oldstyle");
1796 hud_swap = Cvar_Get ("hud_swap", "0", CVAR_ARCHIVE, hud_swap_f,
1797 "new HUD on left side?");
1798 hud_scoreboard_gravity = Cvar_Get ("hud_scoreboard_gravity", "center",
1799 CVAR_ARCHIVE, hud_scoreboard_gravity_f,
1800 "control placement of scoreboard "
1801 "overlay: center, northwest, north, "
1802 "northeast, west, east, southwest, "
1803 "south, southeast");
1804 scr_centertime = Cvar_Get ("scr_centertime", "2", CVAR_NONE, NULL, "How "
1805 "long in seconds screen hints are displayed");
1806 scr_printspeed = Cvar_Get ("scr_printspeed", "8", CVAR_NONE, NULL,
1807 "How fast the text is displayed at the end of "
1808 "the single player episodes");
1809
1810 // register GIB builtins
1811 GIB_Builtin_Add ("print::center", Sbar_GIB_Print_Center_f);
1812 }
1813