1 /* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom: a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 * Copyright 2005, 2006 by
12 * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 * 02111-1307, USA.
28 *
29 * DESCRIPTION: Heads-up displays
30 *
31 *-----------------------------------------------------------------------------
32 */
33
34 // killough 5/3/98: remove unnecessary headers
35
36 #include "doomstat.h"
37 #include "hu_stuff.h"
38 #include "hu_lib.h"
39 #include "hu_tracers.h"
40 #include "st_stuff.h" /* jff 2/16/98 need loc of status bar */
41 #include "s_sound.h"
42 #include "dstrings.h"
43 #include "sounds.h"
44 #include "d_deh.h" /* Ty 03/27/98 - externalization of mapnamesx arrays */
45 #include "g_game.h"
46 #include "r_main.h"
47 #include "p_inter.h"
48 #include "sc_man.h"
49 #include "lprintf.h"
50 #include "e6y.h" //e6y
51
52 // global heads up display controls
53
54 int hud_displayed; //jff 2/23/98 turns heads-up display on/off
55 int hud_num;
56
57 //
58 // Locally used constants, shortcuts.
59 //
60 // Ty 03/28/98 -
61 // These four shortcuts modifed to reflect char ** of mapnamesx[]
62 // e6y: why sizeof(mapnamest)/sizeof(mapnamest[0]) does not work?
63 #define HU_TITLE (*mapnames[(gameepisode-1)*9+gamemap-1])
64 #define HU_TITLE2 (gamemap <= 32 ? *mapnames2[gamemap-1] : "")
65 #define HU_TITLEP (gamemap <= 32 ? *mapnamesp[gamemap-1] : "")
66 #define HU_TITLET (gamemap <= 32 ? *mapnamest[gamemap-1] : "")
67 #define HU_TITLEX 0
68 //jff 2/16/98 change 167 to ST_Y-1
69 // CPhipps - changed to ST_TY
70 // proff - changed to 200-ST_HEIGHT for stretching
71 #define HU_TITLEY ((200-ST_HEIGHT) - 1 - hu_font[0].height)
72
73 //jff 2/16/98 add coord text widget coordinates
74 // proff - changed to SCREENWIDTH to 320 for stretching
75 #define HU_COORDX (320 - 13*hu_font2['A'-HU_FONTSTART].width)
76 //jff 3/3/98 split coord widget into three lines in upper right of screen
77 #define HU_COORDXYZ_Y (1 * hu_font['A'-HU_FONTSTART].height + 1)
78 #define HU_COORDX_Y (0 + 0*hu_font['A'-HU_FONTSTART].height + HU_COORDXYZ_Y)
79 #define HU_COORDY_Y (1 + 1*hu_font['A'-HU_FONTSTART].height + HU_COORDXYZ_Y)
80 #define HU_COORDZ_Y (2 + 2*hu_font['A'-HU_FONTSTART].height + HU_COORDXYZ_Y)
81
82 #define HU_MAP_STAT_X (0)
83 #define HU_MAP_STAT_Y (1 * hu_font['A'-HU_FONTSTART].height + 1)
84 #define HU_MAP_MONSTERS_Y (0 + 0*hu_font['A'-HU_FONTSTART].height + HU_MAP_STAT_Y)
85 #define HU_MAP_SECRETS_Y (1 + 1*hu_font['A'-HU_FONTSTART].height + HU_MAP_STAT_Y)
86 #define HU_MAP_ITEMS_Y (2 + 2*hu_font['A'-HU_FONTSTART].height + HU_MAP_STAT_Y)
87 #define HU_MAP_TIME_Y (4 + 4*hu_font['A'-HU_FONTSTART].height + HU_MAP_STAT_Y)
88 #define HU_MAP_TOTALTIME_Y (5 + 5*hu_font['A'-HU_FONTSTART].height + HU_MAP_STAT_Y)
89
90 //jff 2/16/98 add ammo, health, armor widgets, 2/22/98 less gap
91 #define HU_GAPY 8
92
93 #define HU_INPUTX HU_MSGX
94 #define HU_INPUTY (HU_MSGY + HU_MSGHEIGHT*(hu_font[0].height) +1)
95
96 #define HU_TRACERX (2)
97 #define HU_TRACERY (hu_font['A'-HU_FONTSTART].height)
98
99 #define key_alt KEYD_RALT
100 #define key_shift KEYD_RSHIFT
101
102 const char* chat_macros[] =
103 // Ty 03/27/98 - *not* externalized
104 // CPhipps - const char*
105 {
106 HUSTR_CHATMACRO0,
107 HUSTR_CHATMACRO1,
108 HUSTR_CHATMACRO2,
109 HUSTR_CHATMACRO3,
110 HUSTR_CHATMACRO4,
111 HUSTR_CHATMACRO5,
112 HUSTR_CHATMACRO6,
113 HUSTR_CHATMACRO7,
114 HUSTR_CHATMACRO8,
115 HUSTR_CHATMACRO9
116 };
117
118 const char* player_names[] =
119 // Ty 03/27/98 - *not* externalized
120 // CPhipps - const char*
121 {
122 HUSTR_PLRGREEN,
123 HUSTR_PLRINDIGO,
124 HUSTR_PLRBROWN,
125 HUSTR_PLRRED
126 };
127
128 //jff 3/17/98 translate player colmap to text color ranges
129 int plyrcoltran[MAXPLAYERS]={CR_GREEN,CR_GRAY,CR_BROWN,CR_RED};
130
131 char chat_char; // remove later.
132 static player_t* plr;
133
134 // font sets
135 patchnum_t hu_font[HU_FONTSIZE];
136 patchnum_t hu_font2[HU_FONTSIZE];
137 patchnum_t hu_fontk[HU_FONTSIZE];//jff 3/7/98 added for graphic key indicators
138 patchnum_t hu_msgbg[9]; //jff 2/26/98 add patches for message background
139 patchnum_t hu_font_hud[HU_FONTSIZE];
140
141 // widgets
142 static hu_textline_t w_title;
143 static hu_stext_t w_message;
144 static hu_itext_t w_chat;
145 static hu_itext_t w_inputbuffer[MAXPLAYERS];
146 static hu_textline_t w_coordx; //jff 2/16/98 new coord widget for automap
147 static hu_textline_t w_coordy; //jff 3/3/98 split coord widgets automap
148 static hu_textline_t w_coordz; //jff 3/3/98 split coord widgets automap
149 static hu_textline_t w_ammo; //jff 2/16/98 new ammo widget for hud
150 static hu_textline_t w_health; //jff 2/16/98 new health widget for hud
151 static hu_textline_t w_armor; //jff 2/16/98 new armor widget for hud
152 static hu_textline_t w_weapon; //jff 2/16/98 new weapon widget for hud
153 static hu_textline_t w_keys; //jff 2/16/98 new keys widget for hud
154 static hu_textline_t w_gkeys; //jff 3/7/98 graphic keys widget for hud
155 static hu_textline_t w_monsec; //jff 2/16/98 new kill/secret widget for hud
156 static hu_mtext_t w_rtext; //jff 2/26/98 text message refresh widget
157
158 static hu_textline_t w_map_monsters; //e6y monsters widget for automap
159 static hu_textline_t w_map_secrets; //e6y secrets widgets automap
160 static hu_textline_t w_map_items; //e6y items widgets automap
161 static hu_textline_t w_map_time; //e6y level time widgets automap
162 static hu_textline_t w_map_totaltime; //e6y total time widgets automap
163
164 static hu_textline_t w_health_big;
165 static hu_textline_t w_medict_icon_big;
166 static hu_textline_t w_medict_icon_small;
167 static hu_textline_t w_medict_icon_custom;
168 static hu_textline_t w_armor_big;
169 static hu_textline_t w_armor_icon_big;
170 static hu_textline_t w_armor_icon_small;
171 static hu_textline_t w_armor_icon_custom;
172 static hu_textline_t w_medict_percent;
173 static hu_textline_t w_armor_percent;
174 static hu_textline_t w_ammo_big;
175 static hu_textline_t w_ammo_icon;
176 static hu_textline_t w_keys_icon;
177
178 static dboolean always_off = false;
179 static char chat_dest[MAXPLAYERS];
180 dboolean chat_on;
181 static dboolean message_on;
182 static dboolean message_list; //2/26/98 enable showing list of messages
183 dboolean message_dontfuckwithme;
184 static dboolean message_nottobefuckedwith;
185 static int message_counter;
186 extern int showMessages;
187 static dboolean headsupactive = false;
188
189 //jff 2/16/98 hud supported automap colors added
190 int hudcolor_titl; // color range of automap level title
191 int hudcolor_xyco; // color range of new coords on automap
192 int hudcolor_mapstat_title;
193 int hudcolor_mapstat_value;
194 int hudcolor_mapstat_time;
195 //jff 2/16/98 hud text colors, controls added
196 int hudcolor_mesg; // color range of scrolling messages
197 int hudcolor_chat; // color range of chat lines
198 int hud_msg_lines; // number of message lines in window
199 //jff 2/26/98 hud text colors, controls added
200 int hudcolor_list; // list of messages color
201 int hud_list_bgon; // enable for solid window background for message list
202
203 //jff 2/16/98 initialization strings for ammo, health, armor widgets
204 static char hud_coordstrx[32];
205 static char hud_coordstry[32];
206 static char hud_coordstrz[32];
207 static char hud_ammostr[80];
208 static char hud_healthstr[80];
209 static char hud_armorstr[80];
210 static char hud_weapstr[80];
211 static char hud_keysstr[80];
212 static char hud_gkeysstr[80]; //jff 3/7/98 add support for graphic key display
213 static char hud_monsecstr[80];
214
215 //
216 // Builtin map names.
217 // The actual names can be found in DStrings.h.
218 //
219 // Ty 03/27/98 - externalized map name arrays - now in d_deh.c
220 // and converted to arrays of pointers to char *
221 // See modified HUTITLEx macros
222 extern char **mapnames[];
223 extern char **mapnames2[];
224 extern char **mapnamesp[];
225 extern char **mapnamest[];
226
227 extern int map_point_coordinates;
228 extern int map_level_stat;
229
230 // key tables
231 // jff 5/10/98 french support removed,
232 // as it was not being used and couldn't be easily tested
233 //
234 const char* shiftxform;
235
236 const char english_shiftxform[] =
237 {
238 0,
239 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
240 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
241 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
242 31,
243 ' ', '!', '"', '#', '$', '%', '&',
244 '"', // shift-'
245 '(', ')', '*', '+',
246 '<', // shift-,
247 '_', // shift--
248 '>', // shift-.
249 '?', // shift-/
250 ')', // shift-0
251 '!', // shift-1
252 '@', // shift-2
253 '#', // shift-3
254 '$', // shift-4
255 '%', // shift-5
256 '^', // shift-6
257 '&', // shift-7
258 '*', // shift-8
259 '(', // shift-9
260 ':',
261 ':', // shift-;
262 '<',
263 '+', // shift-=
264 '>', '?', '@',
265 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
266 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
267 '[', // shift-[
268 '!', // shift-backslash - OH MY GOD DOES WATCOM SUCK
269 ']', // shift-]
270 '"', '_',
271 '\'', // shift-`
272 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
273 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
274 '{', '|', '}', '~', 127
275 };
276
277 //
278 // HU_Init()
279 //
280 // Initialize the heads-up display, text that overwrites the primary display
281 //
282 // Passed nothing, returns nothing
283 //
HU_Init(void)284 void HU_Init(void)
285 {
286
287 int i;
288 int j;
289 char buffer[9];
290
291 shiftxform = english_shiftxform;
292
293 // load the heads-up font
294 j = HU_FONTSTART;
295 for (i=0;i<HU_FONTSIZE;i++,j++)
296 {
297 if ('0'<=j && j<='9')
298 {
299 sprintf(buffer, "DIG%.1d",j-48);
300 R_SetPatchNum(&hu_font2[i], buffer);
301 sprintf(buffer, "STCFN%.3d",j);
302 R_SetPatchNum(&hu_font[i], buffer);
303 sprintf(buffer, "STTNUM%.1d",j-48);
304 R_SetPatchNum(&hu_font_hud[i], buffer);
305 }
306 else if ('A'<=j && j<='Z')
307 {
308 sprintf(buffer, "DIG%c",j);
309 R_SetPatchNum(&hu_font2[i], buffer);
310 sprintf(buffer, "STCFN%.3d",j);
311 R_SetPatchNum(&hu_font[i], buffer);
312 }
313 else if (j=='-')
314 {
315 R_SetPatchNum(&hu_font2[i], "DIG45");
316 R_SetPatchNum(&hu_font[i], "STCFN045");
317 }
318 else if (j=='/')
319 {
320 R_SetPatchNum(&hu_font2[i], "DIG47");
321 R_SetPatchNum(&hu_font[i], "STCFN047");
322 }
323 else if (j==':')
324 {
325 R_SetPatchNum(&hu_font2[i], "DIG58");
326 R_SetPatchNum(&hu_font[i], "STCFN058");
327 }
328 else if (j=='[')
329 {
330 R_SetPatchNum(&hu_font2[i], "DIG91");
331 R_SetPatchNum(&hu_font[i], "STCFN091");
332 }
333 else if (j==']')
334 {
335 R_SetPatchNum(&hu_font2[i], "DIG93");
336 R_SetPatchNum(&hu_font[i], "STCFN093");
337 }
338 else if (j<97)
339 {
340 sprintf(buffer, "STCFN%.3d",j);
341 R_SetPatchNum(&hu_font2[i], buffer);
342 R_SetPatchNum(&hu_font[i], buffer);
343 //jff 2/23/98 make all font chars defined, useful or not
344 }
345 else if (j>122)
346 {
347 sprintf(buffer, "STBR%.3d",j);
348 R_SetPatchNum(&hu_font2[i], buffer);
349 R_SetPatchNum(&hu_font[i], buffer);
350 }
351 else
352 hu_font[i] = hu_font[0]; //jff 2/16/98 account for gap
353 }
354
355 // CPhipps - load patches for message background
356 for (i=0; i<9; i++) {
357 sprintf(buffer, "BOX%c%c", "UCL"[i/3], "LCR"[i%3]);
358 R_SetPatchNum(&hu_msgbg[i], buffer);
359 }
360
361 // CPhipps - load patches for keys and double keys
362 for (i=0; i<6; i++) {
363 sprintf(buffer, "STKEYS%d", i);
364 R_SetPatchNum(&hu_fontk[i], buffer);
365 }
366
367 R_SetSpriteByIndex(&hu_font_hud[4], SPR_MEDI);
368 R_SetSpriteByIndex(&hu_font_hud[5], SPR_ARM1);
369 R_SetSpriteByIndex(&hu_font_hud[6], SPR_ARM1);
370 R_SetSpriteByIndex(&hu_font_hud[7], SPR_ARM2);
371
372 R_SetSpriteByIndex(&hu_font_hud[8], SPR_STIM);
373 R_SetSpriteByName(&hu_font_hud[9], "BON2A0");
374 R_SetSpriteByName(&hu_font_hud[10], "BON2B0");
375 R_SetSpriteByName(&hu_font_hud[11], "BON2D0");
376
377 R_SetPatchNum(&hu_font_hud[12], "STTPRCNT");
378 R_SetPatchNum(&hu_font_hud[13], "STTPRCNT");
379
380 R_SetPatchByName(&hu_font_hud[30], "HUDMED");
381 R_SetPatchByName(&hu_font_hud[31], "HUDARM1");
382 R_SetPatchByName(&hu_font_hud[32], "HUDARM1");
383 R_SetPatchByName(&hu_font_hud[33], "HUDARM2");
384
385 R_SetSpriteByName(&hu_font_hud[40], "CLIPA0");
386 R_SetSpriteByName(&hu_font_hud[41], "SHELA0");
387 R_SetSpriteByName(&hu_font_hud[42], "CELLA0");
388 R_SetSpriteByName(&hu_font_hud[43], "ROCKA0");
389
390 }
391
392 //
393 // HU_Stop()
394 //
395 // Make the heads-up displays inactive
396 //
397 // Passed nothing, returns nothing
398 //
HU_Stop(void)399 static void HU_Stop(void)
400 {
401 headsupactive = false;
402 }
403
404 //
405 // HU_Start(void)
406 //
407 // Create and initialize the heads-up widgets, software machines to
408 // maintain, update, and display information over the primary display
409 //
410 // This routine must be called after any change to the heads up configuration
411 // in order for the changes to take effect in the actual displays
412 //
413 // Passed nothing, returns nothing
414 //
HU_Start(void)415 void HU_Start(void)
416 {
417 int i;
418 const char* s; /* cph - const */
419
420 if (headsupactive) // stop before starting
421 HU_Stop();
422
423 plr = &players[displayplayer]; // killough 3/7/98
424 message_on = false;
425 message_dontfuckwithme = false;
426 message_nottobefuckedwith = false;
427 chat_on = false;
428
429 // create the message widget
430 // messages to player in upper-left of screen
431 HUlib_initSText
432 (
433 &w_message,
434 HU_MSGX,
435 HU_MSGY,
436 HU_MSGHEIGHT,
437 hu_font,
438 HU_FONTSTART,
439 hudcolor_mesg,
440 VPT_ALIGN_LEFT_TOP,
441 &message_on
442 );
443
444 //jff 2/16/98 added some HUD widgets
445 // create the map title widget - map title display in lower left of automap
446 HUlib_initTextLine
447 (
448 &w_title,
449 HU_TITLEX,
450 HU_TITLEY,
451 hu_font,
452 HU_FONTSTART,
453 hudcolor_titl,
454 VPT_ALIGN_LEFT_BOTTOM
455 );
456
457 // create the hud health widget
458 // bargraph and number for amount of health,
459 // lower left or upper right of screen
460 HUlib_initTextLine
461 (
462 &w_health,
463 0, 0,
464 hu_font2,
465 HU_FONTSTART,
466 CR_GREEN,
467 VPT_NONE
468 );
469
470 HUlib_initTextLine
471 (
472 &w_health_big,
473 0, 0,
474 hu_font_hud,
475 HU_FONTSTART,
476 CR_RED,
477 VPT_NONE
478 );
479
480 HUlib_initTextLine
481 (
482 &w_medict_icon_big,
483 0, 0,
484 hu_font_hud,
485 HU_FONTSTART,
486 CR_RED,
487 VPT_NONE
488 );
489
490 HUlib_initTextLine
491 (
492 &w_medict_icon_small,
493 0, 0,
494 hu_font_hud,
495 HU_FONTSTART,
496 CR_RED,
497 VPT_NONE
498 );
499
500 HUlib_initTextLine
501 (
502 &w_medict_icon_custom,
503 0, 0,
504 hu_font_hud,
505 HU_FONTSTART,
506 CR_RED,
507 VPT_NONE
508 );
509
510 // create the hud armor widget
511 // bargraph and number for amount of armor,
512 // lower left or upper right of screen
513 HUlib_initTextLine
514 (
515 &w_armor,
516 0, 0,
517 hu_font2,
518 HU_FONTSTART,
519 CR_GREEN,
520 VPT_NONE
521 );
522
523 HUlib_initTextLine
524 (
525 &w_armor_big,
526 0, 0,
527 hu_font_hud,
528 HU_FONTSTART,
529 CR_RED,
530 VPT_NONE
531 );
532
533 HUlib_initTextLine
534 (
535 &w_armor_icon_big,
536 0, 0,
537 hu_font_hud,
538 HU_FONTSTART,
539 CR_RED,
540 VPT_NONE
541 );
542
543 HUlib_initTextLine
544 (
545 &w_armor_icon_small,
546 0, 0,
547 hu_font_hud,
548 HU_FONTSTART,
549 CR_RED,
550 VPT_NONE
551 );
552
553 HUlib_initTextLine
554 (
555 &w_armor_icon_custom,
556 0, 0,
557 hu_font_hud,
558 HU_FONTSTART,
559 CR_RED,
560 VPT_NONE
561 );
562
563 // create the hud ammo widget
564 // bargraph and number for amount of ammo for current weapon,
565 // lower left or lower right of screen
566 HUlib_initTextLine
567 (
568 &w_ammo,
569 0, 0,
570 hu_font2,
571 HU_FONTSTART,
572 CR_GOLD,
573 VPT_NONE
574 );
575
576 // create the hud weapons widget
577 // list of numbers of weapons possessed
578 // lower left or lower right of screen
579 HUlib_initTextLine
580 (
581 &w_weapon,
582 0, 0,
583 hu_font2,
584 HU_FONTSTART,
585 CR_GRAY,
586 VPT_NONE
587 );
588
589 // create the hud keys widget
590 // display of key letters possessed
591 // lower left of screen
592 HUlib_initTextLine
593 (
594 &w_keys,
595 0, 0,
596 hu_font2,
597 HU_FONTSTART,
598 CR_GRAY,
599 VPT_NONE
600 );
601
602 // create the hud graphic keys widget
603 // display of key graphics possessed
604 // lower left of screen
605 HUlib_initTextLine
606 (
607 &w_gkeys,
608 0, 0,
609 hu_fontk,
610 HU_FONTSTART,
611 CR_RED,
612 VPT_NONE
613 );
614
615 // create the hud monster/secret widget
616 // totals and current values for kills, items, secrets
617 // lower left of screen
618 HUlib_initTextLine
619 (
620 &w_monsec,
621 0, 0,
622 hu_font2,
623 HU_FONTSTART,
624 CR_GRAY,
625 VPT_NONE
626 );
627
628 HUlib_initTextLine
629 (
630 &w_medict_percent,
631 0, 0,
632 hu_font_hud,
633 HU_FONTSTART,
634 CR_GRAY,
635 VPT_NONE
636 );
637
638 HUlib_initTextLine
639 (
640 &w_armor_percent,
641 0, 0,
642 hu_font_hud,
643 HU_FONTSTART,
644 CR_GRAY,
645 VPT_NONE
646 );
647
648 HUlib_initTextLine
649 (
650 &w_ammo_big,
651 0, 0,
652 hu_font_hud,
653 HU_FONTSTART,
654 CR_RED,
655 VPT_NONE
656 );
657
658 HUlib_initTextLine
659 (
660 &w_ammo_icon,
661 0, 0,
662 hu_font_hud,
663 HU_FONTSTART,
664 CR_RED,
665 VPT_NONE
666 );
667
668 HUlib_initTextLine
669 (
670 &w_keys_icon,
671 0, 0,
672 hu_fontk,
673 HU_FONTSTART,
674 CR_RED,
675 VPT_NONE
676 );
677
678 // create the hud text refresh widget
679 // scrolling display of last hud_msg_lines messages received
680 if (hud_msg_lines>HU_MAXMESSAGES)
681 hud_msg_lines=HU_MAXMESSAGES;
682 //jff 4/21/98 if setup has disabled message list while active, turn it off
683 message_list = hud_msg_lines > 1; //jff 8/8/98 initialize both ways
684 //jff 2/26/98 add the text refresh widget initialization
685 HUlib_initMText
686 (
687 &w_rtext,
688 0,
689 0,
690 320,
691 // SCREENWIDTH,
692 (hud_msg_lines+2)*HU_REFRESHSPACING,
693 hu_font,
694 HU_FONTSTART,
695 hudcolor_list,
696 hu_msgbg,
697 VPT_ALIGN_LEFT_TOP,
698 &message_list
699 );
700
701 // initialize the automap's level title widget
702 // e6y: stop SEGV here when gamemap is not initialized
703 if (gamestate == GS_LEVEL && gamemap > 0) /* cph - stop SEGV here when not in level */
704 switch (gamemode)
705 {
706 case shareware:
707 case registered:
708 case retail:
709 s = HU_TITLE;
710 break;
711
712 case commercial:
713 default: // Ty 08/27/98 - modified to check mission for TNT/Plutonia
714 s = (gamemission==pack_tnt) ? HU_TITLET :
715 (gamemission==pack_plut) ? HU_TITLEP : HU_TITLE2;
716 break;
717 } else s = "";
718 while (*s)
719 HUlib_addCharToTextLine(&w_title, *(s++));
720
721 // create the automaps coordinate widget
722 // jff 3/3/98 split coord widget into three lines: x,y,z
723 // jff 2/16/98 added
724 HUlib_initTextLine
725 (
726 &w_coordx,
727 HU_COORDX,
728 HU_COORDX_Y,
729 hu_font,
730 HU_FONTSTART,
731 hudcolor_xyco,
732 VPT_ALIGN_RIGHT_TOP
733 );
734 HUlib_initTextLine
735 (
736 &w_coordy,
737 HU_COORDX,
738 HU_COORDY_Y,
739 hu_font,
740 HU_FONTSTART,
741 hudcolor_xyco,
742 VPT_ALIGN_RIGHT_TOP
743 );
744 HUlib_initTextLine
745 (
746 &w_coordz,
747 HU_COORDX,
748 HU_COORDZ_Y,
749 hu_font,
750 HU_FONTSTART,
751 hudcolor_xyco,
752 VPT_ALIGN_RIGHT_TOP
753 );
754 //e6y
755 HUlib_initTextLine
756 (
757 &w_map_monsters,
758 HU_MAP_STAT_X,
759 HU_MAP_MONSTERS_Y,
760 hu_font,
761 HU_FONTSTART,
762 hudcolor_mapstat_title,
763 VPT_ALIGN_LEFT_TOP
764 );
765 HUlib_initTextLine
766 (
767 &w_map_secrets,
768 HU_MAP_STAT_X,
769 HU_MAP_SECRETS_Y,
770 hu_font,
771 HU_FONTSTART,
772 hudcolor_mapstat_title,
773 VPT_ALIGN_LEFT_TOP
774 );
775 HUlib_initTextLine
776 (
777 &w_map_items,
778 HU_MAP_STAT_X,
779 HU_MAP_ITEMS_Y,
780 hu_font,
781 HU_FONTSTART,
782 hudcolor_mapstat_title,
783 VPT_ALIGN_LEFT_TOP
784 );
785 HUlib_initTextLine
786 (
787 &w_map_time,
788 HU_MAP_STAT_X,
789 HU_MAP_TIME_Y,
790 hu_font,
791 HU_FONTSTART,
792 hudcolor_mapstat_time,
793 VPT_ALIGN_LEFT_TOP
794 );
795 HUlib_initTextLine
796 (
797 &w_map_totaltime,
798 HU_MAP_STAT_X,
799 HU_MAP_TOTALTIME_Y,
800 hu_font,
801 HU_FONTSTART,
802 hudcolor_mapstat_time,
803 VPT_ALIGN_LEFT_TOP
804 );
805 HUlib_initTextLine
806 (
807 &w_hudadd,
808 0, 0,
809 hu_font2,
810 HU_FONTSTART,
811 CR_GRAY,
812 VPT_NONE
813 );
814 HUlib_initTextLine
815 (
816 &w_centermsg,
817 HU_CENTERMSGX,
818 HU_CENTERMSGY,
819 hu_font,
820 HU_FONTSTART,
821 hudcolor_titl,
822 VPT_STRETCH
823 );
824 HUlib_initTextLine
825 (
826 &w_precache,
827 16,
828 186,
829 hu_font,
830 HU_FONTSTART,
831 CR_RED,
832 VPT_ALIGN_LEFT_BOTTOM
833 );
834 strcpy(hud_add,"");
835 s = hud_add;
836 while (*s)
837 HUlib_addCharToTextLine(&w_hudadd, *(s++));
838
839 for(i = 0; i < NUMTRACES; i++)
840 {
841 HUlib_initTextLine(
842 &w_traces[i],
843 HU_TRACERX,
844 HU_TRACERY+i*HU_GAPY,
845 hu_font2,
846 HU_FONTSTART,
847 CR_GRAY,
848 VPT_ALIGN_LEFT_BOTTOM
849 );
850
851 strcpy(traces[i].hudstr, "");
852 s = traces[i].hudstr;
853 while (*s)
854 HUlib_addCharToTextLine(&w_traces[i], *(s++));
855 HUlib_drawTextLine(&w_traces[i], false);
856 }
857
858
859 //jff 2/16/98 initialize ammo widget
860 strcpy(hud_ammostr,"AMM ");
861
862 //jff 2/16/98 initialize health widget
863 strcpy(hud_healthstr,"HEL ");
864
865 //jff 2/16/98 initialize armor widget
866 strcpy(hud_armorstr,"ARM ");
867
868 //jff 2/17/98 initialize weapons widget
869 strcpy(hud_weapstr,"WEA ");
870
871 //jff 2/17/98 initialize keys widget
872 //jff 3/17/98 show frags in deathmatch mode
873 strcpy(hud_keysstr,(deathmatch ? "FRG " : "KEY "));
874
875 //jff 2/17/98 initialize graphic keys widget
876 strcpy(hud_gkeysstr," ");
877
878 //jff 2/17/98 initialize kills/items/secret widget
879 strcpy(hud_monsecstr,"STS ");
880
881 // create the chat widget
882 HUlib_initIText
883 (
884 &w_chat,
885 HU_INPUTX,
886 HU_INPUTY,
887 hu_font,
888 HU_FONTSTART,
889 hudcolor_chat,
890 VPT_NONE,
891 &chat_on
892 );
893
894 // create the inputbuffer widgets, one per player
895 for (i=0 ; i<MAXPLAYERS ; i++)
896 HUlib_initIText
897 (
898 &w_inputbuffer[i],
899 0,
900 0,
901 0,
902 0,
903 hudcolor_chat,
904 VPT_NONE,
905 &always_off
906 );
907
908 // now allow the heads-up display to run
909 headsupactive = true;
910
911 HU_LoadHUDDefs();
912
913 HU_MoveHud(true);
914 }
915
HU_NextHud(void)916 void HU_NextHud(void)
917 {
918 if (huds_count > 0)
919 {
920 hud_num = (hud_num + 1) % huds_count; // cycle hud_active
921 }
922 }
923
924 typedef void (*HU_widget_build_func)(void);
925 typedef void (*HU_widget_draw_func)(void);
926
927 typedef struct hud_cfg_item_s
928 {
929 char name[80];
930 int x;
931 int y;
932 } hud_cfg_item_t;
933
934 typedef struct hud_widget_s
935 {
936 hu_textline_t *hu_textline;
937 int x;
938 int y;
939 enum patch_translation_e flags;
940 HU_widget_build_func build;
941 HU_widget_draw_func draw;
942 const char *name;
943 } hud_widget_t;
944
945 typedef struct hud_widgets_list_s
946 {
947 int count;
948 hud_widget_t *items;
949 } hud_widgets_list_t;
950
951 int huds_count;
952 hud_widgets_list_t *huds;
953 hud_widgets_list_t *hud_current;
954
955 void HU_widget_build_ammo(void);
956 void HU_widget_draw_ammo(void);
957 void HU_widget_build_weapon(void);
958 void HU_widget_draw_weapon(void);
959 void HU_widget_build_keys(void);
960 void HU_widget_draw_keys(void);
961 void HU_widget_build_monsec(void);
962 void HU_widget_draw_monsec(void);
963 void HU_widget_build_health(void);
964 void HU_widget_draw_health(void);
965 void HU_widget_build_armor(void);
966 void HU_widget_draw_armor(void);
967 void HU_widget_build_hudadd(void);
968 void HU_widget_draw_hudadd(void);
969
970 void HU_widget_build_health_big(void);
971 void HU_widget_draw_health_big(void);
972 void HU_widget_build_armor_big(void);
973 void HU_widget_draw_armor_big(void);
974
975 void HU_widget_build_medict_icon_big(void);
976 void HU_widget_draw_medict_icon_big(void);
977 void HU_widget_build_armor_icon_big(void);
978 void HU_widget_draw_armor_icon_big(void);
979
980 void HU_widget_build_medict_icon_small(void);
981 void HU_widget_draw_medict_icon_small(void);
982 void HU_widget_build_armor_icon_small(void);
983 void HU_widget_draw_armor_icon_small(void);
984
985 void HU_widget_build_medict_icon_custom(void);
986 void HU_widget_draw_medict_icon_custom(void);
987 void HU_widget_build_armor_icon_custom(void);
988 void HU_widget_draw_armor_icon_custom(void);
989
990 void HU_widget_build_medict_percent(void);
991 void HU_widget_draw_medict_percent(void);
992 void HU_widget_build_armor_percent(void);
993 void HU_widget_draw_armor_percent(void);
994
995 void HU_widget_build_ammo_big(void);
996 void HU_widget_draw_ammo_big(void);
997 void HU_widget_build_ammo_icon(void);
998 void HU_widget_draw_ammo_icon(void);
999
1000 void HU_widget_build_gkeys(void);
1001 void HU_widget_draw_gkeys(void);
1002
1003 static hud_widget_t hud_name_widget[] =
1004 {
1005 {&w_ammo, 0, 0, 0, HU_widget_build_ammo, HU_widget_draw_ammo, "ammo"},
1006 {&w_weapon, 0, 0, 0, HU_widget_build_weapon, HU_widget_draw_weapon, "weapon"},
1007 {&w_keys, 0, 0, 0, HU_widget_build_keys, HU_widget_draw_keys, "keys"},
1008 {&w_monsec, 0, 0, 0, HU_widget_build_monsec, HU_widget_draw_monsec, "monsec"},
1009 {&w_health, 0, 0, 0, HU_widget_build_health, HU_widget_draw_health, "health"},
1010 {&w_armor, 0, 0, 0, HU_widget_build_armor, HU_widget_draw_armor, "armor"},
1011 {&w_hudadd, 0, 0, 0, HU_widget_build_hudadd, HU_widget_draw_hudadd, "hudadd"},
1012
1013 {&w_keys_icon, 0, 0, 0, HU_widget_build_gkeys, HU_widget_draw_gkeys, "gkeys"},
1014
1015 {&w_traces[0], 0, 0, 0, NULL, NULL, "tracers"},
1016
1017 {&w_health_big, 0, 0, VPT_NOOFFSET, HU_widget_build_health_big, HU_widget_draw_health_big, "health_big"},
1018 {&w_armor_big, 0, 0, VPT_NOOFFSET, HU_widget_build_armor_big, HU_widget_draw_armor_big, "armor_big"},
1019
1020 {&w_medict_icon_big, 0, 0, VPT_NOOFFSET, HU_widget_build_medict_icon_big, HU_widget_draw_medict_icon_big, "medict_icon_big"},
1021 {&w_armor_icon_big, 0, 0, VPT_NOOFFSET, HU_widget_build_armor_icon_big, HU_widget_draw_armor_icon_big, "armor_icon_big"},
1022
1023 {&w_medict_icon_small, 0, 0, VPT_NOOFFSET, HU_widget_build_medict_icon_small, HU_widget_draw_medict_icon_small, "medict_icon_small"},
1024 {&w_armor_icon_small, 0, 0, VPT_NOOFFSET, HU_widget_build_armor_icon_small, HU_widget_draw_armor_icon_small, "armor_icon_small"},
1025
1026 {&w_medict_icon_custom, 0, 0, VPT_NOOFFSET, HU_widget_build_medict_icon_custom, HU_widget_draw_medict_icon_custom, "medict_icon_custom"},
1027 {&w_armor_icon_custom, 0, 0, VPT_NOOFFSET, HU_widget_build_armor_icon_custom, HU_widget_draw_armor_icon_custom, "armor_icon_custom"},
1028
1029 {&w_medict_percent, 0, 0, VPT_NOOFFSET, HU_widget_build_medict_percent, HU_widget_draw_medict_percent, "medict_percent"},
1030 {&w_armor_percent, 0, 0, VPT_NOOFFSET, HU_widget_build_armor_percent, HU_widget_draw_armor_percent, "armor_percent"},
1031
1032 {&w_ammo_big, 0, 0, VPT_NOOFFSET, HU_widget_build_ammo_big, HU_widget_draw_ammo_big, "ammo_big"},
1033 {&w_ammo_big, 0, 0, VPT_NOOFFSET, HU_widget_build_ammo_big, HU_widget_draw_ammo_big, "ammo_big"},
1034 {&w_ammo_icon, 0, 0, VPT_NOOFFSET, HU_widget_build_ammo_icon, HU_widget_draw_ammo_icon, "ammo_icon"},
1035 {&w_ammo_icon, 0, 0, VPT_NOOFFSET, HU_widget_build_ammo_icon, HU_widget_draw_ammo_icon, "ammo_icon"},
1036
1037 {NULL, 0, 0, 0, NULL, NULL, NULL}
1038 };
1039
HU_LoadHUDDefs(void)1040 void HU_LoadHUDDefs(void)
1041 {
1042 static int init = 0;
1043
1044 int lump, i, params_count;
1045 hud_cfg_item_t cfg_item;
1046 hud_widgets_list_t *list = NULL;
1047 char st[200];
1048
1049 if (init)
1050 return;
1051
1052 init = true;
1053
1054 huds_count = 0;
1055 huds = NULL;
1056
1057 lump = (W_CheckNumForName)("-PRBHUD-", ns_prboom);
1058 if (lump != -1)
1059 {
1060 SC_OpenLumpByNum(lump);
1061
1062 // Get actor class name.
1063 while (SC_GetString())
1064 {
1065 // declaration of hud
1066 if (SC_Compare("hud"))
1067 {
1068 // skip everything after "hud" signature
1069 while (SC_Check())
1070 SC_GetString();
1071
1072 // setup new hud
1073 huds_count++;
1074 huds = realloc(huds, huds_count * sizeof(huds[0]));
1075 list = &huds[huds_count - 1];
1076 list->items = NULL;
1077 list->count = 0;
1078
1079 // definition of hud is below
1080 continue;
1081 }
1082
1083 // keep going until a valid HUD declaration has been found
1084 if (huds_count < 1)
1085 continue;
1086
1087 strncpy(st, sc_String, sizeof(st) - 1);
1088
1089 while (SC_Check() && SC_GetString())
1090 {
1091 strncat(st, " ", sizeof(st) - 1);
1092 strncat(st, sc_String, sizeof(st) - 1);
1093 }
1094 st[sizeof(st) - 1] = 0;
1095
1096 // hud_widget x y
1097 params_count = sscanf(st, "%s %d %d", &cfg_item.name[0], &cfg_item.x, &cfg_item.y);
1098 if (params_count == 3)
1099 {
1100 for (i = 0; hud_name_widget[i].name; i++)
1101 {
1102 if (!strcasecmp(hud_name_widget[i].name, cfg_item.name))
1103 {
1104 hud_widget_t *item;
1105
1106 list->count++;
1107 list->items = realloc(list->items, list->count * sizeof(list->items[0]));
1108
1109 item = &list->items[list->count - 1];
1110
1111 item->hu_textline = hud_name_widget[i].hu_textline;
1112
1113 item->x = cfg_item.x;
1114 item->y = cfg_item.y;
1115
1116 if (abs(cfg_item.x) < 160)
1117 {
1118 item->flags = (abs(cfg_item.y) > 100 ? VPT_ALIGN_LEFT_BOTTOM : VPT_ALIGN_LEFT_TOP);
1119 }
1120 else
1121 {
1122 item->flags = (abs(cfg_item.y) > 100 ? VPT_ALIGN_RIGHT_BOTTOM : VPT_ALIGN_RIGHT_TOP);
1123 }
1124 item->flags |= hud_name_widget[i].flags;
1125
1126 item->build = hud_name_widget[i].build;
1127 item->draw = hud_name_widget[i].draw;
1128
1129 break;
1130 }
1131 }
1132 }
1133 }
1134
1135 SC_Close();
1136 }
1137 }
1138
1139 //
1140 // HU_MoveHud()
1141 //
1142 // Move the HUD display from distributed to compact mode or vice-versa
1143 //
1144 // Passed nothing, returns nothing
1145 //
1146 //jff 3/9/98 create this externally callable to avoid glitch
1147 // when menu scatter's HUD due to delay in change of position
1148 //
1149
HU_MoveHud(int force)1150 void HU_MoveHud(int force)
1151 {
1152 static int ohud_num = -1;
1153
1154 //jff 3/4/98 move displays around on F5 changing hud_distributed
1155 if ((huds_count > 0) && (force || hud_num != ohud_num))
1156 {
1157 int i;
1158
1159 hud_current = &huds[hud_num % huds_count];
1160
1161 for (i = 0; i < hud_current->count; i++)
1162 {
1163 hud_current->items[i].hu_textline->x = hud_current->items[i].x;
1164 hud_current->items[i].hu_textline->y = hud_current->items[i].y;
1165 hud_current->items[i].hu_textline->flags = hud_current->items[i].flags;
1166 }
1167
1168 ohud_num = hud_num;
1169 }
1170 }
1171
HU_GetHealthColor(int health,int def)1172 int HU_GetHealthColor(int health, int def)
1173 {
1174 int result;
1175
1176 if (health < health_red)
1177 result = CR_RED;
1178 else if (health < health_yellow)
1179 result = CR_GOLD;
1180 else if (health <= health_green)
1181 result = CR_GREEN;
1182 else
1183 result = def;
1184
1185 return result;
1186 }
1187
HU_GetArmorColor(int armor,int def)1188 int HU_GetArmorColor(int armor, int def)
1189 {
1190 int result;
1191
1192 if (armor < armor_red)
1193 result = CR_RED;
1194 else if (armor < armor_yellow)
1195 result = CR_GOLD;
1196 else if (armor <= armor_green)
1197 result = CR_GREEN;
1198 else
1199 result = def;
1200
1201 return result;
1202 }
1203
HU_GetAmmoColor(int ammo,int fullammo)1204 int HU_GetAmmoColor(int ammo, int fullammo)
1205 {
1206 int result;
1207
1208 int ammopct = (100 * ammo) / fullammo;
1209
1210 if (ammopct < ammo_red)
1211 result = CR_RED;
1212 else if (ammopct < ammo_yellow)
1213 result = CR_GOLD;
1214 else
1215 result = CR_GREEN;
1216
1217 return result;
1218 }
1219
HU_widget_build_ammo(void)1220 void HU_widget_build_ammo(void)
1221 {
1222 int i;
1223 char *s;
1224 char ammostr[80]; //jff 3/8/98 allow plenty room for dehacked mods
1225 int fullammo = plr->maxammo[weaponinfo[plr->readyweapon].ammo];
1226
1227 // do the hud ammo display
1228 // clear the widgets internal line
1229 HUlib_clearTextLine(&w_ammo);
1230 strcpy(hud_ammostr,"AMM ");
1231 if (weaponinfo[plr->readyweapon].ammo == am_noammo || fullammo == 0)
1232 { // special case for weapon with no ammo selected - blank bargraph + N/A
1233 strcat(hud_ammostr,"\x7f\x7f\x7f\x7f\x7f\x7f\x7f N/A");
1234 w_ammo.cm = CR_GRAY;
1235 }
1236 else
1237 {
1238 int ammo = plr->ammo[weaponinfo[plr->readyweapon].ammo];
1239 int ammopct = (100*ammo)/fullammo;
1240 int ammobars = ammopct/4;
1241
1242 // build the numeric amount init string
1243 sprintf(ammostr,"%d/%d",ammo,fullammo);
1244 // build the bargraph string
1245 // full bargraph chars
1246 for (i=4;i<4+ammobars/4;)
1247 hud_ammostr[i++] = 123;
1248 // plus one last character with 0,1,2,3 bars
1249 switch(ammobars%4)
1250 {
1251 case 0:
1252 break;
1253 case 1:
1254 hud_ammostr[i++] = 126;
1255 break;
1256 case 2:
1257 hud_ammostr[i++] = 125;
1258 break;
1259 case 3:
1260 hud_ammostr[i++] = 124;
1261 break;
1262 }
1263
1264 // pad string with blank bar characters
1265 while(i<4+7)
1266 hud_ammostr[i++] = 127;
1267 hud_ammostr[i] = '\0';
1268 strcat(hud_ammostr,ammostr);
1269
1270 // set the display color from the percentage of total ammo held
1271 w_ammo.cm = HU_GetAmmoColor(ammo, fullammo);
1272 }
1273 // transfer the init string to the widget
1274 s = hud_ammostr;
1275 while (*s)
1276 HUlib_addCharToTextLine(&w_ammo, *(s++));
1277 }
1278
HU_widget_draw_ammo(void)1279 void HU_widget_draw_ammo(void)
1280 {
1281 // display the ammo widget every frame
1282 HUlib_drawTextLine(&w_ammo, false);
1283 }
1284
HU_widget_build_health(void)1285 void HU_widget_build_health(void)
1286 {
1287 int i;
1288 char *s;
1289 char healthstr[80];//jff
1290 int health = plr->health;
1291 int healthbars = health>100? 25 : health/4;
1292
1293 if (w_health.val != -1 && w_health.val == health)
1294 return;
1295 w_health.val = health;
1296
1297 // clear the widgets internal line
1298 HUlib_clearTextLine(&w_health);
1299
1300 // build the numeric amount init string
1301 sprintf(healthstr,"%3d",health);
1302 // build the bargraph string
1303 // full bargraph chars
1304 for (i=4;i<4+healthbars/4;)
1305 hud_healthstr[i++] = 123;
1306 // plus one last character with 0,1,2,3 bars
1307 switch(healthbars%4)
1308 {
1309 case 0:
1310 break;
1311 case 1:
1312 hud_healthstr[i++] = 126;
1313 break;
1314 case 2:
1315 hud_healthstr[i++] = 125;
1316 break;
1317 case 3:
1318 hud_healthstr[i++] = 124;
1319 break;
1320 }
1321 // pad string with blank bar characters
1322 while(i<4+7)
1323 hud_healthstr[i++] = 127;
1324 hud_healthstr[i] = '\0';
1325 strcat(hud_healthstr,healthstr);
1326
1327 // set the display color from the amount of health posessed
1328 w_health.cm = HU_GetHealthColor(health, CR_BLUE);
1329
1330 // transfer the init string to the widget
1331 s = hud_healthstr;
1332 while (*s)
1333 HUlib_addCharToTextLine(&w_health, *(s++));
1334 }
1335
HU_widget_draw_health(void)1336 void HU_widget_draw_health(void)
1337 {
1338 HUlib_drawTextLine(&w_health, false);
1339 }
1340
HU_widget_build_health_big(void)1341 void HU_widget_build_health_big(void)
1342 {
1343 char *s;
1344 char healthstr[80];//jff
1345 int health = plr->health;
1346
1347 if (w_health_big.val != -1 && w_health_big.val == health)
1348 return;
1349 w_health_big.val = health;
1350
1351 // clear the widgets internal line
1352 HUlib_clearTextLine(&w_health_big);
1353
1354 // build the numeric amount init string
1355 sprintf(healthstr,"%d",health);
1356
1357 // set the display color from the amount of health posessed
1358 if (!sts_always_red)
1359 w_health_big.cm = HU_GetHealthColor(health, CR_BLUE2);
1360
1361 // transfer the init string to the widget
1362 s = healthstr;
1363 while (*s)
1364 HUlib_addCharToTextLine(&w_health_big, *(s++));
1365 }
1366
HU_widget_draw_health_big(void)1367 void HU_widget_draw_health_big(void)
1368 {
1369 HUlib_drawTextLine(&w_health_big, false);
1370 }
1371
HU_widget_build_medict_icon_big(void)1372 void HU_widget_build_medict_icon_big(void)
1373 {
1374 // transfer the graphic key text to the widget
1375 HUlib_clearTextLine(&w_medict_icon_big);
1376 HUlib_addCharToTextLine(&w_medict_icon_big, '!' + 0 + 4);
1377 }
1378
HU_widget_draw_medict_icon_big(void)1379 void HU_widget_draw_medict_icon_big(void)
1380 {
1381 HUlib_drawTextLine(&w_medict_icon_big, false);
1382 }
1383
HU_widget_build_medict_icon_small(void)1384 void HU_widget_build_medict_icon_small(void)
1385 {
1386 // transfer the graphic key text to the widget
1387 HUlib_clearTextLine(&w_medict_icon_small);
1388 HUlib_addCharToTextLine(&w_medict_icon_small, '!' + 0 + 8);
1389 }
1390
HU_widget_draw_medict_icon_small(void)1391 void HU_widget_draw_medict_icon_small(void)
1392 {
1393 HUlib_drawTextLine(&w_medict_icon_small, false);
1394 }
1395
HU_widget_build_medict_icon_custom(void)1396 void HU_widget_build_medict_icon_custom(void)
1397 {
1398 // transfer the graphic key text to the widget
1399 HUlib_clearTextLine(&w_medict_icon_custom);
1400 HUlib_addCharToTextLine(&w_medict_icon_custom, '!' + 0 + 30);
1401 }
1402
HU_widget_draw_medict_icon_custom(void)1403 void HU_widget_draw_medict_icon_custom(void)
1404 {
1405 HUlib_drawTextLine(&w_medict_icon_custom, false);
1406 }
1407
HU_widget_build_armor_icon_custom(void)1408 void HU_widget_build_armor_icon_custom(void)
1409 {
1410 // transfer the graphic key text to the widget
1411 HUlib_clearTextLine(&w_armor_icon_custom);
1412 HUlib_addCharToTextLine(&w_armor_icon_custom, (char)('!' + plr->armortype + 1 + 30));
1413 }
1414
HU_widget_draw_armor_icon_custom(void)1415 void HU_widget_draw_armor_icon_custom(void)
1416 {
1417 HUlib_drawTextLine(&w_armor_icon_custom, false);
1418 }
1419
HU_widget_build_armor(void)1420 void HU_widget_build_armor(void)
1421 {
1422 int i;
1423 char *s;
1424 char armorstr[80]; //jff
1425 int armor = plr->armorpoints;
1426 int armorbars = armor>100? 25 : armor/4;
1427
1428 if (w_armor.val != -1 && w_armor.val == armor)
1429 return;
1430 w_armor.val = armor;
1431
1432 // clear the widgets internal line
1433 HUlib_clearTextLine(&w_armor);
1434 // build the numeric amount init string
1435 sprintf(armorstr,"%3d",armor);
1436 // build the bargraph string
1437 // full bargraph chars
1438 for (i=4;i<4+armorbars/4;)
1439 hud_armorstr[i++] = 123;
1440 // plus one last character with 0,1,2,3 bars
1441 switch(armorbars%4)
1442 {
1443 case 0:
1444 break;
1445 case 1:
1446 hud_armorstr[i++] = 126;
1447 break;
1448 case 2:
1449 hud_armorstr[i++] = 125;
1450 break;
1451 case 3:
1452 hud_armorstr[i++] = 124;
1453 break;
1454 }
1455 // pad string with blank bar characters
1456 while(i<4+7)
1457 hud_armorstr[i++] = 127;
1458 hud_armorstr[i] = '\0';
1459 strcat(hud_armorstr,armorstr);
1460
1461 // set the display color from the amount of armor posessed
1462 w_armor.cm = HU_GetArmorColor(armor, CR_BLUE);
1463
1464 // transfer the init string to the widget
1465 s = hud_armorstr;
1466 while (*s)
1467 HUlib_addCharToTextLine(&w_armor, *(s++));
1468 }
1469
HU_widget_draw_armor(void)1470 void HU_widget_draw_armor(void)
1471 {
1472 HUlib_drawTextLine(&w_armor, false);
1473 }
1474
HU_widget_build_armor_big(void)1475 void HU_widget_build_armor_big(void)
1476 {
1477 char *s;
1478 char armorstr[80]; //jff
1479 int armor = plr->armorpoints;
1480
1481 if (w_armor_big.val != -1 && w_armor_big.val == armor)
1482 return;
1483 w_armor_big.val = armor;
1484
1485 // clear the widgets internal line
1486 HUlib_clearTextLine(&w_armor_big);
1487 // build the numeric amount init string
1488 sprintf(armorstr,"%d",armor);
1489
1490 // set the display color from the amount of armor posessed
1491 if (!sts_always_red)
1492 w_armor_big.cm = HU_GetArmorColor(armor, CR_BLUE2);
1493
1494 // transfer the init string to the widget
1495 s = armorstr;
1496 while (*s)
1497 HUlib_addCharToTextLine(&w_armor_big, *(s++));
1498 }
1499
HU_widget_draw_armor_big(void)1500 void HU_widget_draw_armor_big(void)
1501 {
1502 HUlib_drawTextLine(&w_armor_big, false);
1503 }
1504
HU_widget_build_armor_icon_big(void)1505 void HU_widget_build_armor_icon_big(void)
1506 {
1507 // transfer the graphic key text to the widget
1508 HUlib_clearTextLine(&w_armor_icon_big);
1509 HUlib_addCharToTextLine(&w_armor_icon_big, (char)('!' + plr->armortype + 1 + 4));
1510 }
1511
HU_widget_draw_armor_icon_big(void)1512 void HU_widget_draw_armor_icon_big(void)
1513 {
1514 HUlib_drawTextLine(&w_armor_icon_big, false);
1515 }
1516
HU_widget_build_armor_icon_small(void)1517 void HU_widget_build_armor_icon_small(void)
1518 {
1519 // transfer the graphic key text to the widget
1520 HUlib_clearTextLine(&w_armor_icon_small);
1521 HUlib_addCharToTextLine(&w_armor_icon_small, (char)('!' + plr->armortype + 1 + 8));
1522 }
1523
HU_widget_draw_armor_icon_small(void)1524 void HU_widget_draw_armor_icon_small(void)
1525 {
1526 HUlib_drawTextLine(&w_armor_icon_small, false);
1527 }
1528
1529
HU_widget_build_weapon(void)1530 void HU_widget_build_weapon(void)
1531 {
1532 int i;
1533 char *s;
1534 int w;
1535 int ammo,fullammo,ammopct;
1536
1537 // clear the widgets internal line
1538 HUlib_clearTextLine(&w_weapon);
1539 i=4; hud_weapstr[i] = '\0'; //jff 3/7/98 make sure ammo goes away
1540
1541 // do each weapon that exists in current gamemode
1542 for (w=0;w<=wp_supershotgun;w++) //jff 3/4/98 show fists too, why not?
1543 {
1544 int ok=1;
1545 //jff avoid executing for weapons that do not exist
1546 switch (gamemode)
1547 {
1548 case shareware:
1549 if (w>=wp_plasma && w!=wp_chainsaw)
1550 ok=0;
1551 break;
1552 case retail:
1553 case registered:
1554 if (w>=wp_supershotgun)
1555 ok=0;
1556 break;
1557 default:
1558 case commercial:
1559 break;
1560 }
1561 if (!ok) continue;
1562
1563 ammo = plr->ammo[weaponinfo[w].ammo];
1564 fullammo = plr->maxammo[weaponinfo[w].ammo];
1565 ammopct=0;
1566
1567 // skip weapons not currently posessed
1568 if (!plr->weaponowned[w])
1569 continue;
1570
1571 ammopct = fullammo? (100*ammo)/fullammo : 100;
1572
1573 // display each weapon number in a color related to the ammo for it
1574 hud_weapstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1575 if (weaponinfo[w].ammo==am_noammo) //jff 3/14/98 show berserk on HUD
1576 hud_weapstr[i++] = plr->powers[pw_strength]? '0'+CR_GREEN : '0'+CR_GRAY;
1577 else if (ammopct<ammo_red)
1578 hud_weapstr[i++] = '0'+CR_RED;
1579 else if (ammopct<ammo_yellow)
1580 hud_weapstr[i++] = '0'+CR_GOLD;
1581 else
1582 hud_weapstr[i++] = '0'+CR_GREEN;
1583 hud_weapstr[i++] = '0'+w+1;
1584 hud_weapstr[i++] = ' ';
1585 hud_weapstr[i] = '\0';
1586 }
1587
1588 // transfer the init string to the widget
1589 s = hud_weapstr;
1590 while (*s)
1591 HUlib_addCharToTextLine(&w_weapon, *(s++));
1592 }
1593
HU_widget_draw_weapon(void)1594 void HU_widget_draw_weapon(void)
1595 {
1596 HUlib_drawTextLine(&w_weapon, false);
1597 }
1598
HU_widget_build_keys(void)1599 void HU_widget_build_keys(void)
1600 {
1601 int i;
1602 int k;
1603 char *s;
1604
1605 hud_keysstr[4] = '\0'; //jff 3/7/98 make sure deleted keys go away
1606 //jff add case for graphic key display
1607 if (!deathmatch)
1608 {
1609 i=0;
1610 hud_gkeysstr[i] = '\0'; //jff 3/7/98 init graphic keys widget string
1611 // build text string whose characters call out graphic keys from fontk
1612 for (k=0;k<6;k++)
1613 {
1614 // skip keys not possessed
1615 if (!plr->cards[k])
1616 continue;
1617
1618 hud_gkeysstr[i++] = '!'+k; // key number plus '!' is char for key
1619 hud_gkeysstr[i++] = ' '; // spacing
1620 hud_gkeysstr[i++] = ' ';
1621 }
1622 hud_gkeysstr[i]='\0';
1623 }
1624 else // not possible in current code, unless deathmatching,
1625 {
1626 i=4;
1627 hud_keysstr[i] = '\0'; //jff 3/7/98 make sure deleted keys go away
1628
1629 // if deathmatch, build string showing top four frag counts
1630 if (deathmatch) //jff 3/17/98 show frags, not keys, in deathmatch
1631 {
1632 int top1=-999,top2=-999,top3=-999,top4=-999;
1633 int idx1=-1,idx2=-1,idx3=-1,idx4=-1;
1634 int fragcount,m;
1635 char numbuf[32];
1636
1637 // scan thru players
1638 for (k=0;k<MAXPLAYERS;k++)
1639 {
1640 // skip players not in game
1641 if (!playeringame[k])
1642 continue;
1643
1644 fragcount = 0;
1645 // compute number of times they've fragged each player
1646 // minus number of times they've been fragged by them
1647 for (m=0;m<MAXPLAYERS;m++)
1648 {
1649 if (!playeringame[m]) continue;
1650 fragcount += (m!=k)? players[k].frags[m] : -players[k].frags[m];
1651 }
1652
1653 // very primitive sort of frags to find top four
1654 if (fragcount>top1)
1655 {
1656 top4=top3; top3=top2; top2 = top1; top1=fragcount;
1657 idx4=idx3; idx3=idx2; idx2 = idx1; idx1=k;
1658 }
1659 else if (fragcount>top2)
1660 {
1661 top4=top3; top3=top2; top2=fragcount;
1662 idx4=idx3; idx3=idx2; idx2=k;
1663 }
1664 else if (fragcount>top3)
1665 {
1666 top4=top3; top3=fragcount;
1667 idx4=idx3; idx3=k;
1668 }
1669 else if (fragcount>top4)
1670 {
1671 top4=fragcount;
1672 idx4=k;
1673 }
1674 }
1675 // if the biggest number exists, put it in the init string
1676 if (idx1>-1)
1677 {
1678 sprintf(numbuf,"%5d",top1);
1679 // make frag count in player's color via escape code
1680 hud_keysstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1681 hud_keysstr[i++] = '0'+plyrcoltran[idx1&3];
1682 s = numbuf;
1683 while (*s)
1684 hud_keysstr[i++] = *(s++);
1685 }
1686 // if the second biggest number exists, put it in the init string
1687 if (idx2>-1)
1688 {
1689 sprintf(numbuf,"%5d",top2);
1690 // make frag count in player's color via escape code
1691 hud_keysstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1692 hud_keysstr[i++] = '0'+plyrcoltran[idx2&3];
1693 s = numbuf;
1694 while (*s)
1695 hud_keysstr[i++] = *(s++);
1696 }
1697 // if the third biggest number exists, put it in the init string
1698 if (idx3>-1)
1699 {
1700 sprintf(numbuf,"%5d",top3);
1701 // make frag count in player's color via escape code
1702 hud_keysstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1703 hud_keysstr[i++] = '0'+plyrcoltran[idx3&3];
1704 s = numbuf;
1705 while (*s)
1706 hud_keysstr[i++] = *(s++);
1707 }
1708 // if the fourth biggest number exists, put it in the init string
1709 if (idx4>-1)
1710 {
1711 sprintf(numbuf,"%5d",top4);
1712 // make frag count in player's color via escape code
1713 hud_keysstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1714 hud_keysstr[i++] = '0'+plyrcoltran[idx4&3];
1715 s = numbuf;
1716 while (*s)
1717 hud_keysstr[i++] = *(s++);
1718 }
1719 hud_keysstr[i] = '\0';
1720 } //jff 3/17/98 end of deathmatch clause
1721 else // build alphabetical key display (not used currently)
1722 {
1723 // scan the keys
1724 for (k=0;k<6;k++)
1725 {
1726 // skip any not possessed by the displayed player's stats
1727 if (!plr->cards[k])
1728 continue;
1729
1730 // use color escapes to make text in key's color
1731 hud_keysstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1732 switch(k)
1733 {
1734 case 0:
1735 hud_keysstr[i++] = '0'+CR_BLUE;
1736 hud_keysstr[i++] = 'B';
1737 hud_keysstr[i++] = 'C';
1738 hud_keysstr[i++] = ' ';
1739 break;
1740 case 1:
1741 hud_keysstr[i++] = '0'+CR_GOLD;
1742 hud_keysstr[i++] = 'Y';
1743 hud_keysstr[i++] = 'C';
1744 hud_keysstr[i++] = ' ';
1745 break;
1746 case 2:
1747 hud_keysstr[i++] = '0'+CR_RED;
1748 hud_keysstr[i++] = 'R';
1749 hud_keysstr[i++] = 'C';
1750 hud_keysstr[i++] = ' ';
1751 break;
1752 case 3:
1753 hud_keysstr[i++] = '0'+CR_BLUE;
1754 hud_keysstr[i++] = 'B';
1755 hud_keysstr[i++] = 'S';
1756 hud_keysstr[i++] = ' ';
1757 break;
1758 case 4:
1759 hud_keysstr[i++] = '0'+CR_GOLD;
1760 hud_keysstr[i++] = 'Y';
1761 hud_keysstr[i++] = 'S';
1762 hud_keysstr[i++] = ' ';
1763 break;
1764 case 5:
1765 hud_keysstr[i++] = '0'+CR_RED;
1766 hud_keysstr[i++] = 'R';
1767 hud_keysstr[i++] = 'S';
1768 hud_keysstr[i++] = ' ';
1769 break;
1770 }
1771 hud_keysstr[i]='\0';
1772 }
1773 }
1774 }
1775
1776 HUlib_clearTextLine(&w_keys); // clear the widget strings
1777
1778 // transfer the built string (frags or key title) to the widget
1779 s = hud_keysstr; //jff 3/7/98 display key titles/key text or frags
1780 while (*s)
1781 HUlib_addCharToTextLine(&w_keys, *(s++));
1782
1783 //jff 3/17/98 show graphic keys in non-DM only
1784 if (!deathmatch) //jff 3/7/98 display graphic keys
1785 {
1786 // clear the widget strings
1787 HUlib_clearTextLine(&w_gkeys);
1788 // transfer the graphic key text to the widget
1789 s = hud_gkeysstr;
1790 while (*s)
1791 HUlib_addCharToTextLine(&w_gkeys, *(s++));
1792 }
1793
1794 w_gkeys.x = w_keys.x + 20;
1795 w_gkeys.y = w_keys.y;
1796 w_gkeys.flags = w_keys.flags;
1797 }
1798
HU_widget_draw_keys(void)1799 void HU_widget_draw_keys(void)
1800 {
1801 HUlib_drawTextLine(&w_keys, false);
1802 if (!deathmatch)
1803 {
1804 HUlib_drawTextLine(&w_gkeys, false);
1805 }
1806 }
1807
HU_widget_build_monsec(void)1808 void HU_widget_build_monsec(void)
1809 {
1810 int i;
1811 char *s;
1812
1813 //e6y
1814 char allkills[200], allsecrets[200];
1815 int playerscount;
1816 int fullkillcount, fullitemcount, fullsecretcount;
1817 int color, killcolor, itemcolor, secretcolor;
1818
1819 // clear the internal widget text buffer
1820 HUlib_clearTextLine(&w_monsec);
1821 if (!hudadd_smarttotals || deathmatch)
1822 {
1823 sprintf
1824 (
1825 hud_monsecstr,
1826 "STS \x1b\x36K \x1b\x33%d \x1b\x36M \x1b\x33%d \x1b\x37I \x1b\x33%d/%d \x1b\x35S \x1b\x33%d/%d",
1827 plr->killcount,totallive,
1828 plr->itemcount,totalitems,
1829 plr->secretcount,totalsecret
1830 );
1831 }
1832 else
1833 {
1834 int allkills_len = 0;
1835 int allsecrets_len = 0;
1836
1837 playerscount = 0;
1838 fullkillcount = 0;
1839 fullitemcount = 0;
1840 fullsecretcount = 0;
1841 for (i=0 ; i<MAXPLAYERS ; i++)
1842 {
1843 if (playeringame[i])
1844 {
1845 color = i==displayplayer?0x33:0x32;
1846 if (playerscount==0)
1847 {
1848 allkills_len = sprintf(allkills, "\x1b%c%d", color, players[i].killcount - players[i].resurectedkillcount);
1849 allsecrets_len = sprintf(allsecrets, "\x1b%c%d", color, players[i].secretcount);
1850 }
1851 else
1852 {
1853 if (allkills_len >= 0 && allsecrets_len >=0)
1854 {
1855 allkills_len += sprintf(&allkills[allkills_len], "\x1b%c+%d", color, players[i].killcount - players[i].resurectedkillcount);
1856 allsecrets_len += sprintf(&allsecrets[allsecrets_len], "\x1b%c+%d", color, players[i].secretcount);
1857 }
1858 }
1859 playerscount++;
1860 fullkillcount += players[i].killcount - players[i].resurectedkillcount;
1861 fullitemcount += players[i].itemcount;
1862 fullsecretcount += players[i].secretcount;
1863 }
1864 }
1865 killcolor = (fullkillcount >= totalkills ? 0x37 : 0x35);
1866 secretcolor = (fullsecretcount >= totalsecret ? 0x37 : 0x35);
1867 itemcolor = (fullitemcount >= totalitems ? 0x37 : 0x35);
1868 if (playerscount<2)
1869 {
1870 sprintf
1871 (
1872 hud_monsecstr,
1873 "STS \x1b\x36K \x1b%c%d/%d \x1b\x36I \x1b%c%d/%d \x1b\x36S \x1b%c%d/%d",
1874 killcolor, fullkillcount,totalkills,
1875 itemcolor,plr->itemcount,totalitems,
1876 secretcolor, fullsecretcount,totalsecret
1877 );
1878 }
1879 else
1880 {
1881 sprintf
1882 (
1883 hud_monsecstr,
1884 "STS \x1b\x36K %s \x1b%c%d/%d \x1b\x36I \x1b%c%d/%d \x1b\x36S %s \x1b%c%d/%d",
1885 allkills,killcolor,fullkillcount,totalkills,
1886 itemcolor,plr->itemcount,totalitems,
1887 allsecrets,secretcolor,fullsecretcount,totalsecret
1888 );
1889 }
1890 }
1891
1892 // transfer the init string to the widget
1893 s = hud_monsecstr;
1894 while (*s)
1895 HUlib_addCharToTextLine(&w_monsec, *(s++));
1896 }
1897
HU_widget_draw_monsec(void)1898 void HU_widget_draw_monsec(void)
1899 {
1900 HUlib_drawTextLine(&w_monsec, false);
1901 }
1902
HU_widget_build_hudadd(void)1903 void HU_widget_build_hudadd(void)
1904 {
1905 char *s;
1906 hud_add[0] = 0;
1907
1908 if (!hudadd_gamespeed && !hudadd_leveltime)
1909 return;
1910
1911 if (hudadd_gamespeed)
1912 sprintf(hud_add,"\x1b\x32speed \x1b\x33%.2d ", realtic_clock_rate);
1913 if ((hudadd_leveltime) || (demoplayback && hudadd_demotime))
1914 {
1915 static char demo_len_null[1]={0};
1916 char *demo_len = demoplayback && hudadd_demotime ? demo_len_st : demo_len_null;
1917 if (totalleveltimes)
1918 sprintf(hud_add+strlen(hud_add),"\x1b\x32time \x1b\x35%d:%02d%s \x1b\x33%d:%05.2f ",
1919 (totalleveltimes+leveltime)/35/60, ((totalleveltimes+leveltime)%(60*35))/35, demo_len,
1920 leveltime/35/60, (float)(leveltime%(60*35))/35);
1921 else
1922 sprintf(hud_add+strlen(hud_add),"\x1b\x32time \x1b\x33%d:%05.2f%s ",
1923 leveltime/35/60, (float)(leveltime%(60*35))/35, demo_len);
1924 }
1925 HUlib_clearTextLine(&w_hudadd);
1926 s = hud_add;
1927 while (*s)
1928 HUlib_addCharToTextLine(&w_hudadd, *(s++));
1929 }
1930
HU_widget_draw_hudadd(void)1931 void HU_widget_draw_hudadd(void)
1932 {
1933 if (hudadd_gamespeed || hudadd_leveltime)
1934 {
1935 HUlib_drawTextLine(&w_hudadd, false);
1936 }
1937 }
1938
HU_widget_build_medict_percent(void)1939 void HU_widget_build_medict_percent(void)
1940 {
1941 int health = plr->health;
1942
1943 if (w_medict_percent.val != -1 && w_medict_percent.val == health)
1944 return;
1945 w_medict_percent.val = health;
1946
1947 // transfer the graphic key text to the widget
1948 HUlib_clearTextLine(&w_medict_percent);
1949
1950 if (!sts_always_red)
1951 {
1952 if (sts_pct_always_gray)
1953 w_medict_percent.cm = CR_GRAY;
1954 else
1955 w_medict_percent.cm = HU_GetHealthColor(health, CR_BLUE2);
1956 }
1957
1958 HUlib_addCharToTextLine(&w_medict_percent, (char)('!' + 12));
1959 }
1960
HU_widget_draw_medict_percent(void)1961 void HU_widget_draw_medict_percent(void)
1962 {
1963 HUlib_drawTextLine(&w_medict_percent, false);
1964 }
1965
HU_widget_build_armor_percent(void)1966 void HU_widget_build_armor_percent(void)
1967 {
1968 int armor = plr->armorpoints;
1969
1970 if (w_armor_percent.val != -1 && w_armor_percent.val == armor)
1971 return;
1972 w_armor_percent.val = armor;
1973
1974 // transfer the graphic key text to the widget
1975 HUlib_clearTextLine(&w_armor_percent);
1976
1977 if (!sts_always_red)
1978 {
1979 if (sts_pct_always_gray)
1980 w_armor_percent.cm = CR_GRAY;
1981 else
1982 w_armor_percent.cm = HU_GetArmorColor(armor, CR_BLUE2);
1983 }
1984
1985 HUlib_addCharToTextLine(&w_armor_percent, (char)('!' + 13));
1986 }
1987
HU_widget_draw_armor_percent(void)1988 void HU_widget_draw_armor_percent(void)
1989 {
1990 HUlib_drawTextLine(&w_armor_percent, false);
1991 }
1992
HU_widget_build_ammo_big(void)1993 void HU_widget_build_ammo_big(void)
1994 {
1995 char *s;
1996 char ammostr[80];
1997 int fullammo = plr->maxammo[weaponinfo[plr->readyweapon].ammo];
1998
1999 // clear the widgets internal line
2000 HUlib_clearTextLine(&w_ammo_big);
2001
2002 if (weaponinfo[plr->readyweapon].ammo != am_noammo && fullammo != 0)
2003 {
2004 int ammo = plr->ammo[weaponinfo[plr->readyweapon].ammo];
2005
2006 // build the numeric amount init string
2007 sprintf(ammostr, "%d", ammo);
2008
2009 // set the display color from the percentage of total ammo held
2010 if (!sts_always_red)
2011 w_ammo_big.cm = HU_GetAmmoColor(ammo, fullammo);
2012
2013 // transfer the init string to the widget
2014 s = ammostr;
2015 while (*s)
2016 HUlib_addCharToTextLine(&w_ammo_big, *(s++));
2017 }
2018 }
2019
HU_widget_draw_ammo_big(void)2020 void HU_widget_draw_ammo_big(void)
2021 {
2022 HUlib_drawTextLine(&w_ammo_big, false);
2023 }
2024
HU_widget_build_ammo_icon(void)2025 void HU_widget_build_ammo_icon(void)
2026 {
2027 int ammo = weaponinfo[plr->readyweapon].ammo;
2028
2029 if (w_ammo_icon.val != -1 && w_ammo_icon.val == ammo)
2030 return;
2031 w_ammo_icon.val = ammo;
2032
2033 if (ammo < NUMAMMO)
2034 {
2035 HUlib_clearTextLine(&w_ammo_icon);
2036 HUlib_addCharToTextLine(&w_ammo_icon, (char)('!' + ammo + 40));
2037 }
2038 else
2039 {
2040 HUlib_clearTextLine(&w_ammo_icon);
2041 }
2042 }
2043
HU_widget_draw_ammo_icon(void)2044 void HU_widget_draw_ammo_icon(void)
2045 {
2046 HUlib_drawTextLine(&w_ammo_icon, false);
2047 }
2048
HU_widget_build_gkeys(void)2049 void HU_widget_build_gkeys(void)
2050 {
2051 int i, k;
2052 char *s;
2053 char gkeysstr[80];
2054 int mask = 0;
2055
2056 // build text string whose characters call out graphic keys from fontk
2057 i = 0;
2058 for (k = 0; k < 6; k++)
2059 {
2060 // skip keys not possessed
2061 if (!plr->cards[k])
2062 continue;
2063
2064 gkeysstr[i++] = '!' + k; // key number plus '!' is char for key
2065 gkeysstr[i++] = ' '; // spacing
2066 gkeysstr[i++] = ' ';
2067
2068 mask |= (1 << k);
2069 }
2070
2071 if (w_keys_icon.val != -1 && w_keys_icon.val == mask)
2072 return;
2073 w_keys_icon.val = mask;
2074
2075 gkeysstr[i] = '\0';
2076 while (((--i) > 0) && (gkeysstr[i] == ' '))
2077 gkeysstr[i] = '\0';
2078
2079 // clear the widget strings
2080 HUlib_clearTextLine(&w_keys_icon);
2081 // transfer the graphic key text to the widget
2082 s = gkeysstr;
2083 while (*s)
2084 HUlib_addCharToTextLine(&w_keys_icon, *(s++));
2085
2086 }
2087
HU_widget_draw_gkeys(void)2088 void HU_widget_draw_gkeys(void)
2089 {
2090 HUlib_drawTextLine(&w_keys_icon, false);
2091 }
2092
2093 //
2094 // HU_Drawer()
2095 //
2096 // Draw all the pieces of the heads-up display
2097 //
2098 // Passed nothing, returns nothing
2099 //
HU_Drawer(void)2100 void HU_Drawer(void)
2101 {
2102 char *s;
2103 player_t *plr;
2104 //jff 3/4/98 speed update up for slow systems
2105 //e6y: speed update for uncapped framerate
2106 static dboolean needupdate = false;
2107 if (realframe) needupdate = !needupdate;
2108
2109 // don't draw anything if there's a fullscreen menu up
2110 if (menuactive == mnact_full)
2111 return;
2112
2113 plr = &players[displayplayer]; // killough 3/7/98
2114 // draw the automap widgets if automap is displayed
2115 if (automapmode & am_active)
2116 {
2117 if (!(automapmode & am_overlay) || (viewheight != SCREENHEIGHT))//!hud_displayed)
2118 {
2119 // map title
2120 HUlib_drawTextLine(&w_title, false);
2121 }
2122
2123 //jff 2/16/98 output new coord display
2124 // x-coord
2125 if (map_point_coordinates)
2126 {
2127
2128 //e6y: speedup
2129 if (!realframe)
2130 {
2131 HUlib_drawTextLine(&w_coordx, false);
2132 HUlib_drawTextLine(&w_coordy, false);
2133 HUlib_drawTextLine(&w_coordz, false);
2134 }
2135 else
2136 {
2137 sprintf(hud_coordstrx,"X: %-5d", (plr->mo->x)>>FRACBITS);
2138 HUlib_clearTextLine(&w_coordx);
2139 s = hud_coordstrx;
2140 while (*s)
2141 HUlib_addCharToTextLine(&w_coordx, *(s++));
2142 HUlib_drawTextLine(&w_coordx, false);
2143
2144 //jff 3/3/98 split coord display into x,y,z lines
2145 // y-coord
2146 sprintf(hud_coordstry,"Y: %-5d", (plr->mo->y)>>FRACBITS);
2147 HUlib_clearTextLine(&w_coordy);
2148 s = hud_coordstry;
2149 while (*s)
2150 HUlib_addCharToTextLine(&w_coordy, *(s++));
2151 HUlib_drawTextLine(&w_coordy, false);
2152
2153 //jff 3/3/98 split coord display into x,y,z lines
2154 //jff 2/22/98 added z
2155 // z-coord
2156 sprintf(hud_coordstrz,"Z: %-5d", (plr->mo->z)>>FRACBITS);
2157 HUlib_clearTextLine(&w_coordz);
2158 s = hud_coordstrz;
2159 while (*s)
2160 HUlib_addCharToTextLine(&w_coordz, *(s++));
2161 HUlib_drawTextLine(&w_coordz, false);
2162 }
2163 }
2164
2165 if (map_level_stat)
2166 {
2167 static char str[32];
2168 int time = leveltime / TICRATE;
2169 int ttime = (totalleveltimes + leveltime) / TICRATE;
2170
2171 sprintf(str, "Monsters: \x1b%c%d/%d", '0' + hudcolor_mapstat_value,
2172 players[consoleplayer].killcount - players[consoleplayer].resurectedkillcount,
2173 totalkills);
2174 HUlib_clearTextLine(&w_map_monsters);
2175 s = str;
2176 while (*s)
2177 HUlib_addCharToTextLine(&w_map_monsters, *(s++));
2178 HUlib_drawTextLine(&w_map_monsters, false);
2179
2180 sprintf(str, "Secrets: \x1b%c%d/%d", '0' + hudcolor_mapstat_value,
2181 players[consoleplayer].secretcount, totalsecret);
2182 HUlib_clearTextLine(&w_map_secrets);
2183 s = str;
2184 while (*s)
2185 HUlib_addCharToTextLine(&w_map_secrets, *(s++));
2186 HUlib_drawTextLine(&w_map_secrets, false);
2187
2188 sprintf(str, "Items: \x1b%c%d/%d", '0' + hudcolor_mapstat_value,
2189 players[consoleplayer].itemcount, totalitems);
2190 HUlib_clearTextLine(&w_map_items);
2191 s = str;
2192 while (*s)
2193 HUlib_addCharToTextLine(&w_map_items, *(s++));
2194 HUlib_drawTextLine(&w_map_items, false);
2195
2196 sprintf(str, "%02d:%02d:%02d", time/3600, (time%3600)/60, time%60);
2197 HUlib_clearTextLine(&w_map_time);
2198 s = str;
2199 while (*s)
2200 HUlib_addCharToTextLine(&w_map_time, *(s++));
2201 HUlib_drawTextLine(&w_map_time, false);
2202
2203 if (totalleveltimes > 0)
2204 {
2205 sprintf(str, "%02d:%02d:%02d", ttime/3600, (ttime%3600)/60, ttime%60);
2206 HUlib_clearTextLine(&w_map_totaltime);
2207 s = str;
2208 while (*s)
2209 HUlib_addCharToTextLine(&w_map_totaltime, *(s++));
2210 HUlib_drawTextLine(&w_map_totaltime, false);
2211 }
2212 }
2213 }
2214
2215 // draw the weapon/health/ammo/armor/kills/keys displays if optioned
2216 //jff 2/17/98 allow new hud stuff to be turned off
2217 // killough 2/21/98: really allow new hud stuff to be turned off COMPLETELY
2218 if
2219 (
2220 hud_num > 0 && // hud optioned on
2221 hud_displayed && // hud on from fullscreen key
2222 viewheight==SCREENHEIGHT && // fullscreen mode is active
2223 (!(automapmode & am_active) || // automap is not active
2224 (automapmode & am_overlay))
2225 )
2226 {
2227 int i;
2228
2229 HU_MoveHud(false); // insure HUD display coords are correct
2230
2231 if (hud_current)
2232 {
2233 for (i = 0; i < hud_current->count; i++)
2234 {
2235 if (hud_current->items[i].build && hud_current->items[i].draw)
2236 {
2237 if (realframe)
2238 {
2239 hud_current->items[i].build();
2240 }
2241 hud_current->items[i].draw();
2242 }
2243 }
2244 }
2245
2246 //e6y
2247 if (traces_present)
2248 {
2249 int k, num = 0;
2250 for(k = 0; k < NUMTRACES; k++)
2251 {
2252 if (traces[k].count)
2253 {
2254 if (realframe)
2255 {
2256 w_traces[num].y = w_traces[0].y - num * 8;
2257
2258 if (traces[k].ApplyFunc)
2259 traces[k].ApplyFunc(k);
2260
2261 HUlib_clearTextLine(&w_traces[num]);
2262 s = traces[k].hudstr;
2263 while (*s)
2264 HUlib_addCharToTextLine(&w_traces[num], *(s++));
2265
2266 if (traces[k].ResetFunc)
2267 traces[k].ResetFunc(k);
2268 }
2269 HUlib_drawTextLine(&w_traces[num], false);
2270 num++;
2271 }
2272 }
2273 }
2274
2275 }
2276
2277 //jff 3/4/98 display last to give priority
2278 HU_Erase(); // jff 4/24/98 Erase current lines before drawing current
2279 // needed when screen not fullsize
2280
2281 //jff 4/21/98 if setup has disabled message list while active, turn it off
2282 if (hud_msg_lines<=1)
2283 message_list = false;
2284
2285 // if the message review not enabled, show the standard message widget
2286 if (!message_list)
2287 HUlib_drawSText(&w_message);
2288
2289 //e6y
2290 if (messagecenter_counter)
2291 HUlib_drawTextLine(&w_centermsg, false);
2292
2293 // if the message review is enabled show the scrolling message review
2294 if (hud_msg_lines>1 && message_list)
2295 HUlib_drawMText(&w_rtext);
2296
2297 // display the interactive buffer for chat entry
2298 HUlib_drawIText(&w_chat);
2299 }
2300
2301 //
2302 // HU_Erase()
2303 //
2304 // Erase hud display lines that can be trashed by small screen display
2305 //
2306 // Passed nothing, returns nothing
2307 //
HU_Erase(void)2308 void HU_Erase(void)
2309 {
2310 // erase the message display or the message review display
2311 if (!message_list)
2312 HUlib_eraseSText(&w_message);
2313 else
2314 HUlib_eraseMText(&w_rtext);
2315
2316 //e6y
2317 if (messagecenter_counter)
2318 HUlib_eraseTextLine(&w_centermsg);
2319
2320 // erase the interactive text buffer for chat entry
2321 HUlib_eraseIText(&w_chat);
2322
2323 // erase the automap title
2324 HUlib_eraseTextLine(&w_title);
2325 }
2326
2327 //
2328 // HU_Ticker()
2329 //
2330 // Update the hud displays once per frame
2331 //
2332 // Passed nothing, returns nothing
2333 //
2334 static dboolean bsdown; // Is backspace down?
2335 static int bscounter;
2336
HU_Ticker(void)2337 void HU_Ticker(void)
2338 {
2339 int i, rc;
2340 char c;
2341
2342 // tick down message counter if message is up
2343 if (message_counter && !--message_counter)
2344 {
2345 message_on = false;
2346 message_nottobefuckedwith = false;
2347 }
2348 if (bsdown && bscounter++ > 9) {
2349 HUlib_keyInIText(&w_chat, (unsigned char)key_backspace);
2350 bscounter = 8;
2351 }
2352
2353 // if messages on, or "Messages Off" is being displayed
2354 // this allows the notification of turning messages off to be seen
2355 if (showMessages || message_dontfuckwithme)
2356 {
2357 // display message if necessary
2358 if ((plr->message && !message_nottobefuckedwith)
2359 || (plr->message && message_dontfuckwithme))
2360 {
2361 //post the message to the message widget
2362 HUlib_addMessageToSText(&w_message, 0, plr->message);
2363 //jff 2/26/98 add message to refresh text widget too
2364 HUlib_addMessageToMText(&w_rtext, 0, plr->message);
2365
2366 // clear the message to avoid posting multiple times
2367 plr->message = 0;
2368 // note a message is displayed
2369 message_on = true;
2370 // start the message persistence counter
2371 message_counter = HU_MSGTIMEOUT;
2372 // transfer "Messages Off" exception to the "being displayed" variable
2373 message_nottobefuckedwith = message_dontfuckwithme;
2374 // clear the flag that "Messages Off" is being posted
2375 message_dontfuckwithme = 0;
2376 }
2377 }
2378 //e6y
2379 if (messagecenter_counter)
2380 messagecenter_counter--;
2381 if (/*showMessages && */plr->centermessage)
2382 {
2383 const char *s = plr->centermessage;
2384 HUlib_clearTextLine(&w_centermsg);
2385 while (*s)
2386 {
2387 HUlib_addCharToTextLine(&w_centermsg, *(s++));
2388 }
2389 HUlib_setTextXCenter(&w_centermsg);
2390 plr->centermessage = NULL;
2391 messagecenter_counter = HU_MSGCENTERTIMEOUT;
2392
2393 S_StartSound(NULL, sfx_secret);
2394 }
2395
2396 // check for incoming chat characters
2397 if (netgame)
2398 {
2399 for (i=0; i<MAXPLAYERS; i++)
2400 {
2401 if (!playeringame[i])
2402 continue;
2403 if (i != consoleplayer
2404 && (c = players[i].cmd.chatchar))
2405 {
2406 if (c <= HU_BROADCAST)
2407 chat_dest[i] = c;
2408 else
2409 {
2410 if (c >= 'a' && c <= 'z')
2411 c = (char) shiftxform[(unsigned char) c];
2412 rc = HUlib_keyInIText(&w_inputbuffer[i], c);
2413 if (rc && c == KEYD_ENTER)
2414 {
2415 if (w_inputbuffer[i].l.len
2416 && (chat_dest[i] == consoleplayer+1
2417 || chat_dest[i] == HU_BROADCAST))
2418 {
2419 HUlib_addMessageToSText(&w_message,
2420 player_names[i],
2421 w_inputbuffer[i].l.l);
2422
2423 message_nottobefuckedwith = true;
2424 message_on = true;
2425 message_counter = HU_MSGTIMEOUT;
2426 if ( gamemode == commercial )
2427 S_StartSound(0, sfx_radio);
2428 else
2429 S_StartSound(0, sfx_tink);
2430 }
2431 HUlib_resetIText(&w_inputbuffer[i]);
2432 }
2433 }
2434 players[i].cmd.chatchar = 0;
2435 }
2436 }
2437 }
2438 }
2439
2440 #define QUEUESIZE 128
2441
2442 static char chatchars[QUEUESIZE];
2443 static int head = 0;
2444 static int tail = 0;
2445
2446 //
2447 // HU_queueChatChar()
2448 //
2449 // Add an incoming character to the circular chat queue
2450 //
2451 // Passed the character to queue, returns nothing
2452 //
HU_queueChatChar(char c)2453 static void HU_queueChatChar(char c)
2454 {
2455 if (((head + 1) & (QUEUESIZE-1)) == tail)
2456 {
2457 plr->message = HUSTR_MSGU;
2458 }
2459 else
2460 {
2461 chatchars[head] = c;
2462 head = (head + 1) & (QUEUESIZE-1);
2463 }
2464 }
2465
2466 //
2467 // HU_dequeueChatChar()
2468 //
2469 // Remove the earliest added character from the circular chat queue
2470 //
2471 // Passed nothing, returns the character dequeued
2472 //
HU_dequeueChatChar(void)2473 char HU_dequeueChatChar(void)
2474 {
2475 char c;
2476
2477 if (head != tail)
2478 {
2479 c = chatchars[tail];
2480 tail = (tail + 1) & (QUEUESIZE-1);
2481 }
2482 else
2483 {
2484 c = 0;
2485 }
2486 return c;
2487 }
2488
2489 //
2490 // HU_Responder()
2491 //
2492 // Responds to input events that affect the heads up displays
2493 //
2494 // Passed the event to respond to, returns true if the event was handled
2495 //
HU_Responder(event_t * ev)2496 dboolean HU_Responder(event_t *ev)
2497 {
2498
2499 static char lastmessage[HU_MAXLINELENGTH+1];
2500 const char* macromessage; // CPhipps - const char*
2501 dboolean eatkey = false;
2502 static dboolean shiftdown = false;
2503 static dboolean altdown = false;
2504 unsigned char c;
2505 int i;
2506 int numplayers;
2507
2508 static int num_nobrainers = 0;
2509
2510 numplayers = 0;
2511 for (i=0 ; i<MAXPLAYERS ; i++)
2512 numplayers += playeringame[i];
2513
2514 if (ev->data1 == key_shift)
2515 {
2516 shiftdown = ev->type == ev_keydown;
2517 return false;
2518 }
2519 else if (ev->data1 == key_alt)
2520 {
2521 altdown = ev->type == ev_keydown;
2522 return false;
2523 }
2524 else if (ev->data1 == key_backspace)
2525 {
2526 bsdown = ev->type == ev_keydown;
2527 bscounter = 0;
2528 }
2529
2530 if (ev->type != ev_keydown)
2531 return false;
2532
2533 if (!chat_on)
2534 {
2535 if (ev->data1 == key_enter) // phares
2536 {
2537 #ifndef INSTRUMENTED // never turn on message review if INSTRUMENTED defined
2538 if (hud_msg_lines>1) // it posts multi-line messages that will trash
2539 {
2540 if (message_list) HU_Erase(); //jff 4/28/98 erase behind messages
2541 message_list = !message_list; //jff 2/26/98 toggle list of messages
2542 }
2543 #endif
2544 if (!message_list) // if not message list, refresh message
2545 {
2546 message_on = true;
2547 message_counter = HU_MSGTIMEOUT;
2548 }
2549 eatkey = true;
2550 }//jff 2/26/98 no chat if message review is displayed
2551 // killough 10/02/98: no chat if demo playback
2552 // no chat in -solo-net mode
2553 else if (!demoplayback && !message_list && netgame && numplayers > 1)
2554 {
2555 if (ev->data1 == key_chat)
2556 {
2557 eatkey = chat_on = true;
2558 HUlib_resetIText(&w_chat);
2559 HU_queueChatChar(HU_BROADCAST);
2560 }
2561 else if (numplayers > 2)
2562 {
2563 for (i=0; i<MAXPLAYERS ; i++)
2564 {
2565 if (ev->data1 == destination_keys[i])
2566 {
2567 if (playeringame[i] && i!=consoleplayer)
2568 {
2569 eatkey = chat_on = true;
2570 HUlib_resetIText(&w_chat);
2571 HU_queueChatChar((char)(i+1));
2572 break;
2573 }
2574 else if (i == consoleplayer)
2575 {
2576 num_nobrainers++;
2577 if (num_nobrainers < 3)
2578 plr->message = HUSTR_TALKTOSELF1;
2579 else if (num_nobrainers < 6)
2580 plr->message = HUSTR_TALKTOSELF2;
2581 else if (num_nobrainers < 9)
2582 plr->message = HUSTR_TALKTOSELF3;
2583 else if (num_nobrainers < 32)
2584 plr->message = HUSTR_TALKTOSELF4;
2585 else
2586 plr->message = HUSTR_TALKTOSELF5;
2587 }
2588 }
2589 }
2590 }
2591 }
2592 }//jff 2/26/98 no chat functions if message review is displayed
2593 else if (!message_list)
2594 {
2595 c = ev->data1;
2596 // send a macro
2597 if (altdown)
2598 {
2599 c = c - '0';
2600 if (c > 9)
2601 return false;
2602 macromessage = chat_macros[c];
2603
2604 // kill last message with a '\n'
2605 HU_queueChatChar((char)key_enter); // DEBUG!!! // phares
2606
2607 // send the macro message
2608 while (*macromessage)
2609 HU_queueChatChar(*macromessage++);
2610 HU_queueChatChar((char)key_enter); // phares
2611
2612 // leave chat mode and notify that it was sent
2613 chat_on = false;
2614 strcpy(lastmessage, chat_macros[c]);
2615 plr->message = lastmessage;
2616 eatkey = true;
2617 }
2618 else
2619 {
2620 if (shiftdown || (c >= 'a' && c <= 'z'))
2621 c = shiftxform[c];
2622 eatkey = HUlib_keyInIText(&w_chat, c);
2623 if (eatkey)
2624 HU_queueChatChar(c);
2625
2626 if (c == key_enter) // phares
2627 {
2628 chat_on = false;
2629 if (w_chat.l.len)
2630 {
2631 strcpy(lastmessage, w_chat.l.l);
2632 plr->message = lastmessage;
2633 }
2634 }
2635 else if (c == key_escape) // phares
2636 chat_on = false;
2637 }
2638 }
2639 return eatkey;
2640 }
2641