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 // Builtin map names.
232 // The actual names can be found in DStrings.h.
234 // Ty 03/27/98 - externalized map name arrays - now in d_deh.c
235 // and converted to arrays of pointers to char *
236 // See modified HUTITLEx macros
237 extern char **mapnames
[];
238 extern char **mapnames2
[];
239 extern char **mapnamesp
[];
240 extern char **mapnamest
[];
243 // jff 5/10/98 french support removed,
244 // as it was not being used and couldn't be easily tested
246 const char* shiftxform
;
248 const char english_shiftxform
[] =
251 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
252 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
253 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
255 ' ', '!', '"', '#', '$', '%', '&',
277 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
278 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
280 '!', // shift-backslash - OH MY GOD DOES WATCOM SUCK
284 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
285 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
286 '{', '|', '}', '~', 127
292 // Initialize the heads-up display, text that overwrites the primary display
294 // Passed nothing, returns nothing
302 shiftxform
= english_shiftxform
;
304 // malloc all the strings, trying to get size down
305 hud_ammostr
=malloc(80*sizeof(char));
306 hud_healthstr
=malloc(80*sizeof(char));
307 hud_armorstr
=malloc(80*sizeof(char));
308 hud_weapstr
=malloc(80*sizeof(char));
309 hud_keysstr
=malloc(80*sizeof(char));
310 hud_gkeysstr
=malloc(80*sizeof(char));
311 hud_monsecstr
=malloc(80*sizeof(char));
312 hud_coordstrx
=malloc(32*sizeof(char));
313 hud_coordstry
=malloc(32*sizeof(char));
314 hud_coordstrz
=malloc(32*sizeof(char));
315 hu_fontk
=malloc(HU_FONTSIZE
*sizeof(patchnum_t
));
316 hu_font2
=malloc(HU_FONTSIZE
*sizeof(patchnum_t
));
318 // load the heads-up font
320 for (i
=0;i
<HU_FONTSIZE
;i
++,j
++)
322 if ('0'<=j
&& j
<='9')
324 snprintf(buffer
, sizeof(buffer
), "DIG%d",j
-48);
325 R_SetPatchNum(hu_font2
+i
, buffer
);
326 snprintf(buffer
, sizeof(buffer
), "STCFN%s%d", (j
/10>0?"0":"00"), j
); //NOTE ROCKHACK: "STCFN%.3d"
327 R_SetPatchNum(&hu_font
[i
], buffer
);
329 else if ('A'<=j
&& j
<='Z')
331 snprintf(buffer
, sizeof(buffer
), "DIG%c",j
);
332 R_SetPatchNum(hu_font2
+i
, buffer
);
333 snprintf(buffer
, sizeof(buffer
), "STCFN%s%d", (j
/10>0?"0":"00"), j
); //NOTE ROCKHACK: "STCFN%.3d"
334 R_SetPatchNum(&hu_font
[i
], buffer
);
338 R_SetPatchNum(hu_font2
+i
, "DIG45");
339 R_SetPatchNum(&hu_font
[i
], "STCFN045");
343 R_SetPatchNum(hu_font2
+i
, "DIG47");
344 R_SetPatchNum(&hu_font
[i
], "STCFN047");
348 R_SetPatchNum(hu_font2
+i
, "DIG58");
349 R_SetPatchNum(&hu_font
[i
], "STCFN058");
353 R_SetPatchNum(hu_font2
+i
, "DIG91");
354 R_SetPatchNum(&hu_font
[i
], "STCFN091");
358 R_SetPatchNum(hu_font2
+i
, "DIG93");
359 R_SetPatchNum(&hu_font
[i
], "STCFN093");
363 snprintf(buffer
, sizeof(buffer
), "STCFN%s%d", (j
/10>0?"0":"00"), j
); //NOTE ROCKHACK: "STCFN%.3d"
364 R_SetPatchNum(hu_font2
+i
, buffer
);
365 R_SetPatchNum(&hu_font
[i
], buffer
);
366 //jff 2/23/98 make all font chars defined, useful or not
370 snprintf(buffer
, sizeof(buffer
), "STBR%d", j
); //NOTE: "STBR%.3d"
371 R_SetPatchNum(hu_font2
+i
, buffer
);
372 R_SetPatchNum(&hu_font
[i
], buffer
);
375 hu_font
[i
] = hu_font
[0]; //jff 2/16/98 account for gap
378 // CPhipps - load patches for message background
379 for (i
=0; i
<9; i
++) {
380 snprintf(buffer
, sizeof(buffer
), "BOX%c%c", "UCL"[i
/3], "LCR"[i
%3]);
381 R_SetPatchNum(&hu_msgbg
[i
], buffer
);
384 // CPhipps - load patches for keys and double keys
385 for (i
=0; i
<6; i
++) {
386 snprintf(buffer
, sizeof(buffer
), "STKEYS%d", i
);
387 R_SetPatchNum(hu_fontk
+i
, buffer
);
394 // Make the heads-up displays inactive
396 // Passed nothing, returns nothing
400 headsupactive
= false;
406 // Create and initialize the heads-up widgets, software machines to
407 // maintain, update, and display information over the primary display
409 // This routine must be called after any change to the heads up configuration
410 // in order for the changes to take effect in the actual displays
412 // Passed nothing, returns nothing
418 const char* s
; /* cph - const */
420 if (headsupactive
) // stop before starting
423 plr
= &players
[displayplayer
]; // killough 3/7/98
425 message_dontfuckwithme
= false;
426 message_nottobefuckedwith
= false;
429 // create the message widget
430 // messages to player in upper-left of screen
443 //jff 2/16/98 added some HUD widgets
444 // create the map title widget - map title display in lower left of automap
455 // create the hud health widget
456 // bargraph and number for amount of health,
457 // lower left or upper right of screen
461 hud_distributed
? HU_HEALTHX_D
: HU_HEALTHX
, //3/4/98 distribute
462 hud_distributed
? HU_HEALTHY_D
: HU_HEALTHY
,
468 // create the hud armor widget
469 // bargraph and number for amount of armor,
470 // lower left or upper right of screen
474 hud_distributed
? HU_ARMORX_D
: HU_ARMORX
, //3/4/98 distribute
475 hud_distributed
? HU_ARMORY_D
: HU_ARMORY
,
481 // create the hud ammo widget
482 // bargraph and number for amount of ammo for current weapon,
483 // lower left or lower right of screen
487 hud_distributed
? HU_AMMOX_D
: HU_AMMOX
, //3/4/98 distribute
488 hud_distributed
? HU_AMMOY_D
: HU_AMMOY
,
494 // create the hud weapons widget
495 // list of numbers of weapons possessed
496 // lower left or lower right of screen
500 hud_distributed
? HU_WEAPX_D
: HU_WEAPX
, //3/4/98 distribute
501 hud_distributed
? HU_WEAPY_D
: HU_WEAPY
,
507 // create the hud keys widget
508 // display of key letters possessed
509 // lower left of screen
513 hud_distributed
? HU_KEYSX_D
: HU_KEYSX
, //3/4/98 distribute
514 hud_distributed
? HU_KEYSY_D
: HU_KEYSY
,
520 // create the hud graphic keys widget
521 // display of key graphics possessed
522 // lower left of screen
526 hud_distributed
? HU_KEYSGX_D
: HU_KEYSGX
, //3/4/98 distribute
527 hud_distributed
? HU_KEYSY_D
: HU_KEYSY
,
533 // create the hud monster/secret widget
534 // totals and current values for kills, items, secrets
535 // lower left of screen
539 hud_distributed
? HU_MONSECX_D
: HU_MONSECX
, //3/4/98 distribute
540 hud_distributed
? HU_MONSECY_D
: HU_MONSECY
,
546 // create the hud text refresh widget
547 // scrolling display of last hud_msg_lines messages received
548 if (hud_msg_lines
>HU_MAXMESSAGES
)
549 hud_msg_lines
=HU_MAXMESSAGES
;
550 //jff 4/21/98 if setup has disabled message list while active, turn it off
551 message_list
= hud_msg_lines
> 1; //jff 8/8/98 initialize both ways
552 //jff 2/26/98 add the text refresh widget initialization
560 (hud_msg_lines
+2)*HU_REFRESHSPACING
,
568 // initialize the automap's level title widget
569 if (gamestate
== GS_LEVEL
) /* cph - stop SEGV here when not in level */
579 default: // Ty 08/27/98 - modified to check mission for TNT/Plutonia
580 s
= (gamemission
==pack_tnt
) ? HU_TITLET
:
581 (gamemission
==pack_plut
) ? HU_TITLEP
: HU_TITLE2
;
585 HUlib_addCharToTextLine(&w_title
, *(s
++));
587 // create the automaps coordinate widget
588 // jff 3/3/98 split coord widget into three lines: x,y,z
618 // initialize the automaps coordinate widget
619 //jff 3/3/98 split coordstr widget into 3 parts
620 snprintf(hud_coordstrx
,32*sizeof(char),"X: %d",0); //jff 2/22/98 added z
623 HUlib_addCharToTextLine(&w_coordx
, *(s
++));
624 snprintf(hud_coordstry
,32*sizeof(char),"Y: %d",0); //jff 3/3/98 split x,y,z
627 HUlib_addCharToTextLine(&w_coordy
, *(s
++));
628 snprintf(hud_coordstrz
,32*sizeof(char),"Z: %d",0); //jff 3/3/98 split x,y,z
631 HUlib_addCharToTextLine(&w_coordz
, *(s
++));
633 //jff 2/16/98 initialize ammo widget
634 strcpy(hud_ammostr
,"AMM ");
637 HUlib_addCharToTextLine(&w_ammo
, *(s
++));
639 //jff 2/16/98 initialize health widget
640 strcpy(hud_healthstr
,"HEL ");
643 HUlib_addCharToTextLine(&w_health
, *(s
++));
645 //jff 2/16/98 initialize armor widget
646 strcpy(hud_armorstr
,"ARM ");
649 HUlib_addCharToTextLine(&w_armor
, *(s
++));
651 //jff 2/17/98 initialize weapons widget
652 strcpy(hud_weapstr
,"WEA ");
655 HUlib_addCharToTextLine(&w_weapon
, *(s
++));
657 //jff 2/17/98 initialize keys widget
658 if (!deathmatch
) //jff 3/17/98 show frags in deathmatch mode
659 strcpy(hud_keysstr
,"KEY ");
661 strcpy(hud_keysstr
,"FRG ");
664 HUlib_addCharToTextLine(&w_keys
, *(s
++));
666 //jff 2/17/98 initialize graphic keys widget
667 strcpy(hud_gkeysstr
," ");
670 HUlib_addCharToTextLine(&w_gkeys
, *(s
++));
672 //jff 2/17/98 initialize kills/items/secret widget
673 strcpy(hud_monsecstr
,"STS ");
676 HUlib_addCharToTextLine(&w_monsec
, *(s
++));
678 // create the chat widget
690 // create the inputbuffer widgets, one per player
691 for (i
=0 ; i
<MAXPLAYERS
; i
++)
703 // now allow the heads-up display to run
704 headsupactive
= true;
710 // Move the HUD display from distributed to compact mode or vice-versa
712 // Passed nothing, returns nothing
714 //jff 3/9/98 create this externally callable to avoid glitch
715 // when menu scatter's HUD due to delay in change of position
717 void HU_MoveHud(void)
719 static int ohud_distributed
=-1;
721 //jff 3/4/98 move displays around on F5 changing hud_distributed
722 if (hud_distributed
!=ohud_distributed
)
724 w_ammo
.x
= hud_distributed
? HU_AMMOX_D
: HU_AMMOX
;
725 w_ammo
.y
= hud_distributed
? HU_AMMOY_D
: HU_AMMOY
;
726 w_weapon
.x
= hud_distributed
? HU_WEAPX_D
: HU_WEAPX
;
727 w_weapon
.y
= hud_distributed
? HU_WEAPY_D
: HU_WEAPY
;
728 w_keys
.x
= hud_distributed
? HU_KEYSX_D
: HU_KEYSX
;
729 w_keys
.y
= hud_distributed
? HU_KEYSY_D
: HU_KEYSY
;
730 w_gkeys
.x
= hud_distributed
? HU_KEYSGX_D
: HU_KEYSGX
;
731 w_gkeys
.y
= hud_distributed
? HU_KEYSY_D
: HU_KEYSY
;
732 w_monsec
.x
= hud_distributed
? HU_MONSECX_D
: HU_MONSECX
;
733 w_monsec
.y
= hud_distributed
? HU_MONSECY_D
: HU_MONSECY
;
734 w_health
.x
= hud_distributed
? HU_HEALTHX_D
: HU_HEALTHX
;
735 w_health
.y
= hud_distributed
? HU_HEALTHY_D
: HU_HEALTHY
;
736 w_armor
.x
= hud_distributed
? HU_ARMORX_D
: HU_ARMORX
;
737 w_armor
.y
= hud_distributed
? HU_ARMORY_D
: HU_ARMORY
;
739 ohud_distributed
= hud_distributed
;
745 // Draw all the pieces of the heads-up display
747 // Passed nothing, returns nothing
753 char ammostr
[80]; //jff 3/8/98 allow plenty room for dehacked mods
754 char healthstr
[80];//jff
755 char armorstr
[80]; //jff
758 plr
= &players
[displayplayer
]; // killough 3/7/98
759 // draw the automap widgets if automap is displayed
760 if (automapmode
& am_active
)
763 HUlib_drawTextLine(&w_title
, false);
765 //jff 2/16/98 output new coord display
767 snprintf(hud_coordstrx
,32*sizeof(char),"X: %d", (plr
->mo
->x
)>>FRACBITS
);
768 HUlib_clearTextLine(&w_coordx
);
771 HUlib_addCharToTextLine(&w_coordx
, *(s
++));
772 HUlib_drawTextLine(&w_coordx
, false);
774 //jff 3/3/98 split coord display into x,y,z lines
776 snprintf(hud_coordstry
,32*sizeof(char),"Y: %d", (plr
->mo
->y
)>>FRACBITS
);
777 HUlib_clearTextLine(&w_coordy
);
780 HUlib_addCharToTextLine(&w_coordy
, *(s
++));
781 HUlib_drawTextLine(&w_coordy
, false);
783 //jff 3/3/98 split coord display into x,y,z lines
784 //jff 2/22/98 added z
786 snprintf(hud_coordstrz
,32*sizeof(char),"Z: %d", (plr
->mo
->z
)>>FRACBITS
);
787 HUlib_clearTextLine(&w_coordz
);
790 HUlib_addCharToTextLine(&w_coordz
, *(s
++));
791 HUlib_drawTextLine(&w_coordz
, false);
794 // draw the weapon/health/ammo/armor/kills/keys displays if optioned
795 //jff 2/17/98 allow new hud stuff to be turned off
796 // killough 2/21/98: really allow new hud stuff to be turned off COMPLETELY
799 hud_active
>0 && // hud optioned on
800 hud_displayed
&& // hud on from fullscreen key
801 viewheight
==SCREENHEIGHT
&& // fullscreen mode is active
802 !(automapmode
& am_active
) // automap is not active
805 doit
= !(gametic
&1); //jff 3/4/98 speed update up for slow systems
806 if (doit
) //jff 8/7/98 update every time, avoid lag in update
808 HU_MoveHud(); // insure HUD display coords are correct
810 // do the hud ammo display
811 // clear the widgets internal line
812 HUlib_clearTextLine(&w_ammo
);
813 strcpy(hud_ammostr
,"AMM ");
814 if (weaponinfo
[plr
->readyweapon
].ammo
== am_noammo
)
815 { // special case for weapon with no ammo selected - blank bargraph + N/A
816 strcat(hud_ammostr
,"\x7f\x7f\x7f\x7f\x7f\x7f\x7f N/A");
821 int ammo
= plr
->ammo
[weaponinfo
[plr
->readyweapon
].ammo
];
822 int fullammo
= plr
->maxammo
[weaponinfo
[plr
->readyweapon
].ammo
];
823 int ammopct
= (100*ammo
)/fullammo
;
824 int ammobars
= ammopct
/4;
826 // build the numeric amount init string
827 snprintf(ammostr
,sizeof(ammostr
),"%d/%d",ammo
,fullammo
);
828 // build the bargraph string
829 // full bargraph chars
830 for (i
=4;i
<4+ammobars
/4;)
831 hud_ammostr
[i
++] = 123;
832 // plus one last character with 0,1,2,3 bars
838 hud_ammostr
[i
++] = 126;
841 hud_ammostr
[i
++] = 125;
844 hud_ammostr
[i
++] = 124;
847 // pad string with blank bar characters
849 hud_ammostr
[i
++] = 127;
850 hud_ammostr
[i
] = '\0';
851 strcat(hud_ammostr
,ammostr
);
853 // set the display color from the percentage of total ammo held
854 if (ammopct
<ammo_red
)
856 else if (ammopct
<ammo_yellow
)
859 w_ammo
.cm
= CR_GREEN
;
861 // transfer the init string to the widget
864 HUlib_addCharToTextLine(&w_ammo
, *(s
++));
866 // display the ammo widget every frame
867 HUlib_drawTextLine(&w_ammo
, false);
869 // do the hud health display
872 int health
= plr
->health
;
873 int healthbars
= health
>100? 25 : health
/4;
875 // clear the widgets internal line
876 HUlib_clearTextLine(&w_health
);
878 // build the numeric amount init string
879 snprintf(healthstr
,sizeof(healthstr
),"%3d",health
);
880 // build the bargraph string
881 // full bargraph chars
882 for (i
=4;i
<4+healthbars
/4;)
883 hud_healthstr
[i
++] = 123;
884 // plus one last character with 0,1,2,3 bars
890 hud_healthstr
[i
++] = 126;
893 hud_healthstr
[i
++] = 125;
896 hud_healthstr
[i
++] = 124;
899 // pad string with blank bar characters
901 hud_healthstr
[i
++] = 127;
902 hud_healthstr
[i
] = '\0';
903 strcat(hud_healthstr
,healthstr
);
905 // set the display color from the amount of health posessed
906 if (health
<health_red
)
907 w_health
.cm
= CR_RED
;
908 else if (health
<health_yellow
)
909 w_health
.cm
= CR_GOLD
;
910 else if (health
<=health_green
)
911 w_health
.cm
= CR_GREEN
;
913 w_health
.cm
= CR_BLUE
;
915 // transfer the init string to the widget
918 HUlib_addCharToTextLine(&w_health
, *(s
++));
920 // display the health widget every frame
921 HUlib_drawTextLine(&w_health
, false);
923 // do the hud armor display
926 int armor
= plr
->armorpoints
;
927 int armorbars
= armor
>100? 25 : armor
/4;
929 // clear the widgets internal line
930 HUlib_clearTextLine(&w_armor
);
931 // build the numeric amount init string
932 snprintf(armorstr
,sizeof(armorstr
),"%3d",armor
);
933 // build the bargraph string
934 // full bargraph chars
935 for (i
=4;i
<4+armorbars
/4;)
936 hud_armorstr
[i
++] = 123;
937 // plus one last character with 0,1,2,3 bars
943 hud_armorstr
[i
++] = 126;
946 hud_armorstr
[i
++] = 125;
949 hud_armorstr
[i
++] = 124;
952 // pad string with blank bar characters
954 hud_armorstr
[i
++] = 127;
955 hud_armorstr
[i
] = '\0';
956 strcat(hud_armorstr
,armorstr
);
958 // set the display color from the amount of armor posessed
961 else if (armor
<armor_yellow
)
962 w_armor
.cm
= CR_GOLD
;
963 else if (armor
<=armor_green
)
964 w_armor
.cm
= CR_GREEN
;
966 w_armor
.cm
= CR_BLUE
;
968 // transfer the init string to the widget
971 HUlib_addCharToTextLine(&w_armor
, *(s
++));
973 // display the armor widget every frame
974 HUlib_drawTextLine(&w_armor
, false);
976 // do the hud weapon display
980 int ammo
,fullammo
,ammopct
;
982 // clear the widgets internal line
983 HUlib_clearTextLine(&w_weapon
);
984 i
=4; hud_weapstr
[i
] = '\0'; //jff 3/7/98 make sure ammo goes away
986 // do each weapon that exists in current gamemode
987 for (w
=0;w
<=wp_supershotgun
;w
++) //jff 3/4/98 show fists too, why not?
990 //jff avoid executing for weapons that do not exist
994 if (w
>=wp_plasma
&& w
!=wp_chainsaw
)
999 if (w
>=wp_supershotgun
)
1008 ammo
= plr
->ammo
[weaponinfo
[w
].ammo
];
1009 fullammo
= plr
->maxammo
[weaponinfo
[w
].ammo
];
1012 // skip weapons not currently posessed
1013 if (!plr
->weaponowned
[w
])
1016 ammopct
= fullammo
? (100*ammo
)/fullammo
: 100;
1018 // display each weapon number in a color related to the ammo for it
1019 hud_weapstr
[i
++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1020 if (weaponinfo
[w
].ammo
==am_noammo
) //jff 3/14/98 show berserk on HUD
1021 hud_weapstr
[i
++] = plr
->powers
[pw_strength
]? '0'+CR_GREEN
: '0'+CR_GRAY
;
1022 else if (ammopct
<ammo_red
)
1023 hud_weapstr
[i
++] = '0'+CR_RED
;
1024 else if (ammopct
<ammo_yellow
)
1025 hud_weapstr
[i
++] = '0'+CR_GOLD
;
1027 hud_weapstr
[i
++] = '0'+CR_GREEN
;
1028 hud_weapstr
[i
++] = '0'+w
+1;
1029 hud_weapstr
[i
++] = ' ';
1030 hud_weapstr
[i
] = '\0';
1033 // transfer the init string to the widget
1036 HUlib_addCharToTextLine(&w_weapon
, *(s
++));
1038 // display the weapon widget every frame
1039 HUlib_drawTextLine(&w_weapon
, false);
1041 if (doit
&& hud_active
>1)
1045 hud_keysstr
[4] = '\0'; //jff 3/7/98 make sure deleted keys go away
1046 //jff add case for graphic key display
1047 if (!deathmatch
&& hud_graph_keys
)
1050 hud_gkeysstr
[i
] = '\0'; //jff 3/7/98 init graphic keys widget string
1051 // build text string whose characters call out graphic keys from fontk
1054 // skip keys not possessed
1058 hud_gkeysstr
[i
++] = '!'+k
; // key number plus '!' is char for key
1059 hud_gkeysstr
[i
++] = ' '; // spacing
1060 hud_gkeysstr
[i
++] = ' ';
1062 hud_gkeysstr
[i
]='\0';
1064 else // not possible in current code, unless deathmatching,
1067 hud_keysstr
[i
] = '\0'; //jff 3/7/98 make sure deleted keys go away
1069 // if deathmatch, build string showing top four frag counts
1070 if (deathmatch
) //jff 3/17/98 show frags, not keys, in deathmatch
1072 int top1
=-999,top2
=-999,top3
=-999,top4
=-999;
1073 int idx1
=-1,idx2
=-1,idx3
=-1,idx4
=-1;
1077 // scan thru players
1078 for (k
=0;k
<MAXPLAYERS
;k
++)
1080 // skip players not in game
1081 if (!playeringame
[k
])
1085 // compute number of times they've fragged each player
1086 // minus number of times they've been fragged by them
1087 for (m
=0;m
<MAXPLAYERS
;m
++)
1089 if (!playeringame
[m
]) continue;
1090 fragcount
+= (m
!=k
)? players
[k
].frags
[m
] : -players
[k
].frags
[m
];
1093 // very primitive sort of frags to find top four
1096 top4
=top3
; top3
=top2
; top2
= top1
; top1
=fragcount
;
1097 idx4
=idx3
; idx3
=idx2
; idx2
= idx1
; idx1
=k
;
1099 else if (fragcount
>top2
)
1101 top4
=top3
; top3
=top2
; top2
=fragcount
;
1102 idx4
=idx3
; idx3
=idx2
; idx2
=k
;
1104 else if (fragcount
>top3
)
1106 top4
=top3
; top3
=fragcount
;
1109 else if (fragcount
>top4
)
1115 // if the biggest number exists, put it in the init string
1118 snprintf(numbuf
,sizeof(numbuf
),"%5d",top1
);
1119 // make frag count in player's color via escape code
1120 hud_keysstr
[i
++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1121 hud_keysstr
[i
++] = '0'+plyrcoltran
[idx1
&3];
1124 hud_keysstr
[i
++] = *(s
++);
1126 // if the second biggest number exists, put it in the init string
1129 snprintf(numbuf
,sizeof(numbuf
),"%5d",top2
);
1130 // make frag count in player's color via escape code
1131 hud_keysstr
[i
++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1132 hud_keysstr
[i
++] = '0'+plyrcoltran
[idx2
&3];
1135 hud_keysstr
[i
++] = *(s
++);
1137 // if the third biggest number exists, put it in the init string
1140 snprintf(numbuf
,sizeof(numbuf
),"%5d",top3
);
1141 // make frag count in player's color via escape code
1142 hud_keysstr
[i
++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1143 hud_keysstr
[i
++] = '0'+plyrcoltran
[idx3
&3];
1146 hud_keysstr
[i
++] = *(s
++);
1148 // if the fourth biggest number exists, put it in the init string
1151 snprintf(numbuf
,sizeof(numbuf
),"%5d",top4
);
1152 // make frag count in player's color via escape code
1153 hud_keysstr
[i
++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1154 hud_keysstr
[i
++] = '0'+plyrcoltran
[idx4
&3];
1157 hud_keysstr
[i
++] = *(s
++);
1159 hud_keysstr
[i
] = '\0';
1160 } //jff 3/17/98 end of deathmatch clause
1161 else // build alphabetical key display (not used currently)
1166 // skip any not possessed by the displayed player's stats
1170 // use color escapes to make text in key's color
1171 hud_keysstr
[i
++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1175 hud_keysstr
[i
++] = '0'+CR_BLUE
;
1176 hud_keysstr
[i
++] = 'B';
1177 hud_keysstr
[i
++] = 'C';
1178 hud_keysstr
[i
++] = ' ';
1181 hud_keysstr
[i
++] = '0'+CR_GOLD
;
1182 hud_keysstr
[i
++] = 'Y';
1183 hud_keysstr
[i
++] = 'C';
1184 hud_keysstr
[i
++] = ' ';
1187 hud_keysstr
[i
++] = '0'+CR_RED
;
1188 hud_keysstr
[i
++] = 'R';
1189 hud_keysstr
[i
++] = 'C';
1190 hud_keysstr
[i
++] = ' ';
1193 hud_keysstr
[i
++] = '0'+CR_BLUE
;
1194 hud_keysstr
[i
++] = 'B';
1195 hud_keysstr
[i
++] = 'S';
1196 hud_keysstr
[i
++] = ' ';
1199 hud_keysstr
[i
++] = '0'+CR_GOLD
;
1200 hud_keysstr
[i
++] = 'Y';
1201 hud_keysstr
[i
++] = 'S';
1202 hud_keysstr
[i
++] = ' ';
1205 hud_keysstr
[i
++] = '0'+CR_RED
;
1206 hud_keysstr
[i
++] = 'R';
1207 hud_keysstr
[i
++] = 'S';
1208 hud_keysstr
[i
++] = ' ';
1211 hud_keysstr
[i
]='\0';
1216 // display the keys/frags line each frame
1219 HUlib_clearTextLine(&w_keys
); // clear the widget strings
1220 HUlib_clearTextLine(&w_gkeys
);
1222 // transfer the built string (frags or key title) to the widget
1223 s
= hud_keysstr
; //jff 3/7/98 display key titles/key text or frags
1225 HUlib_addCharToTextLine(&w_keys
, *(s
++));
1226 HUlib_drawTextLine(&w_keys
, false);
1228 //jff 3/17/98 show graphic keys in non-DM only
1229 if (!deathmatch
) //jff 3/7/98 display graphic keys
1231 // transfer the graphic key text to the widget
1234 HUlib_addCharToTextLine(&w_gkeys
, *(s
++));
1235 // display the widget
1236 HUlib_drawTextLine(&w_gkeys
, false);
1240 // display the hud kills/items/secret display if optioned
1243 if (hud_active
>1 && doit
)
1245 // clear the internal widget text buffer
1246 HUlib_clearTextLine(&w_monsec
);
1247 //jff 3/26/98 use ESC not '\' for paths
1248 // build the init string with fixed colors
1251 hud_monsecstr
,80*sizeof(char),
1252 "STS \x1b\x36K \x1b\x33%d \x1b\x36M \x1b\x33%d \x1b\x37I \x1b\x33%d/%d \x1b\x35S \x1b\x33%d/%d",
1253 plr
->killcount
,totallive
,
1254 plr
->itemcount
,totalitems
,
1255 plr
->secretcount
,totalsecret
1257 // transfer the init string to the widget
1260 HUlib_addCharToTextLine(&w_monsec
, *(s
++));
1262 // display the kills/items/secrets each frame, if optioned
1264 HUlib_drawTextLine(&w_monsec
, false);
1268 //jff 3/4/98 display last to give priority
1269 HU_Erase(); // jff 4/24/98 Erase current lines before drawing current
1270 // needed when screen not fullsize
1272 //jff 4/21/98 if setup has disabled message list while active, turn it off
1273 if (hud_msg_lines
<=1)
1274 message_list
= false;
1276 // if the message review not enabled, show the standard message widget
1278 HUlib_drawSText(&w_message
);
1280 // if the message review is enabled show the scrolling message review
1281 if (hud_msg_lines
>1 && message_list
)
1282 HUlib_drawMText(&w_rtext
);
1284 // display the interactive buffer for chat entry
1285 HUlib_drawIText(&w_chat
);
1291 // Erase hud display lines that can be trashed by small screen display
1293 // Passed nothing, returns nothing
1297 // erase the message display or the message review display
1299 HUlib_eraseSText(&w_message
);
1301 HUlib_eraseMText(&w_rtext
);
1303 // erase the interactive text buffer for chat entry
1304 HUlib_eraseIText(&w_chat
);
1306 // erase the automap title
1307 HUlib_eraseTextLine(&w_title
);
1313 // Update the hud displays once per frame
1315 // Passed nothing, returns nothing
1317 static boolean bsdown
; // Is backspace down?
1318 static int bscounter
;
1320 void HU_Ticker(void)
1325 // tick down message counter if message is up
1326 if (message_counter
&& !--message_counter
)
1329 message_nottobefuckedwith
= false;
1331 if (bsdown
&& bscounter
++ > 9) {
1332 HUlib_keyInIText(&w_chat
, (unsigned char)key_backspace
);
1336 // if messages on, or "Messages Off" is being displayed
1337 // this allows the notification of turning messages off to be seen
1338 if (showMessages
|| message_dontfuckwithme
)
1340 // display message if necessary
1341 if ((plr
->message
&& !message_nottobefuckedwith
)
1342 || (plr
->message
&& message_dontfuckwithme
))
1344 //post the message to the message widget
1345 HUlib_addMessageToSText(&w_message
, 0, plr
->message
);
1346 //jff 2/26/98 add message to refresh text widget too
1347 HUlib_addMessageToMText(&w_rtext
, 0, plr
->message
);
1349 // clear the message to avoid posting multiple times
1351 // note a message is displayed
1353 // start the message persistence counter
1354 message_counter
= HU_MSGTIMEOUT
;
1355 // transfer "Messages Off" exception to the "being displayed" variable
1356 message_nottobefuckedwith
= message_dontfuckwithme
;
1357 // clear the flag that "Messages Off" is being posted
1358 message_dontfuckwithme
= 0;
1362 // check for incoming chat characters
1365 for (i
=0; i
<MAXPLAYERS
; i
++)
1367 if (!playeringame
[i
])
1369 if (i
!= consoleplayer
1370 && (c
= players
[i
].cmd
.chatchar
))
1372 if (c
<= HU_BROADCAST
)
1376 if (c
>= 'a' && c
<= 'z')
1377 c
= (char) shiftxform
[(unsigned char) c
];
1378 rc
= HUlib_keyInIText(&w_inputbuffer
[i
], c
);
1379 if (rc
&& c
== KEY_ENTER
)
1381 if (w_inputbuffer
[i
].l
.len
1382 && (chat_dest
[i
] == consoleplayer
+1
1383 || chat_dest
[i
] == HU_BROADCAST
))
1385 HUlib_addMessageToSText(&w_message
,
1387 w_inputbuffer
[i
].l
.l
);
1389 message_nottobefuckedwith
= true;
1391 message_counter
= HU_MSGTIMEOUT
;
1392 if ( gamemode
== commercial
)
1393 S_StartSound(0, sfx_radio
);
1395 S_StartSound(0, sfx_tink
);
1397 HUlib_resetIText(&w_inputbuffer
[i
]);
1400 players
[i
].cmd
.chatchar
= 0;
1406 #define QUEUESIZE 128
1408 static char chatchars
[QUEUESIZE
];
1409 static int head
= 0;
1410 static int tail
= 0;
1413 // HU_queueChatChar()
1415 // Add an incoming character to the circular chat queue
1417 // Passed the character to queue, returns nothing
1419 void HU_queueChatChar(char c
)
1421 if (((head
+ 1) & (QUEUESIZE
-1)) == tail
)
1423 plr
->message
= HUSTR_MSGU
;
1427 chatchars
[head
] = c
;
1428 head
= (head
+ 1) & (QUEUESIZE
-1);
1433 // HU_dequeueChatChar()
1435 // Remove the earliest added character from the circular chat queue
1437 // Passed nothing, returns the character dequeued
1439 char HU_dequeueChatChar(void)
1445 c
= chatchars
[tail
];
1446 tail
= (tail
+ 1) & (QUEUESIZE
-1);
1458 // Responds to input events that affect the heads up displays
1460 // Passed the event to respond to, returns true if the event was handled
1462 boolean
HU_Responder(event_t
*ev
)
1465 static char lastmessage
[HU_MAXLINELENGTH
+1];
1466 const char* macromessage
; // CPhipps - const char*
1467 boolean eatkey
= false;
1468 static boolean shiftdown
= false;
1469 static boolean altdown
= false;
1474 static int num_nobrainers
= 0;
1477 for (i
=0 ; i
<MAXPLAYERS
; i
++)
1478 numplayers
+= playeringame
[i
];
1480 if (ev
->data1
== key_shift
)
1482 shiftdown
= ev
->type
== ev_keydown
;
1485 else if (ev
->data1
== key_alt
)
1487 altdown
= ev
->type
== ev_keydown
;
1490 else if (ev
->data1
== key_backspace
)
1492 bsdown
= ev
->type
== ev_keydown
;
1496 if (ev
->type
!= ev_keydown
)
1501 if (ev
->data1
== key_enter
) // phares
1503 #ifndef INSTRUMENTED // never turn on message review if INSTRUMENTED defined
1504 if (hud_msg_lines
>1) // it posts multi-line messages that will trash
1506 if (message_list
) HU_Erase(); //jff 4/28/98 erase behind messages
1507 message_list
= !message_list
; //jff 2/26/98 toggle list of messages
1510 if (!message_list
) // if not message list, refresh message
1513 message_counter
= HU_MSGTIMEOUT
;
1516 }//jff 2/26/98 no chat if message review is displayed
1517 else if (!message_list
&& netgame
&& ev
->data1
== key_chat
)
1519 eatkey
= chat_on
= true;
1520 HUlib_resetIText(&w_chat
);
1521 HU_queueChatChar(HU_BROADCAST
);
1522 }//jff 2/26/98 no chat if message review is displayed
1523 // killough 10/02/98: no chat if demo playback
1524 else if (!demoplayback
&& !message_list
&& netgame
&& numplayers
> 2)
1526 for (i
=0; i
<MAXPLAYERS
; i
++)
1528 if (ev
->data1
== destination_keys
[i
])
1530 if (playeringame
[i
] && i
!=consoleplayer
)
1532 eatkey
= chat_on
= true;
1533 HUlib_resetIText(&w_chat
);
1534 HU_queueChatChar((char)(i
+1));
1537 else if (i
== consoleplayer
)
1540 if (num_nobrainers
< 3)
1541 plr
->message
= HUSTR_TALKTOSELF1
;
1542 else if (num_nobrainers
< 6)
1543 plr
->message
= HUSTR_TALKTOSELF2
;
1544 else if (num_nobrainers
< 9)
1545 plr
->message
= HUSTR_TALKTOSELF3
;
1546 else if (num_nobrainers
< 32)
1547 plr
->message
= HUSTR_TALKTOSELF4
;
1549 plr
->message
= HUSTR_TALKTOSELF5
;
1554 }//jff 2/26/98 no chat functions if message review is displayed
1555 else if (!message_list
)
1564 macromessage
= chat_macros
[c
];
1566 // kill last message with a '\n'
1567 HU_queueChatChar((char)key_enter
); // DEBUG!!! // phares
1569 // send the macro message
1570 while (*macromessage
)
1571 HU_queueChatChar(*macromessage
++);
1572 HU_queueChatChar((char)key_enter
); // phares
1574 // leave chat mode and notify that it was sent
1576 strcpy(lastmessage
, chat_macros
[c
]);
1577 plr
->message
= lastmessage
;
1582 if (shiftdown
|| (c
>= 'a' && c
<= 'z'))
1584 eatkey
= HUlib_keyInIText(&w_chat
, c
);
1586 HU_queueChatChar(c
);
1588 if (c
== key_enter
) // phares
1593 strcpy(lastmessage
, w_chat
.l
.l
);
1594 plr
->message
= lastmessage
;
1597 else if (c
== key_escape
) // phares