1 /* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
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
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 * DESCRIPTION: Heads-up displays
29 *-----------------------------------------------------------------------------
32 // killough 5/3/98: remove unnecessary headers
37 #include "st_stuff.h" /* jff 2/16/98 need loc of status bar */
42 //#include "d_deh.h" /* Ty 03/27/98 - externalization of mapnamesx arrays */
46 // global heads up display controls
48 int hud_active
; //jff 2/17/98 controls heads-up display mode
49 int hud_displayed
; //jff 2/23/98 turns heads-up display on/off
50 int hud_nosecrets
; //jff 2/18/98 allows secrets line to be disabled in HUD
51 int hud_distributed
; //jff 3/4/98 display HUD in different places on screen
52 int hud_graph_keys
=1; //jff 3/7/98 display HUD keys as graphics
55 // Locally used constants, shortcuts.
58 // These four shortcuts modifed to reflect char ** of mapnamesx[]
59 #define HU_TITLE (*mapnames[(gameepisode-1)*9+gamemap-1])
60 #define HU_TITLE2 (*mapnames2[gamemap-1])
61 #define HU_TITLEP (*mapnamesp[gamemap-1])
62 #define HU_TITLET (*mapnamest[gamemap-1])
63 #define HU_TITLEHEIGHT 1
65 //jff 2/16/98 change 167 to ST_Y-1
66 // CPhipps - changed to ST_TY
67 // proff - changed to 200-ST_HEIGHT for stretching
68 #define HU_TITLEY ((200-ST_HEIGHT) - 1 - SHORT(hu_font[0].height))
70 //jff 2/16/98 add coord text widget coordinates
71 // proff - changed to SCREENWIDTH to 320 for stretching
72 #define HU_COORDX (320 - 13*SHORT(hu_font2['A'-HU_FONTSTART].width))
73 //jff 3/3/98 split coord widget into three lines in upper right of screen
74 #define HU_COORDX_Y (1 + 0*SHORT(hu_font['A'-HU_FONTSTART].height))
75 #define HU_COORDY_Y (2 + 1*SHORT(hu_font['A'-HU_FONTSTART].height))
76 #define HU_COORDZ_Y (3 + 2*SHORT(hu_font['A'-HU_FONTSTART].height))
78 //jff 2/16/98 add ammo, health, armor widgets, 2/22/98 less gap
80 #define HU_HUDHEIGHT (6*HU_GAPY)
82 #define HU_HUDY (200-HU_HUDHEIGHT-1)
83 #define HU_MONSECX (HU_HUDX)
84 #define HU_MONSECY (HU_HUDY+0*HU_GAPY)
85 #define HU_KEYSX (HU_HUDX)
86 //jff 3/7/98 add offset for graphic key widget
87 #define HU_KEYSGX (HU_HUDX+4*SHORT(hu_font2['A'-HU_FONTSTART].width))
88 #define HU_KEYSY (HU_HUDY+1*HU_GAPY)
89 #define HU_WEAPX (HU_HUDX)
90 #define HU_WEAPY (HU_HUDY+2*HU_GAPY)
91 #define HU_AMMOX (HU_HUDX)
92 #define HU_AMMOY (HU_HUDY+3*HU_GAPY)
93 #define HU_HEALTHX (HU_HUDX)
94 #define HU_HEALTHY (HU_HUDY+4*HU_GAPY)
95 #define HU_ARMORX (HU_HUDX)
96 #define HU_ARMORY (HU_HUDY+5*HU_GAPY)
98 //jff 3/4/98 distributed HUD positions
100 #define HU_HUDY_LL (200-2*HU_GAPY-1)
101 // proff/nicolas 09/20/98: Changed for high-res
102 #define HU_HUDX_LR (320-120)
103 #define HU_HUDY_LR (200-2*HU_GAPY-1)
104 // proff/nicolas 09/20/98: Changed for high-res
105 #define HU_HUDX_UR (320-96)
107 #define HU_MONSECX_D (HU_HUDX_LL)
108 #define HU_MONSECY_D (HU_HUDY_LL+0*HU_GAPY)
109 #define HU_KEYSX_D (HU_HUDX_LL)
110 #define HU_KEYSGX_D (HU_HUDX_LL+4*SHORT(hu_font2['A'-HU_FONTSTART].width))
111 #define HU_KEYSY_D (HU_HUDY_LL+1*HU_GAPY)
112 #define HU_WEAPX_D (HU_HUDX_LR)
113 #define HU_WEAPY_D (HU_HUDY_LR+0*HU_GAPY)
114 #define HU_AMMOX_D (HU_HUDX_LR)
115 #define HU_AMMOY_D (HU_HUDY_LR+1*HU_GAPY)
116 #define HU_HEALTHX_D (HU_HUDX_UR)
117 #define HU_HEALTHY_D (HU_HUDY_UR+0*HU_GAPY)
118 #define HU_ARMORX_D (HU_HUDX_UR)
119 #define HU_ARMORY_D (HU_HUDY_UR+1*HU_GAPY)
121 //#define HU_INPUTTOGGLE 't' // not used // phares
122 #define HU_INPUTX HU_MSGX
123 #define HU_INPUTY (HU_MSGY + HU_MSGHEIGHT*(SHORT(hu_font[0].height) +1))
124 #define HU_INPUTWIDTH 64
125 #define HU_INPUTHEIGHT 1
127 #define key_alt KEY_RALT
128 #define key_shift KEY_RSHIFT
130 const char* chat_macros
[] =
131 // Ty 03/27/98 - *not* externalized
132 // CPhipps - const char*
146 const char* player_names
[] =
147 // Ty 03/27/98 - *not* externalized
148 // CPhipps - const char*
156 //jff 3/17/98 translate player colmap to text color ranges
157 int plyrcoltran
[MAXPLAYERS
]={CR_GREEN
,CR_GRAY
,CR_BROWN
,CR_RED
};
159 char chat_char
; // remove later.
160 static player_t
* plr
;
163 patchnum_t hu_font
[HU_FONTSIZE
];
164 patchnum_t
*hu_font2
;
165 patchnum_t
*hu_fontk
;//jff 3/7/98 added for graphic key indicators
166 patchnum_t hu_msgbg
[9]; //jff 2/26/98 add patches for message background
169 static hu_textline_t w_title
;
170 static hu_stext_t w_message
;
171 static hu_itext_t w_chat
;
172 static hu_itext_t w_inputbuffer
[MAXPLAYERS
];
173 static hu_textline_t w_coordx
; //jff 2/16/98 new coord widget for automap
174 static hu_textline_t w_coordy
; //jff 3/3/98 split coord widgets automap
175 static hu_textline_t w_coordz
; //jff 3/3/98 split coord widgets automap
176 static hu_textline_t w_ammo
; //jff 2/16/98 new ammo widget for hud
177 static hu_textline_t w_health
; //jff 2/16/98 new health widget for hud
178 static hu_textline_t w_armor
; //jff 2/16/98 new armor widget for hud
179 static hu_textline_t w_weapon
; //jff 2/16/98 new weapon widget for hud
180 static hu_textline_t w_keys
; //jff 2/16/98 new keys widget for hud
181 static hu_textline_t w_gkeys
; //jff 3/7/98 graphic keys widget for hud
182 static hu_textline_t w_monsec
; //jff 2/16/98 new kill/secret widget for hud
183 static hu_mtext_t w_rtext
; //jff 2/26/98 text message refresh widget
185 static boolean always_off
= false;
186 static char chat_dest
[MAXPLAYERS
];
188 static boolean message_on
;
189 static boolean message_list
; //2/26/98 enable showing list of messages
190 boolean message_dontfuckwithme
;
191 static boolean message_nottobefuckedwith
;
192 static int message_counter
;
193 extern int showMessages
;
194 extern boolean automapactive
;
195 static boolean headsupactive
= false;
197 //jff 2/16/98 hud supported automap colors added
198 int hudcolor_titl
; // color range of automap level title
199 int hudcolor_xyco
; // color range of new coords on automap
200 //jff 2/16/98 hud text colors, controls added
201 int hudcolor_mesg
; // color range of scrolling messages
202 int hudcolor_chat
; // color range of chat lines
203 int hud_msg_lines
; // number of message lines in window
204 //jff 2/26/98 hud text colors, controls added
205 int hudcolor_list
; // list of messages color
206 int hud_list_bgon
; // enable for solid window background for message list
208 //jff 2/16/98 initialization strings for ammo, health, armor widgets
209 static char *hud_coordstrx
;
210 static char *hud_coordstry
;
211 static char *hud_coordstrz
;
212 static char *hud_ammostr
;
213 static char *hud_healthstr
;
214 static char *hud_armorstr
;
215 static char *hud_weapstr
;
216 static char *hud_keysstr
;
217 static char *hud_gkeysstr
; //jff 3/7/98 add support for graphic key display
218 static char *hud_monsecstr
;
220 //jff 2/16/98 declaration of color switch points
222 extern int ammo_yellow
;
223 extern int health_red
;
224 extern int health_yellow
;
225 extern int health_green
;
226 extern int armor_red
;
227 extern int armor_yellow
;
228 extern int armor_green
;
231 // jff 5/10/98 french support removed,
232 // as it was not being used and couldn't be easily tested
234 const char* shiftxform
;
236 const char english_shiftxform
[] =
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,
243 ' ', '!', '"', '#', '$', '%', '&',
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',
268 '!', // shift-backslash - OH MY GOD DOES WATCOM SUCK
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
280 // Initialize the heads-up display, text that overwrites the primary display
282 // Passed nothing, returns nothing
290 shiftxform
= english_shiftxform
;
292 // malloc all the strings, trying to get size down
293 hud_ammostr
=malloc(80*sizeof(char));
294 hud_healthstr
=malloc(80*sizeof(char));
295 hud_armorstr
=malloc(80*sizeof(char));
296 hud_weapstr
=malloc(80*sizeof(char));
297 hud_keysstr
=malloc(80*sizeof(char));
298 hud_gkeysstr
=malloc(80*sizeof(char));
299 hud_monsecstr
=malloc(80*sizeof(char));
300 hud_coordstrx
=malloc(32*sizeof(char));
301 hud_coordstry
=malloc(32*sizeof(char));
302 hud_coordstrz
=malloc(32*sizeof(char));
303 hu_fontk
=malloc(HU_FONTSIZE
*sizeof(patchnum_t
));
304 hu_font2
=malloc(HU_FONTSIZE
*sizeof(patchnum_t
));
306 // load the heads-up font
308 for (i
=0;i
<HU_FONTSIZE
;i
++,j
++)
310 if ('0'<=j
&& j
<='9')
312 snprintf(buffer
, sizeof(buffer
), "DIG%d",j
-48);
313 R_SetPatchNum(hu_font2
+i
, buffer
);
314 snprintf(buffer
, sizeof(buffer
), "STCFN%s%d", (j
/10>0?"0":"00"), j
); //NOTE ROCKHACK: "STCFN%.3d"
315 R_SetPatchNum(&hu_font
[i
], buffer
);
317 else if ('A'<=j
&& j
<='Z')
319 snprintf(buffer
, sizeof(buffer
), "DIG%c",j
);
320 R_SetPatchNum(hu_font2
+i
, buffer
);
321 snprintf(buffer
, sizeof(buffer
), "STCFN%s%d", (j
/10>0?"0":"00"), j
); //NOTE ROCKHACK: "STCFN%.3d"
322 R_SetPatchNum(&hu_font
[i
], buffer
);
326 R_SetPatchNum(hu_font2
+i
, "DIG45");
327 R_SetPatchNum(&hu_font
[i
], "STCFN045");
331 R_SetPatchNum(hu_font2
+i
, "DIG47");
332 R_SetPatchNum(&hu_font
[i
], "STCFN047");
336 R_SetPatchNum(hu_font2
+i
, "DIG58");
337 R_SetPatchNum(&hu_font
[i
], "STCFN058");
341 R_SetPatchNum(hu_font2
+i
, "DIG91");
342 R_SetPatchNum(&hu_font
[i
], "STCFN091");
346 R_SetPatchNum(hu_font2
+i
, "DIG93");
347 R_SetPatchNum(&hu_font
[i
], "STCFN093");
351 snprintf(buffer
, sizeof(buffer
), "STCFN%s%d", (j
/10>0?"0":"00"), j
); //NOTE ROCKHACK: "STCFN%.3d"
352 R_SetPatchNum(hu_font2
+i
, buffer
);
353 R_SetPatchNum(&hu_font
[i
], buffer
);
354 //jff 2/23/98 make all font chars defined, useful or not
358 snprintf(buffer
, sizeof(buffer
), "STBR%d", j
); //NOTE: "STBR%.3d"
359 R_SetPatchNum(hu_font2
+i
, buffer
);
360 R_SetPatchNum(&hu_font
[i
], buffer
);
363 hu_font
[i
] = hu_font
[0]; //jff 2/16/98 account for gap
366 // CPhipps - load patches for message background
367 for (i
=0; i
<9; i
++) {
368 snprintf(buffer
, sizeof(buffer
), "BOX%c%c", "UCL"[i
/3], "LCR"[i
%3]);
369 R_SetPatchNum(&hu_msgbg
[i
], buffer
);
372 // CPhipps - load patches for keys and double keys
373 for (i
=0; i
<6; i
++) {
374 snprintf(buffer
, sizeof(buffer
), "STKEYS%d", i
);
375 R_SetPatchNum(hu_fontk
+i
, buffer
);
382 // Make the heads-up displays inactive
384 // Passed nothing, returns nothing
388 headsupactive
= false;
394 // Create and initialize the heads-up widgets, software machines to
395 // maintain, update, and display information over the primary display
397 // This routine must be called after any change to the heads up configuration
398 // in order for the changes to take effect in the actual displays
400 // Passed nothing, returns nothing
406 const char* s
; /* cph - const */
408 if (headsupactive
) // stop before starting
411 plr
= &players
[displayplayer
]; // killough 3/7/98
413 message_dontfuckwithme
= false;
414 message_nottobefuckedwith
= false;
417 // create the message widget
418 // messages to player in upper-left of screen
431 //jff 2/16/98 added some HUD widgets
432 // create the map title widget - map title display in lower left of automap
443 // create the hud health widget
444 // bargraph and number for amount of health,
445 // lower left or upper right of screen
449 hud_distributed
? HU_HEALTHX_D
: HU_HEALTHX
, //3/4/98 distribute
450 hud_distributed
? HU_HEALTHY_D
: HU_HEALTHY
,
456 // create the hud armor widget
457 // bargraph and number for amount of armor,
458 // lower left or upper right of screen
462 hud_distributed
? HU_ARMORX_D
: HU_ARMORX
, //3/4/98 distribute
463 hud_distributed
? HU_ARMORY_D
: HU_ARMORY
,
469 // create the hud ammo widget
470 // bargraph and number for amount of ammo for current weapon,
471 // lower left or lower right of screen
475 hud_distributed
? HU_AMMOX_D
: HU_AMMOX
, //3/4/98 distribute
476 hud_distributed
? HU_AMMOY_D
: HU_AMMOY
,
482 // create the hud weapons widget
483 // list of numbers of weapons possessed
484 // lower left or lower right of screen
488 hud_distributed
? HU_WEAPX_D
: HU_WEAPX
, //3/4/98 distribute
489 hud_distributed
? HU_WEAPY_D
: HU_WEAPY
,
495 // create the hud keys widget
496 // display of key letters possessed
497 // lower left of screen
501 hud_distributed
? HU_KEYSX_D
: HU_KEYSX
, //3/4/98 distribute
502 hud_distributed
? HU_KEYSY_D
: HU_KEYSY
,
508 // create the hud graphic keys widget
509 // display of key graphics possessed
510 // lower left of screen
514 hud_distributed
? HU_KEYSGX_D
: HU_KEYSGX
, //3/4/98 distribute
515 hud_distributed
? HU_KEYSY_D
: HU_KEYSY
,
521 // create the hud monster/secret widget
522 // totals and current values for kills, items, secrets
523 // lower left of screen
527 hud_distributed
? HU_MONSECX_D
: HU_MONSECX
, //3/4/98 distribute
528 hud_distributed
? HU_MONSECY_D
: HU_MONSECY
,
534 // create the hud text refresh widget
535 // scrolling display of last hud_msg_lines messages received
536 if (hud_msg_lines
>HU_MAXMESSAGES
)
537 hud_msg_lines
=HU_MAXMESSAGES
;
538 //jff 4/21/98 if setup has disabled message list while active, turn it off
539 message_list
= hud_msg_lines
> 1; //jff 8/8/98 initialize both ways
540 //jff 2/26/98 add the text refresh widget initialization
548 (hud_msg_lines
+2)*HU_REFRESHSPACING
,
556 // initialize the automap's level title widget
557 if (gamestate
== GS_LEVEL
) /* cph - stop SEGV here when not in level */
567 default: // Ty 08/27/98 - modified to check mission for TNT/Plutonia
568 s
= (gamemission
==pack_tnt
) ? HU_TITLET
:
569 (gamemission
==pack_plut
) ? HU_TITLEP
: HU_TITLE2
;
573 HUlib_addCharToTextLine(&w_title
, *(s
++));
575 // create the automaps coordinate widget
576 // jff 3/3/98 split coord widget into three lines: x,y,z
606 // initialize the automaps coordinate widget
607 //jff 3/3/98 split coordstr widget into 3 parts
608 snprintf(hud_coordstrx
,32*sizeof(char),"X: %d",0); //jff 2/22/98 added z
611 HUlib_addCharToTextLine(&w_coordx
, *(s
++));
612 snprintf(hud_coordstry
,32*sizeof(char),"Y: %d",0); //jff 3/3/98 split x,y,z
615 HUlib_addCharToTextLine(&w_coordy
, *(s
++));
616 snprintf(hud_coordstrz
,32*sizeof(char),"Z: %d",0); //jff 3/3/98 split x,y,z
619 HUlib_addCharToTextLine(&w_coordz
, *(s
++));
621 //jff 2/16/98 initialize ammo widget
622 strcpy(hud_ammostr
,"AMM ");
625 HUlib_addCharToTextLine(&w_ammo
, *(s
++));
627 //jff 2/16/98 initialize health widget
628 strcpy(hud_healthstr
,"HEL ");
631 HUlib_addCharToTextLine(&w_health
, *(s
++));
633 //jff 2/16/98 initialize armor widget
634 strcpy(hud_armorstr
,"ARM ");
637 HUlib_addCharToTextLine(&w_armor
, *(s
++));
639 //jff 2/17/98 initialize weapons widget
640 strcpy(hud_weapstr
,"WEA ");
643 HUlib_addCharToTextLine(&w_weapon
, *(s
++));
645 //jff 2/17/98 initialize keys widget
646 if (!deathmatch
) //jff 3/17/98 show frags in deathmatch mode
647 strcpy(hud_keysstr
,"KEY ");
649 strcpy(hud_keysstr
,"FRG ");
652 HUlib_addCharToTextLine(&w_keys
, *(s
++));
654 //jff 2/17/98 initialize graphic keys widget
655 strcpy(hud_gkeysstr
," ");
658 HUlib_addCharToTextLine(&w_gkeys
, *(s
++));
660 //jff 2/17/98 initialize kills/items/secret widget
661 strcpy(hud_monsecstr
,"STS ");
664 HUlib_addCharToTextLine(&w_monsec
, *(s
++));
666 // create the chat widget
678 // create the inputbuffer widgets, one per player
679 for (i
=0 ; i
<MAXPLAYERS
; i
++)
691 // now allow the heads-up display to run
692 headsupactive
= true;
698 // Move the HUD display from distributed to compact mode or vice-versa
700 // Passed nothing, returns nothing
702 //jff 3/9/98 create this externally callable to avoid glitch
703 // when menu scatter's HUD due to delay in change of position
705 void HU_MoveHud(void)
707 static int ohud_distributed
=-1;
709 //jff 3/4/98 move displays around on F5 changing hud_distributed
710 if (hud_distributed
!=ohud_distributed
)
712 w_ammo
.x
= hud_distributed
? HU_AMMOX_D
: HU_AMMOX
;
713 w_ammo
.y
= hud_distributed
? HU_AMMOY_D
: HU_AMMOY
;
714 w_weapon
.x
= hud_distributed
? HU_WEAPX_D
: HU_WEAPX
;
715 w_weapon
.y
= hud_distributed
? HU_WEAPY_D
: HU_WEAPY
;
716 w_keys
.x
= hud_distributed
? HU_KEYSX_D
: HU_KEYSX
;
717 w_keys
.y
= hud_distributed
? HU_KEYSY_D
: HU_KEYSY
;
718 w_gkeys
.x
= hud_distributed
? HU_KEYSGX_D
: HU_KEYSGX
;
719 w_gkeys
.y
= hud_distributed
? HU_KEYSY_D
: HU_KEYSY
;
720 w_monsec
.x
= hud_distributed
? HU_MONSECX_D
: HU_MONSECX
;
721 w_monsec
.y
= hud_distributed
? HU_MONSECY_D
: HU_MONSECY
;
722 w_health
.x
= hud_distributed
? HU_HEALTHX_D
: HU_HEALTHX
;
723 w_health
.y
= hud_distributed
? HU_HEALTHY_D
: HU_HEALTHY
;
724 w_armor
.x
= hud_distributed
? HU_ARMORX_D
: HU_ARMORX
;
725 w_armor
.y
= hud_distributed
? HU_ARMORY_D
: HU_ARMORY
;
727 ohud_distributed
= hud_distributed
;
733 // Draw all the pieces of the heads-up display
735 // Passed nothing, returns nothing
741 char ammostr
[80]; //jff 3/8/98 allow plenty room for dehacked mods
742 char healthstr
[80];//jff
743 char armorstr
[80]; //jff
746 plr
= &players
[displayplayer
]; // killough 3/7/98
747 // draw the automap widgets if automap is displayed
748 if (automapmode
& am_active
)
751 HUlib_drawTextLine(&w_title
, false);
753 //jff 2/16/98 output new coord display
755 snprintf(hud_coordstrx
,32*sizeof(char),"X: %d", (plr
->mo
->x
)>>FRACBITS
);
756 HUlib_clearTextLine(&w_coordx
);
759 HUlib_addCharToTextLine(&w_coordx
, *(s
++));
760 HUlib_drawTextLine(&w_coordx
, false);
762 //jff 3/3/98 split coord display into x,y,z lines
764 snprintf(hud_coordstry
,32*sizeof(char),"Y: %d", (plr
->mo
->y
)>>FRACBITS
);
765 HUlib_clearTextLine(&w_coordy
);
768 HUlib_addCharToTextLine(&w_coordy
, *(s
++));
769 HUlib_drawTextLine(&w_coordy
, false);
771 //jff 3/3/98 split coord display into x,y,z lines
772 //jff 2/22/98 added z
774 snprintf(hud_coordstrz
,32*sizeof(char),"Z: %d", (plr
->mo
->z
)>>FRACBITS
);
775 HUlib_clearTextLine(&w_coordz
);
778 HUlib_addCharToTextLine(&w_coordz
, *(s
++));
779 HUlib_drawTextLine(&w_coordz
, false);
782 // draw the weapon/health/ammo/armor/kills/keys displays if optioned
783 //jff 2/17/98 allow new hud stuff to be turned off
784 // killough 2/21/98: really allow new hud stuff to be turned off COMPLETELY
787 hud_active
>0 && // hud optioned on
788 hud_displayed
&& // hud on from fullscreen key
789 viewheight
==SCREENHEIGHT
&& // fullscreen mode is active
790 !(automapmode
& am_active
) // automap is not active
793 doit
= !(gametic
&1); //jff 3/4/98 speed update up for slow systems
794 if (doit
) //jff 8/7/98 update every time, avoid lag in update
796 HU_MoveHud(); // insure HUD display coords are correct
798 // do the hud ammo display
799 // clear the widgets internal line
800 HUlib_clearTextLine(&w_ammo
);
801 strcpy(hud_ammostr
,"AMM ");
802 if (weaponinfo
[plr
->readyweapon
].ammo
== am_noammo
)
803 { // special case for weapon with no ammo selected - blank bargraph + N/A
804 strcat(hud_ammostr
,"\x7f\x7f\x7f\x7f\x7f\x7f\x7f N/A");
809 int ammo
= plr
->ammo
[weaponinfo
[plr
->readyweapon
].ammo
];
810 int fullammo
= plr
->maxammo
[weaponinfo
[plr
->readyweapon
].ammo
];
811 int ammopct
= (100*ammo
)/fullammo
;
812 int ammobars
= ammopct
/4;
814 // build the numeric amount init string
815 snprintf(ammostr
,sizeof(ammostr
),"%d/%d",ammo
,fullammo
);
816 // build the bargraph string
817 // full bargraph chars
818 for (i
=4;i
<4+ammobars
/4;)
819 hud_ammostr
[i
++] = 123;
820 // plus one last character with 0,1,2,3 bars
826 hud_ammostr
[i
++] = 126;
829 hud_ammostr
[i
++] = 125;
832 hud_ammostr
[i
++] = 124;
835 // pad string with blank bar characters
837 hud_ammostr
[i
++] = 127;
838 hud_ammostr
[i
] = '\0';
839 strcat(hud_ammostr
,ammostr
);
841 // set the display color from the percentage of total ammo held
842 if (ammopct
<ammo_red
)
844 else if (ammopct
<ammo_yellow
)
847 w_ammo
.cm
= CR_GREEN
;
849 // transfer the init string to the widget
852 HUlib_addCharToTextLine(&w_ammo
, *(s
++));
854 // display the ammo widget every frame
855 HUlib_drawTextLine(&w_ammo
, false);
857 // do the hud health display
860 int health
= plr
->health
;
861 int healthbars
= health
>100? 25 : health
/4;
863 // clear the widgets internal line
864 HUlib_clearTextLine(&w_health
);
866 // build the numeric amount init string
867 snprintf(healthstr
,sizeof(healthstr
),"%3d",health
);
868 // build the bargraph string
869 // full bargraph chars
870 for (i
=4;i
<4+healthbars
/4;)
871 hud_healthstr
[i
++] = 123;
872 // plus one last character with 0,1,2,3 bars
878 hud_healthstr
[i
++] = 126;
881 hud_healthstr
[i
++] = 125;
884 hud_healthstr
[i
++] = 124;
887 // pad string with blank bar characters
889 hud_healthstr
[i
++] = 127;
890 hud_healthstr
[i
] = '\0';
891 strcat(hud_healthstr
,healthstr
);
893 // set the display color from the amount of health posessed
894 if (health
<health_red
)
895 w_health
.cm
= CR_RED
;
896 else if (health
<health_yellow
)
897 w_health
.cm
= CR_GOLD
;
898 else if (health
<=health_green
)
899 w_health
.cm
= CR_GREEN
;
901 w_health
.cm
= CR_BLUE
;
903 // transfer the init string to the widget
906 HUlib_addCharToTextLine(&w_health
, *(s
++));
908 // display the health widget every frame
909 HUlib_drawTextLine(&w_health
, false);
911 // do the hud armor display
914 int armor
= plr
->armorpoints
;
915 int armorbars
= armor
>100? 25 : armor
/4;
917 // clear the widgets internal line
918 HUlib_clearTextLine(&w_armor
);
919 // build the numeric amount init string
920 snprintf(armorstr
,sizeof(armorstr
),"%3d",armor
);
921 // build the bargraph string
922 // full bargraph chars
923 for (i
=4;i
<4+armorbars
/4;)
924 hud_armorstr
[i
++] = 123;
925 // plus one last character with 0,1,2,3 bars
931 hud_armorstr
[i
++] = 126;
934 hud_armorstr
[i
++] = 125;
937 hud_armorstr
[i
++] = 124;
940 // pad string with blank bar characters
942 hud_armorstr
[i
++] = 127;
943 hud_armorstr
[i
] = '\0';
944 strcat(hud_armorstr
,armorstr
);
946 // set the display color from the amount of armor posessed
949 else if (armor
<armor_yellow
)
950 w_armor
.cm
= CR_GOLD
;
951 else if (armor
<=armor_green
)
952 w_armor
.cm
= CR_GREEN
;
954 w_armor
.cm
= CR_BLUE
;
956 // transfer the init string to the widget
959 HUlib_addCharToTextLine(&w_armor
, *(s
++));
961 // display the armor widget every frame
962 HUlib_drawTextLine(&w_armor
, false);
964 // do the hud weapon display
968 int ammo
,fullammo
,ammopct
;
970 // clear the widgets internal line
971 HUlib_clearTextLine(&w_weapon
);
972 i
=4; hud_weapstr
[i
] = '\0'; //jff 3/7/98 make sure ammo goes away
974 // do each weapon that exists in current gamemode
975 for (w
=0;w
<=wp_supershotgun
;w
++) //jff 3/4/98 show fists too, why not?
978 //jff avoid executing for weapons that do not exist
982 if (w
>=wp_plasma
&& w
!=wp_chainsaw
)
987 if (w
>=wp_supershotgun
)
996 ammo
= plr
->ammo
[weaponinfo
[w
].ammo
];
997 fullammo
= plr
->maxammo
[weaponinfo
[w
].ammo
];
1000 // skip weapons not currently posessed
1001 if (!plr
->weaponowned
[w
])
1004 ammopct
= fullammo
? (100*ammo
)/fullammo
: 100;
1006 // display each weapon number in a color related to the ammo for it
1007 hud_weapstr
[i
++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1008 if (weaponinfo
[w
].ammo
==am_noammo
) //jff 3/14/98 show berserk on HUD
1009 hud_weapstr
[i
++] = plr
->powers
[pw_strength
]? '0'+CR_GREEN
: '0'+CR_GRAY
;
1010 else if (ammopct
<ammo_red
)
1011 hud_weapstr
[i
++] = '0'+CR_RED
;
1012 else if (ammopct
<ammo_yellow
)
1013 hud_weapstr
[i
++] = '0'+CR_GOLD
;
1015 hud_weapstr
[i
++] = '0'+CR_GREEN
;
1016 hud_weapstr
[i
++] = '0'+w
+1;
1017 hud_weapstr
[i
++] = ' ';
1018 hud_weapstr
[i
] = '\0';
1021 // transfer the init string to the widget
1024 HUlib_addCharToTextLine(&w_weapon
, *(s
++));
1026 // display the weapon widget every frame
1027 HUlib_drawTextLine(&w_weapon
, false);
1029 if (doit
&& hud_active
>1)
1033 hud_keysstr
[4] = '\0'; //jff 3/7/98 make sure deleted keys go away
1034 //jff add case for graphic key display
1035 if (!deathmatch
&& hud_graph_keys
)
1038 hud_gkeysstr
[i
] = '\0'; //jff 3/7/98 init graphic keys widget string
1039 // build text string whose characters call out graphic keys from fontk
1042 // skip keys not possessed
1046 hud_gkeysstr
[i
++] = '!'+k
; // key number plus '!' is char for key
1047 hud_gkeysstr
[i
++] = ' '; // spacing
1048 hud_gkeysstr
[i
++] = ' ';
1050 hud_gkeysstr
[i
]='\0';
1052 else // not possible in current code, unless deathmatching,
1055 hud_keysstr
[i
] = '\0'; //jff 3/7/98 make sure deleted keys go away
1057 // if deathmatch, build string showing top four frag counts
1058 if (deathmatch
) //jff 3/17/98 show frags, not keys, in deathmatch
1060 int top1
=-999,top2
=-999,top3
=-999,top4
=-999;
1061 int idx1
=-1,idx2
=-1,idx3
=-1,idx4
=-1;
1065 // scan thru players
1066 for (k
=0;k
<MAXPLAYERS
;k
++)
1068 // skip players not in game
1069 if (!playeringame
[k
])
1073 // compute number of times they've fragged each player
1074 // minus number of times they've been fragged by them
1075 for (m
=0;m
<MAXPLAYERS
;m
++)
1077 if (!playeringame
[m
]) continue;
1078 fragcount
+= (m
!=k
)? players
[k
].frags
[m
] : -players
[k
].frags
[m
];
1081 // very primitive sort of frags to find top four
1084 top4
=top3
; top3
=top2
; top2
= top1
; top1
=fragcount
;
1085 idx4
=idx3
; idx3
=idx2
; idx2
= idx1
; idx1
=k
;
1087 else if (fragcount
>top2
)
1089 top4
=top3
; top3
=top2
; top2
=fragcount
;
1090 idx4
=idx3
; idx3
=idx2
; idx2
=k
;
1092 else if (fragcount
>top3
)
1094 top4
=top3
; top3
=fragcount
;
1097 else if (fragcount
>top4
)
1103 // if the biggest number exists, put it in the init string
1106 snprintf(numbuf
,sizeof(numbuf
),"%5d",top1
);
1107 // make frag count in player's color via escape code
1108 hud_keysstr
[i
++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1109 hud_keysstr
[i
++] = '0'+plyrcoltran
[idx1
&3];
1112 hud_keysstr
[i
++] = *(s
++);
1114 // if the second biggest number exists, put it in the init string
1117 snprintf(numbuf
,sizeof(numbuf
),"%5d",top2
);
1118 // make frag count in player's color via escape code
1119 hud_keysstr
[i
++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1120 hud_keysstr
[i
++] = '0'+plyrcoltran
[idx2
&3];
1123 hud_keysstr
[i
++] = *(s
++);
1125 // if the third biggest number exists, put it in the init string
1128 snprintf(numbuf
,sizeof(numbuf
),"%5d",top3
);
1129 // make frag count in player's color via escape code
1130 hud_keysstr
[i
++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1131 hud_keysstr
[i
++] = '0'+plyrcoltran
[idx3
&3];
1134 hud_keysstr
[i
++] = *(s
++);
1136 // if the fourth biggest number exists, put it in the init string
1139 snprintf(numbuf
,sizeof(numbuf
),"%5d",top4
);
1140 // make frag count in player's color via escape code
1141 hud_keysstr
[i
++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1142 hud_keysstr
[i
++] = '0'+plyrcoltran
[idx4
&3];
1145 hud_keysstr
[i
++] = *(s
++);
1147 hud_keysstr
[i
] = '\0';
1148 } //jff 3/17/98 end of deathmatch clause
1149 else // build alphabetical key display (not used currently)
1154 // skip any not possessed by the displayed player's stats
1158 // use color escapes to make text in key's color
1159 hud_keysstr
[i
++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1163 hud_keysstr
[i
++] = '0'+CR_BLUE
;
1164 hud_keysstr
[i
++] = 'B';
1165 hud_keysstr
[i
++] = 'C';
1166 hud_keysstr
[i
++] = ' ';
1169 hud_keysstr
[i
++] = '0'+CR_GOLD
;
1170 hud_keysstr
[i
++] = 'Y';
1171 hud_keysstr
[i
++] = 'C';
1172 hud_keysstr
[i
++] = ' ';
1175 hud_keysstr
[i
++] = '0'+CR_RED
;
1176 hud_keysstr
[i
++] = 'R';
1177 hud_keysstr
[i
++] = 'C';
1178 hud_keysstr
[i
++] = ' ';
1181 hud_keysstr
[i
++] = '0'+CR_BLUE
;
1182 hud_keysstr
[i
++] = 'B';
1183 hud_keysstr
[i
++] = 'S';
1184 hud_keysstr
[i
++] = ' ';
1187 hud_keysstr
[i
++] = '0'+CR_GOLD
;
1188 hud_keysstr
[i
++] = 'Y';
1189 hud_keysstr
[i
++] = 'S';
1190 hud_keysstr
[i
++] = ' ';
1193 hud_keysstr
[i
++] = '0'+CR_RED
;
1194 hud_keysstr
[i
++] = 'R';
1195 hud_keysstr
[i
++] = 'S';
1196 hud_keysstr
[i
++] = ' ';
1199 hud_keysstr
[i
]='\0';
1204 // display the keys/frags line each frame
1207 HUlib_clearTextLine(&w_keys
); // clear the widget strings
1208 HUlib_clearTextLine(&w_gkeys
);
1210 // transfer the built string (frags or key title) to the widget
1211 s
= hud_keysstr
; //jff 3/7/98 display key titles/key text or frags
1213 HUlib_addCharToTextLine(&w_keys
, *(s
++));
1214 HUlib_drawTextLine(&w_keys
, false);
1216 //jff 3/17/98 show graphic keys in non-DM only
1217 if (!deathmatch
) //jff 3/7/98 display graphic keys
1219 // transfer the graphic key text to the widget
1222 HUlib_addCharToTextLine(&w_gkeys
, *(s
++));
1223 // display the widget
1224 HUlib_drawTextLine(&w_gkeys
, false);
1228 // display the hud kills/items/secret display if optioned
1231 if (hud_active
>1 && doit
)
1233 // clear the internal widget text buffer
1234 HUlib_clearTextLine(&w_monsec
);
1235 //jff 3/26/98 use ESC not '\' for paths
1236 // build the init string with fixed colors
1239 hud_monsecstr
,80*sizeof(char),
1240 "STS \x1b\x36K \x1b\x33%d \x1b\x36M \x1b\x33%d \x1b\x37I \x1b\x33%d/%d \x1b\x35S \x1b\x33%d/%d",
1241 plr
->killcount
,totallive
,
1242 plr
->itemcount
,totalitems
,
1243 plr
->secretcount
,totalsecret
1245 // transfer the init string to the widget
1248 HUlib_addCharToTextLine(&w_monsec
, *(s
++));
1250 // display the kills/items/secrets each frame, if optioned
1252 HUlib_drawTextLine(&w_monsec
, false);
1256 //jff 3/4/98 display last to give priority
1257 HU_Erase(); // jff 4/24/98 Erase current lines before drawing current
1258 // needed when screen not fullsize
1260 //jff 4/21/98 if setup has disabled message list while active, turn it off
1261 if (hud_msg_lines
<=1)
1262 message_list
= false;
1264 // if the message review not enabled, show the standard message widget
1266 HUlib_drawSText(&w_message
);
1268 // if the message review is enabled show the scrolling message review
1269 if (hud_msg_lines
>1 && message_list
)
1270 HUlib_drawMText(&w_rtext
);
1272 // display the interactive buffer for chat entry
1273 HUlib_drawIText(&w_chat
);
1279 // Erase hud display lines that can be trashed by small screen display
1281 // Passed nothing, returns nothing
1285 // erase the message display or the message review display
1287 HUlib_eraseSText(&w_message
);
1289 HUlib_eraseMText(&w_rtext
);
1291 // erase the interactive text buffer for chat entry
1292 HUlib_eraseIText(&w_chat
);
1294 // erase the automap title
1295 HUlib_eraseTextLine(&w_title
);
1301 // Update the hud displays once per frame
1303 // Passed nothing, returns nothing
1305 static boolean bsdown
; // Is backspace down?
1306 static int bscounter
;
1308 void HU_Ticker(void)
1313 // tick down message counter if message is up
1314 if (message_counter
&& !--message_counter
)
1317 message_nottobefuckedwith
= false;
1319 if (bsdown
&& bscounter
++ > 9) {
1320 HUlib_keyInIText(&w_chat
, (unsigned char)key_backspace
);
1324 // if messages on, or "Messages Off" is being displayed
1325 // this allows the notification of turning messages off to be seen
1326 if (showMessages
|| message_dontfuckwithme
)
1328 // display message if necessary
1329 if ((plr
->message
&& !message_nottobefuckedwith
)
1330 || (plr
->message
&& message_dontfuckwithme
))
1332 //post the message to the message widget
1333 HUlib_addMessageToSText(&w_message
, 0, plr
->message
);
1334 //jff 2/26/98 add message to refresh text widget too
1335 HUlib_addMessageToMText(&w_rtext
, 0, plr
->message
);
1337 // clear the message to avoid posting multiple times
1339 // note a message is displayed
1341 // start the message persistence counter
1342 message_counter
= HU_MSGTIMEOUT
;
1343 // transfer "Messages Off" exception to the "being displayed" variable
1344 message_nottobefuckedwith
= message_dontfuckwithme
;
1345 // clear the flag that "Messages Off" is being posted
1346 message_dontfuckwithme
= 0;
1350 // check for incoming chat characters
1353 for (i
=0; i
<MAXPLAYERS
; i
++)
1355 if (!playeringame
[i
])
1357 if (i
!= consoleplayer
1358 && (c
= players
[i
].cmd
.chatchar
))
1360 if (c
<= HU_BROADCAST
)
1364 if (c
>= 'a' && c
<= 'z')
1365 c
= (char) shiftxform
[(unsigned char) c
];
1366 rc
= HUlib_keyInIText(&w_inputbuffer
[i
], c
);
1367 if (rc
&& c
== KEY_ENTER
)
1369 if (w_inputbuffer
[i
].l
.len
1370 && (chat_dest
[i
] == consoleplayer
+1
1371 || chat_dest
[i
] == HU_BROADCAST
))
1373 HUlib_addMessageToSText(&w_message
,
1375 w_inputbuffer
[i
].l
.l
);
1377 message_nottobefuckedwith
= true;
1379 message_counter
= HU_MSGTIMEOUT
;
1380 if ( gamemode
== commercial
)
1381 S_StartSound(0, sfx_radio
);
1383 S_StartSound(0, sfx_tink
);
1385 HUlib_resetIText(&w_inputbuffer
[i
]);
1388 players
[i
].cmd
.chatchar
= 0;
1394 #define QUEUESIZE 128
1396 static char chatchars
[QUEUESIZE
];
1397 static int head
= 0;
1398 static int tail
= 0;
1401 // HU_queueChatChar()
1403 // Add an incoming character to the circular chat queue
1405 // Passed the character to queue, returns nothing
1407 void HU_queueChatChar(char c
)
1409 if (((head
+ 1) & (QUEUESIZE
-1)) == tail
)
1411 plr
->message
= HUSTR_MSGU
;
1415 chatchars
[head
] = c
;
1416 head
= (head
+ 1) & (QUEUESIZE
-1);
1421 // HU_dequeueChatChar()
1423 // Remove the earliest added character from the circular chat queue
1425 // Passed nothing, returns the character dequeued
1427 char HU_dequeueChatChar(void)
1433 c
= chatchars
[tail
];
1434 tail
= (tail
+ 1) & (QUEUESIZE
-1);
1446 // Responds to input events that affect the heads up displays
1448 // Passed the event to respond to, returns true if the event was handled
1450 boolean
HU_Responder(event_t
*ev
)
1453 static char lastmessage
[HU_MAXLINELENGTH
+1];
1454 const char* macromessage
; // CPhipps - const char*
1455 boolean eatkey
= false;
1456 static boolean shiftdown
= false;
1457 static boolean altdown
= false;
1462 static int num_nobrainers
= 0;
1465 for (i
=0 ; i
<MAXPLAYERS
; i
++)
1466 numplayers
+= playeringame
[i
];
1468 if (ev
->data1
== key_shift
)
1470 shiftdown
= ev
->type
== ev_keydown
;
1473 else if (ev
->data1
== key_alt
)
1475 altdown
= ev
->type
== ev_keydown
;
1478 else if (ev
->data1
== key_backspace
)
1480 bsdown
= ev
->type
== ev_keydown
;
1484 if (ev
->type
!= ev_keydown
)
1489 if (ev
->data1
== key_enter
) // phares
1491 #ifndef INSTRUMENTED // never turn on message review if INSTRUMENTED defined
1492 if (hud_msg_lines
>1) // it posts multi-line messages that will trash
1494 if (message_list
) HU_Erase(); //jff 4/28/98 erase behind messages
1495 message_list
= !message_list
; //jff 2/26/98 toggle list of messages
1498 if (!message_list
) // if not message list, refresh message
1501 message_counter
= HU_MSGTIMEOUT
;
1504 }//jff 2/26/98 no chat if message review is displayed
1505 else if (!message_list
&& netgame
&& ev
->data1
== key_chat
)
1507 eatkey
= chat_on
= true;
1508 HUlib_resetIText(&w_chat
);
1509 HU_queueChatChar(HU_BROADCAST
);
1510 }//jff 2/26/98 no chat if message review is displayed
1511 // killough 10/02/98: no chat if demo playback
1512 else if (!demoplayback
&& !message_list
&& netgame
&& numplayers
> 2)
1514 for (i
=0; i
<MAXPLAYERS
; i
++)
1516 if (ev
->data1
== destination_keys
[i
])
1518 if (playeringame
[i
] && i
!=consoleplayer
)
1520 eatkey
= chat_on
= true;
1521 HUlib_resetIText(&w_chat
);
1522 HU_queueChatChar((char)(i
+1));
1525 else if (i
== consoleplayer
)
1528 if (num_nobrainers
< 3)
1529 plr
->message
= HUSTR_TALKTOSELF1
;
1530 else if (num_nobrainers
< 6)
1531 plr
->message
= HUSTR_TALKTOSELF2
;
1532 else if (num_nobrainers
< 9)
1533 plr
->message
= HUSTR_TALKTOSELF3
;
1534 else if (num_nobrainers
< 32)
1535 plr
->message
= HUSTR_TALKTOSELF4
;
1537 plr
->message
= HUSTR_TALKTOSELF5
;
1542 }//jff 2/26/98 no chat functions if message review is displayed
1543 else if (!message_list
)
1552 macromessage
= chat_macros
[c
];
1554 // kill last message with a '\n'
1555 HU_queueChatChar((char)key_enter
); // DEBUG!!! // phares
1557 // send the macro message
1558 while (*macromessage
)
1559 HU_queueChatChar(*macromessage
++);
1560 HU_queueChatChar((char)key_enter
); // phares
1562 // leave chat mode and notify that it was sent
1564 strcpy(lastmessage
, chat_macros
[c
]);
1565 plr
->message
= lastmessage
;
1570 if (shiftdown
|| (c
>= 'a' && c
<= 'z'))
1572 eatkey
= HUlib_keyInIText(&w_chat
, c
);
1574 HU_queueChatChar(c
);
1576 if (c
== key_enter
) // phares
1581 strcpy(lastmessage
, w_chat
.l
.l
);
1582 plr
->message
= lastmessage
;
1585 else if (c
== key_escape
) // phares