aboutsummaryrefslogtreecommitdiff
path: root/src/hu_stuff.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/hu_stuff.c')
-rw-r--r--src/hu_stuff.c1593
1 files changed, 1593 insertions, 0 deletions
diff --git a/src/hu_stuff.c b/src/hu_stuff.c
new file mode 100644
index 0000000..976bc2e
--- /dev/null
+++ b/src/hu_stuff.c
@@ -0,0 +1,1593 @@
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 "st_stuff.h" /* jff 2/16/98 need loc of status bar */
40#include "w_wad.h"
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
48// global heads up display controls
49
50int hud_active; //jff 2/17/98 controls heads-up display mode
51int hud_displayed; //jff 2/23/98 turns heads-up display on/off
52int hud_nosecrets; //jff 2/18/98 allows secrets line to be disabled in HUD
53int hud_distributed; //jff 3/4/98 display HUD in different places on screen
54int hud_graph_keys=1; //jff 3/7/98 display HUD keys as graphics
55
56//
57// Locally used constants, shortcuts.
58//
59// Ty 03/28/98 -
60// These four shortcuts modifed to reflect char ** of mapnamesx[]
61#define HU_TITLE (*mapnames[(gameepisode-1)*9+gamemap-1])
62#define HU_TITLE2 (*mapnames2[gamemap-1])
63#define HU_TITLEP (*mapnamesp[gamemap-1])
64#define HU_TITLET (*mapnamest[gamemap-1])
65#define HU_TITLEHEIGHT 1
66#define HU_TITLEX 0
67//jff 2/16/98 change 167 to ST_Y-1
68// CPhipps - changed to ST_TY
69// proff - changed to 200-ST_HEIGHT for stretching
70#define HU_TITLEY ((200-ST_HEIGHT) - 1 - hu_font[0].height)
71
72//jff 2/16/98 add coord text widget coordinates
73// proff - changed to SCREENWIDTH to 320 for stretching
74#define HU_COORDX (320 - 13*hu_font2['A'-HU_FONTSTART].width)
75//jff 3/3/98 split coord widget into three lines in upper right of screen
76#define HU_COORDX_Y (1 + 0*hu_font['A'-HU_FONTSTART].height)
77#define HU_COORDY_Y (2 + 1*hu_font['A'-HU_FONTSTART].height)
78#define HU_COORDZ_Y (3 + 2*hu_font['A'-HU_FONTSTART].height)
79
80//jff 2/16/98 add ammo, health, armor widgets, 2/22/98 less gap
81#define HU_GAPY 8
82#define HU_HUDHEIGHT (6*HU_GAPY)
83#define HU_HUDX 2
84#define HU_HUDY (200-HU_HUDHEIGHT-1)
85#define HU_MONSECX (HU_HUDX)
86#define HU_MONSECY (HU_HUDY+0*HU_GAPY)
87#define HU_KEYSX (HU_HUDX)
88//jff 3/7/98 add offset for graphic key widget
89#define HU_KEYSGX (HU_HUDX+4*hu_font2['A'-HU_FONTSTART].width)
90#define HU_KEYSY (HU_HUDY+1*HU_GAPY)
91#define HU_WEAPX (HU_HUDX)
92#define HU_WEAPY (HU_HUDY+2*HU_GAPY)
93#define HU_AMMOX (HU_HUDX)
94#define HU_AMMOY (HU_HUDY+3*HU_GAPY)
95#define HU_HEALTHX (HU_HUDX)
96#define HU_HEALTHY (HU_HUDY+4*HU_GAPY)
97#define HU_ARMORX (HU_HUDX)
98#define HU_ARMORY (HU_HUDY+5*HU_GAPY)
99
100//jff 3/4/98 distributed HUD positions
101#define HU_HUDX_LL 2
102#define HU_HUDY_LL (200-2*HU_GAPY-1)
103// proff/nicolas 09/20/98: Changed for high-res
104#define HU_HUDX_LR (320-120)
105#define HU_HUDY_LR (200-2*HU_GAPY-1)
106// proff/nicolas 09/20/98: Changed for high-res
107#define HU_HUDX_UR (320-96)
108#define HU_HUDY_UR 2
109#define HU_MONSECX_D (HU_HUDX_LL)
110#define HU_MONSECY_D (HU_HUDY_LL+0*HU_GAPY)
111#define HU_KEYSX_D (HU_HUDX_LL)
112#define HU_KEYSGX_D (HU_HUDX_LL+4*hu_font2['A'-HU_FONTSTART].width)
113#define HU_KEYSY_D (HU_HUDY_LL+1*HU_GAPY)
114#define HU_WEAPX_D (HU_HUDX_LR)
115#define HU_WEAPY_D (HU_HUDY_LR+0*HU_GAPY)
116#define HU_AMMOX_D (HU_HUDX_LR)
117#define HU_AMMOY_D (HU_HUDY_LR+1*HU_GAPY)
118#define HU_HEALTHX_D (HU_HUDX_UR)
119#define HU_HEALTHY_D (HU_HUDY_UR+0*HU_GAPY)
120#define HU_ARMORX_D (HU_HUDX_UR)
121#define HU_ARMORY_D (HU_HUDY_UR+1*HU_GAPY)
122
123//#define HU_INPUTTOGGLE 't' // not used // phares
124#define HU_INPUTX HU_MSGX
125#define HU_INPUTY (HU_MSGY + HU_MSGHEIGHT*(hu_font[0].height) +1)
126#define HU_INPUTWIDTH 64
127#define HU_INPUTHEIGHT 1
128
129#define key_alt KEYD_RALT
130#define key_shift KEYD_RSHIFT
131
132const char* chat_macros[] =
133// Ty 03/27/98 - *not* externalized
134// CPhipps - const char*
135{
136 HUSTR_CHATMACRO0,
137 HUSTR_CHATMACRO1,
138 HUSTR_CHATMACRO2,
139 HUSTR_CHATMACRO3,
140 HUSTR_CHATMACRO4,
141 HUSTR_CHATMACRO5,
142 HUSTR_CHATMACRO6,
143 HUSTR_CHATMACRO7,
144 HUSTR_CHATMACRO8,
145 HUSTR_CHATMACRO9
146};
147
148const char* player_names[] =
149// Ty 03/27/98 - *not* externalized
150// CPhipps - const char*
151{
152 HUSTR_PLRGREEN,
153 HUSTR_PLRINDIGO,
154 HUSTR_PLRBROWN,
155 HUSTR_PLRRED
156};
157
158//jff 3/17/98 translate player colmap to text color ranges
159int plyrcoltran[MAXPLAYERS]={CR_GREEN,CR_GRAY,CR_BROWN,CR_RED};
160
161char chat_char; // remove later.
162static player_t* plr;
163
164// font sets
165patchnum_t hu_font[HU_FONTSIZE];
166patchnum_t hu_font2[HU_FONTSIZE];
167patchnum_t hu_fontk[HU_FONTSIZE];//jff 3/7/98 added for graphic key indicators
168patchnum_t hu_msgbg[9]; //jff 2/26/98 add patches for message background
169
170// widgets
171static hu_textline_t w_title;
172static hu_stext_t w_message;
173static hu_itext_t w_chat;
174static hu_itext_t w_inputbuffer[MAXPLAYERS];
175static hu_textline_t w_coordx; //jff 2/16/98 new coord widget for automap
176static hu_textline_t w_coordy; //jff 3/3/98 split coord widgets automap
177static hu_textline_t w_coordz; //jff 3/3/98 split coord widgets automap
178static hu_textline_t w_ammo; //jff 2/16/98 new ammo widget for hud
179static hu_textline_t w_health; //jff 2/16/98 new health widget for hud
180static hu_textline_t w_armor; //jff 2/16/98 new armor widget for hud
181static hu_textline_t w_weapon; //jff 2/16/98 new weapon widget for hud
182static hu_textline_t w_keys; //jff 2/16/98 new keys widget for hud
183static hu_textline_t w_gkeys; //jff 3/7/98 graphic keys widget for hud
184static hu_textline_t w_monsec; //jff 2/16/98 new kill/secret widget for hud
185static hu_mtext_t w_rtext; //jff 2/26/98 text message refresh widget
186
187static boolean always_off = false;
188static char chat_dest[MAXPLAYERS];
189boolean chat_on;
190static boolean message_on;
191static boolean message_list; //2/26/98 enable showing list of messages
192boolean message_dontfuckwithme;
193static boolean message_nottobefuckedwith;
194static int message_counter;
195extern int showMessages;
196extern boolean automapactive;
197static boolean headsupactive = false;
198
199//jff 2/16/98 hud supported automap colors added
200int hudcolor_titl; // color range of automap level title
201int hudcolor_xyco; // color range of new coords on automap
202//jff 2/16/98 hud text colors, controls added
203int hudcolor_mesg; // color range of scrolling messages
204int hudcolor_chat; // color range of chat lines
205int hud_msg_lines; // number of message lines in window
206//jff 2/26/98 hud text colors, controls added
207int hudcolor_list; // list of messages color
208int hud_list_bgon; // enable for solid window background for message list
209
210//jff 2/16/98 initialization strings for ammo, health, armor widgets
211static char hud_coordstrx[32];
212static char hud_coordstry[32];
213static char hud_coordstrz[32];
214static char hud_ammostr[80];
215static char hud_healthstr[80];
216static char hud_armorstr[80];
217static char hud_weapstr[80];
218static char hud_keysstr[80];
219static char hud_gkeysstr[80]; //jff 3/7/98 add support for graphic key display
220static char hud_monsecstr[80];
221
222//
223// Builtin map names.
224// The actual names can be found in DStrings.h.
225//
226// Ty 03/27/98 - externalized map name arrays - now in d_deh.c
227// and converted to arrays of pointers to char *
228// See modified HUTITLEx macros
229extern char **mapnames[];
230extern char **mapnames2[];
231extern char **mapnamesp[];
232extern char **mapnamest[];
233
234extern int map_point_coordinates;
235
236// key tables
237// jff 5/10/98 french support removed,
238// as it was not being used and couldn't be easily tested
239//
240const char* shiftxform;
241
242const char english_shiftxform[] =
243{
244 0,
245 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
246 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
247 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
248 31,
249 ' ', '!', '"', '#', '$', '%', '&',
250 '"', // shift-'
251 '(', ')', '*', '+',
252 '<', // shift-,
253 '_', // shift--
254 '>', // shift-.
255 '?', // shift-/
256 ')', // shift-0
257 '!', // shift-1
258 '@', // shift-2
259 '#', // shift-3
260 '$', // shift-4
261 '%', // shift-5
262 '^', // shift-6
263 '&', // shift-7
264 '*', // shift-8
265 '(', // shift-9
266 ':',
267 ':', // shift-;
268 '<',
269 '+', // shift-=
270 '>', '?', '@',
271 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
272 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
273 '[', // shift-[
274 '!', // shift-backslash - OH MY GOD DOES WATCOM SUCK
275 ']', // shift-]
276 '"', '_',
277 '\'', // shift-`
278 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
279 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
280 '{', '|', '}', '~', 127
281};
282
283//
284// HU_Init()
285//
286// Initialize the heads-up display, text that overwrites the primary display
287//
288// Passed nothing, returns nothing
289//
290void HU_Init(void)
291{
292
293 int i;
294 int j;
295 char buffer[9];
296
297 shiftxform = english_shiftxform;
298
299 // load the heads-up font
300 j = HU_FONTSTART;
301 for (i=0;i<HU_FONTSIZE;i++,j++)
302 {
303 if ('0'<=j && j<='9')
304 {
305 sprintf(buffer, "DIG%.1d",j-48);
306 R_SetPatchNum(&hu_font2[i], buffer);
307 sprintf(buffer, "STCFN%.3d",j);
308 R_SetPatchNum(&hu_font[i], buffer);
309 }
310 else if ('A'<=j && j<='Z')
311 {
312 sprintf(buffer, "DIG%c",j);
313 R_SetPatchNum(&hu_font2[i], buffer);
314 sprintf(buffer, "STCFN%.3d",j);
315 R_SetPatchNum(&hu_font[i], buffer);
316 }
317 else if (j=='-')
318 {
319 R_SetPatchNum(&hu_font2[i], "DIG45");
320 R_SetPatchNum(&hu_font[i], "STCFN045");
321 }
322 else if (j=='/')
323 {
324 R_SetPatchNum(&hu_font2[i], "DIG47");
325 R_SetPatchNum(&hu_font[i], "STCFN047");
326 }
327 else if (j==':')
328 {
329 R_SetPatchNum(&hu_font2[i], "DIG58");
330 R_SetPatchNum(&hu_font[i], "STCFN058");
331 }
332 else if (j=='[')
333 {
334 R_SetPatchNum(&hu_font2[i], "DIG91");
335 R_SetPatchNum(&hu_font[i], "STCFN091");
336 }
337 else if (j==']')
338 {
339 R_SetPatchNum(&hu_font2[i], "DIG93");
340 R_SetPatchNum(&hu_font[i], "STCFN093");
341 }
342 else if (j<97)
343 {
344 sprintf(buffer, "STCFN%.3d",j);
345 R_SetPatchNum(&hu_font2[i], buffer);
346 R_SetPatchNum(&hu_font[i], buffer);
347 //jff 2/23/98 make all font chars defined, useful or not
348 }
349 else if (j>122)
350 {
351 sprintf(buffer, "STBR%.3d",j);
352 R_SetPatchNum(&hu_font2[i], buffer);
353 R_SetPatchNum(&hu_font[i], buffer);
354 }
355 else
356 hu_font[i] = hu_font[0]; //jff 2/16/98 account for gap
357 }
358
359 // CPhipps - load patches for message background
360 for (i=0; i<9; i++) {
361 sprintf(buffer, "BOX%c%c", "UCL"[i/3], "LCR"[i%3]);
362 R_SetPatchNum(&hu_msgbg[i], buffer);
363 }
364
365 // CPhipps - load patches for keys and double keys
366 for (i=0; i<6; i++) {
367 sprintf(buffer, "STKEYS%d", i);
368 R_SetPatchNum(&hu_fontk[i], buffer);
369 }
370}
371
372//
373// HU_Stop()
374//
375// Make the heads-up displays inactive
376//
377// Passed nothing, returns nothing
378//
379static void HU_Stop(void)
380{
381 headsupactive = false;
382}
383
384//
385// HU_Start(void)
386//
387// Create and initialize the heads-up widgets, software machines to
388// maintain, update, and display information over the primary display
389//
390// This routine must be called after any change to the heads up configuration
391// in order for the changes to take effect in the actual displays
392//
393// Passed nothing, returns nothing
394//
395void HU_Start(void)
396{
397
398 int i;
399 const char* s; /* cph - const */
400
401 if (headsupactive) // stop before starting
402 HU_Stop();
403
404 plr = &players[displayplayer]; // killough 3/7/98
405 message_on = false;
406 message_dontfuckwithme = false;
407 message_nottobefuckedwith = false;
408 chat_on = false;
409
410 // create the message widget
411 // messages to player in upper-left of screen
412 HUlib_initSText
413 (
414 &w_message,
415 HU_MSGX,
416 HU_MSGY,
417 HU_MSGHEIGHT,
418 hu_font,
419 HU_FONTSTART,
420 hudcolor_mesg,
421 &message_on
422 );
423
424 //jff 2/16/98 added some HUD widgets
425 // create the map title widget - map title display in lower left of automap
426 HUlib_initTextLine
427 (
428 &w_title,
429 HU_TITLEX,
430 HU_TITLEY,
431 hu_font,
432 HU_FONTSTART,
433 hudcolor_titl
434 );
435
436 // create the hud health widget
437 // bargraph and number for amount of health,
438 // lower left or upper right of screen
439 HUlib_initTextLine
440 (
441 &w_health,
442 hud_distributed? HU_HEALTHX_D : HU_HEALTHX, //3/4/98 distribute
443 hud_distributed? HU_HEALTHY_D : HU_HEALTHY,
444 hu_font2,
445 HU_FONTSTART,
446 CR_GREEN
447 );
448
449 // create the hud armor widget
450 // bargraph and number for amount of armor,
451 // lower left or upper right of screen
452 HUlib_initTextLine
453 (
454 &w_armor,
455 hud_distributed? HU_ARMORX_D : HU_ARMORX, //3/4/98 distribute
456 hud_distributed? HU_ARMORY_D : HU_ARMORY,
457 hu_font2,
458 HU_FONTSTART,
459 CR_GREEN
460 );
461
462 // create the hud ammo widget
463 // bargraph and number for amount of ammo for current weapon,
464 // lower left or lower right of screen
465 HUlib_initTextLine
466 (
467 &w_ammo,
468 hud_distributed? HU_AMMOX_D : HU_AMMOX, //3/4/98 distribute
469 hud_distributed? HU_AMMOY_D : HU_AMMOY,
470 hu_font2,
471 HU_FONTSTART,
472 CR_GOLD
473 );
474
475 // create the hud weapons widget
476 // list of numbers of weapons possessed
477 // lower left or lower right of screen
478 HUlib_initTextLine
479 (
480 &w_weapon,
481 hud_distributed? HU_WEAPX_D : HU_WEAPX, //3/4/98 distribute
482 hud_distributed? HU_WEAPY_D : HU_WEAPY,
483 hu_font2,
484 HU_FONTSTART,
485 CR_GRAY
486 );
487
488 // create the hud keys widget
489 // display of key letters possessed
490 // lower left of screen
491 HUlib_initTextLine
492 (
493 &w_keys,
494 hud_distributed? HU_KEYSX_D : HU_KEYSX, //3/4/98 distribute
495 hud_distributed? HU_KEYSY_D : HU_KEYSY,
496 hu_font2,
497 HU_FONTSTART,
498 CR_GRAY
499 );
500
501 // create the hud graphic keys widget
502 // display of key graphics possessed
503 // lower left of screen
504 HUlib_initTextLine
505 (
506 &w_gkeys,
507 hud_distributed? HU_KEYSGX_D : HU_KEYSGX, //3/4/98 distribute
508 hud_distributed? HU_KEYSY_D : HU_KEYSY,
509 hu_fontk,
510 HU_FONTSTART,
511 CR_RED
512 );
513
514 // create the hud monster/secret widget
515 // totals and current values for kills, items, secrets
516 // lower left of screen
517 HUlib_initTextLine
518 (
519 &w_monsec,
520 hud_distributed? HU_MONSECX_D : HU_MONSECX, //3/4/98 distribute
521 hud_distributed? HU_MONSECY_D : HU_MONSECY,
522 hu_font2,
523 HU_FONTSTART,
524 CR_GRAY
525 );
526
527 // create the hud text refresh widget
528 // scrolling display of last hud_msg_lines messages received
529 if (hud_msg_lines>HU_MAXMESSAGES)
530 hud_msg_lines=HU_MAXMESSAGES;
531 //jff 4/21/98 if setup has disabled message list while active, turn it off
532 message_list = hud_msg_lines > 1; //jff 8/8/98 initialize both ways
533 //jff 2/26/98 add the text refresh widget initialization
534 HUlib_initMText
535 (
536 &w_rtext,
537 0,
538 0,
539 320,
540// SCREENWIDTH,
541 (hud_msg_lines+2)*HU_REFRESHSPACING,
542 hu_font,
543 HU_FONTSTART,
544 hudcolor_list,
545 hu_msgbg,
546 &message_list
547 );
548
549 // initialize the automap's level title widget
550 if (gamestate == GS_LEVEL) /* cph - stop SEGV here when not in level */
551 switch (gamemode)
552 {
553 case shareware:
554 case registered:
555 case retail:
556 s = HU_TITLE;
557 break;
558
559 case commercial:
560 default: // Ty 08/27/98 - modified to check mission for TNT/Plutonia
561 s = (gamemission==pack_tnt) ? HU_TITLET :
562 (gamemission==pack_plut) ? HU_TITLEP : HU_TITLE2;
563 break;
564 } else s = "";
565 while (*s)
566 HUlib_addCharToTextLine(&w_title, *(s++));
567
568 // create the automaps coordinate widget
569 // jff 3/3/98 split coord widget into three lines: x,y,z
570 // jff 2/16/98 added
571 HUlib_initTextLine
572 (
573 &w_coordx,
574 HU_COORDX,
575 HU_COORDX_Y,
576 hu_font,
577 HU_FONTSTART,
578 hudcolor_xyco
579 );
580 HUlib_initTextLine
581 (
582 &w_coordy,
583 HU_COORDX,
584 HU_COORDY_Y,
585 hu_font,
586 HU_FONTSTART,
587 hudcolor_xyco
588 );
589 HUlib_initTextLine
590 (
591 &w_coordz,
592 HU_COORDX,
593 HU_COORDZ_Y,
594 hu_font,
595 HU_FONTSTART,
596 hudcolor_xyco
597 );
598
599 // initialize the automaps coordinate widget
600 //jff 3/3/98 split coordstr widget into 3 parts
601 if (map_point_coordinates)
602 {
603 sprintf(hud_coordstrx,"X: %-5d",0); //jff 2/22/98 added z
604 s = hud_coordstrx;
605 while (*s)
606 HUlib_addCharToTextLine(&w_coordx, *(s++));
607 sprintf(hud_coordstry,"Y: %-5d",0); //jff 3/3/98 split x,y,z
608 s = hud_coordstry;
609 while (*s)
610 HUlib_addCharToTextLine(&w_coordy, *(s++));
611 sprintf(hud_coordstrz,"Z: %-5d",0); //jff 3/3/98 split x,y,z
612 s = hud_coordstrz;
613 while (*s)
614 HUlib_addCharToTextLine(&w_coordz, *(s++));
615 }
616
617 //jff 2/16/98 initialize ammo widget
618 strcpy(hud_ammostr,"AMM ");
619 s = hud_ammostr;
620 while (*s)
621 HUlib_addCharToTextLine(&w_ammo, *(s++));
622
623 //jff 2/16/98 initialize health widget
624 strcpy(hud_healthstr,"HEL ");
625 s = hud_healthstr;
626 while (*s)
627 HUlib_addCharToTextLine(&w_health, *(s++));
628
629 //jff 2/16/98 initialize armor widget
630 strcpy(hud_armorstr,"ARM ");
631 s = hud_armorstr;
632 while (*s)
633 HUlib_addCharToTextLine(&w_armor, *(s++));
634
635 //jff 2/17/98 initialize weapons widget
636 strcpy(hud_weapstr,"WEA ");
637 s = hud_weapstr;
638 while (*s)
639 HUlib_addCharToTextLine(&w_weapon, *(s++));
640
641 //jff 2/17/98 initialize keys widget
642 if (!deathmatch) //jff 3/17/98 show frags in deathmatch mode
643 strcpy(hud_keysstr,"KEY ");
644 else
645 strcpy(hud_keysstr,"FRG ");
646 s = hud_keysstr;
647 while (*s)
648 HUlib_addCharToTextLine(&w_keys, *(s++));
649
650 //jff 2/17/98 initialize graphic keys widget
651 strcpy(hud_gkeysstr," ");
652 s = hud_gkeysstr;
653 while (*s)
654 HUlib_addCharToTextLine(&w_gkeys, *(s++));
655
656 //jff 2/17/98 initialize kills/items/secret widget
657 strcpy(hud_monsecstr,"STS ");
658 s = hud_monsecstr;
659 while (*s)
660 HUlib_addCharToTextLine(&w_monsec, *(s++));
661
662 // create the chat widget
663 HUlib_initIText
664 (
665 &w_chat,
666 HU_INPUTX,
667 HU_INPUTY,
668 hu_font,
669 HU_FONTSTART,
670 hudcolor_chat,
671 &chat_on
672 );
673
674 // create the inputbuffer widgets, one per player
675 for (i=0 ; i<MAXPLAYERS ; i++)
676 HUlib_initIText
677 (
678 &w_inputbuffer[i],
679 0,
680 0,
681 0,
682 0,
683 hudcolor_chat,
684 &always_off
685 );
686
687 // now allow the heads-up display to run
688 headsupactive = true;
689}
690
691//
692// HU_MoveHud()
693//
694// Move the HUD display from distributed to compact mode or vice-versa
695//
696// Passed nothing, returns nothing
697//
698//jff 3/9/98 create this externally callable to avoid glitch
699// when menu scatter's HUD due to delay in change of position
700//
701void HU_MoveHud(void)
702{
703 static int ohud_distributed=-1;
704
705 //jff 3/4/98 move displays around on F5 changing hud_distributed
706 if (hud_distributed!=ohud_distributed)
707 {
708 w_ammo.x = hud_distributed? HU_AMMOX_D : HU_AMMOX;
709 w_ammo.y = hud_distributed? HU_AMMOY_D : HU_AMMOY;
710 w_weapon.x = hud_distributed? HU_WEAPX_D : HU_WEAPX;
711 w_weapon.y = hud_distributed? HU_WEAPY_D : HU_WEAPY;
712 w_keys.x = hud_distributed? HU_KEYSX_D : HU_KEYSX;
713 w_keys.y = hud_distributed? HU_KEYSY_D : HU_KEYSY;
714 w_gkeys.x = hud_distributed? HU_KEYSGX_D : HU_KEYSGX;
715 w_gkeys.y = hud_distributed? HU_KEYSY_D : HU_KEYSY;
716 w_monsec.x = hud_distributed? HU_MONSECX_D : HU_MONSECX;
717 w_monsec.y = hud_distributed? HU_MONSECY_D : HU_MONSECY;
718 w_health.x = hud_distributed? HU_HEALTHX_D : HU_HEALTHX;
719 w_health.y = hud_distributed? HU_HEALTHY_D : HU_HEALTHY;
720 w_armor.x = hud_distributed? HU_ARMORX_D : HU_ARMORX;
721 w_armor.y = hud_distributed? HU_ARMORY_D : HU_ARMORY;
722 }
723 ohud_distributed = hud_distributed;
724}
725
726//
727// HU_Drawer()
728//
729// Draw all the pieces of the heads-up display
730//
731// Passed nothing, returns nothing
732//
733void HU_Drawer(void)
734{
735 char *s;
736 player_t *plr;
737 char ammostr[80]; //jff 3/8/98 allow plenty room for dehacked mods
738 char healthstr[80];//jff
739 char armorstr[80]; //jff
740 int i,doit;
741
742 plr = &players[displayplayer]; // killough 3/7/98
743 // draw the automap widgets if automap is displayed
744 if (automapmode & am_active)
745 {
746 // map title
747 HUlib_drawTextLine(&w_title, false);
748
749 //jff 2/16/98 output new coord display
750 // x-coord
751 if (map_point_coordinates)
752 {
753 sprintf(hud_coordstrx,"X: %-5d", (plr->mo->x)>>FRACBITS);
754 HUlib_clearTextLine(&w_coordx);
755 s = hud_coordstrx;
756 while (*s)
757 HUlib_addCharToTextLine(&w_coordx, *(s++));
758 HUlib_drawTextLine(&w_coordx, false);
759
760 //jff 3/3/98 split coord display into x,y,z lines
761 // y-coord
762 sprintf(hud_coordstry,"Y: %-5d", (plr->mo->y)>>FRACBITS);
763 HUlib_clearTextLine(&w_coordy);
764 s = hud_coordstry;
765 while (*s)
766 HUlib_addCharToTextLine(&w_coordy, *(s++));
767 HUlib_drawTextLine(&w_coordy, false);
768
769 //jff 3/3/98 split coord display into x,y,z lines
770 //jff 2/22/98 added z
771 // z-coord
772 sprintf(hud_coordstrz,"Z: %-5d", (plr->mo->z)>>FRACBITS);
773 HUlib_clearTextLine(&w_coordz);
774 s = hud_coordstrz;
775 while (*s)
776 HUlib_addCharToTextLine(&w_coordz, *(s++));
777 HUlib_drawTextLine(&w_coordz, false);
778 }
779 }
780
781 // draw the weapon/health/ammo/armor/kills/keys displays if optioned
782 //jff 2/17/98 allow new hud stuff to be turned off
783 // killough 2/21/98: really allow new hud stuff to be turned off COMPLETELY
784 if
785 (
786 hud_active>0 && // hud optioned on
787 hud_displayed && // hud on from fullscreen key
788 viewheight==SCREENHEIGHT && // fullscreen mode is active
789 !(automapmode & am_active) // automap is not active
790 )
791 {
792 doit = !(gametic&1); //jff 3/4/98 speed update up for slow systems
793 if (doit) //jff 8/7/98 update every time, avoid lag in update
794 {
795 HU_MoveHud(); // insure HUD display coords are correct
796
797 // do the hud ammo display
798 // clear the widgets internal line
799 HUlib_clearTextLine(&w_ammo);
800 strcpy(hud_ammostr,"AMM ");
801 if (weaponinfo[plr->readyweapon].ammo == am_noammo)
802 { // special case for weapon with no ammo selected - blank bargraph + N/A
803 strcat(hud_ammostr,"\x7f\x7f\x7f\x7f\x7f\x7f\x7f N/A");
804 w_ammo.cm = CR_GRAY;
805 }
806 else
807 {
808 int ammo = plr->ammo[weaponinfo[plr->readyweapon].ammo];
809 int fullammo = plr->maxammo[weaponinfo[plr->readyweapon].ammo];
810 int ammopct = (100*ammo)/fullammo;
811 int ammobars = ammopct/4;
812
813 // build the numeric amount init string
814 sprintf(ammostr,"%d/%d",ammo,fullammo);
815 // build the bargraph string
816 // full bargraph chars
817 for (i=4;i<4+ammobars/4;)
818 hud_ammostr[i++] = 123;
819 // plus one last character with 0,1,2,3 bars
820 switch(ammobars%4)
821 {
822 case 0:
823 break;
824 case 1:
825 hud_ammostr[i++] = 126;
826 break;
827 case 2:
828 hud_ammostr[i++] = 125;
829 break;
830 case 3:
831 hud_ammostr[i++] = 124;
832 break;
833 }
834 // pad string with blank bar characters
835 while(i<4+7)
836 hud_ammostr[i++] = 127;
837 hud_ammostr[i] = '\0';
838 strcat(hud_ammostr,ammostr);
839
840 // set the display color from the percentage of total ammo held
841 if (ammopct<ammo_red)
842 w_ammo.cm = CR_RED;
843 else if (ammopct<ammo_yellow)
844 w_ammo.cm = CR_GOLD;
845 else
846 w_ammo.cm = CR_GREEN;
847 }
848 // transfer the init string to the widget
849 s = hud_ammostr;
850 while (*s)
851 HUlib_addCharToTextLine(&w_ammo, *(s++));
852 }
853 // display the ammo widget every frame
854 HUlib_drawTextLine(&w_ammo, false);
855
856 // do the hud health display
857 if (doit)
858 {
859 int health = plr->health;
860 int healthbars = health>100? 25 : health/4;
861
862 // clear the widgets internal line
863 HUlib_clearTextLine(&w_health);
864
865 // build the numeric amount init string
866 sprintf(healthstr,"%3d",health);
867 // build the bargraph string
868 // full bargraph chars
869 for (i=4;i<4+healthbars/4;)
870 hud_healthstr[i++] = 123;
871 // plus one last character with 0,1,2,3 bars
872 switch(healthbars%4)
873 {
874 case 0:
875 break;
876 case 1:
877 hud_healthstr[i++] = 126;
878 break;
879 case 2:
880 hud_healthstr[i++] = 125;
881 break;
882 case 3:
883 hud_healthstr[i++] = 124;
884 break;
885 }
886 // pad string with blank bar characters
887 while(i<4+7)
888 hud_healthstr[i++] = 127;
889 hud_healthstr[i] = '\0';
890 strcat(hud_healthstr,healthstr);
891
892 // set the display color from the amount of health posessed
893 if (health<health_red)
894 w_health.cm = CR_RED;
895 else if (health<health_yellow)
896 w_health.cm = CR_GOLD;
897 else if (health<=health_green)
898 w_health.cm = CR_GREEN;
899 else
900 w_health.cm = CR_BLUE;
901
902 // transfer the init string to the widget
903 s = hud_healthstr;
904 while (*s)
905 HUlib_addCharToTextLine(&w_health, *(s++));
906 }
907 // display the health widget every frame
908 HUlib_drawTextLine(&w_health, false);
909
910 // do the hud armor display
911 if (doit)
912 {
913 int armor = plr->armorpoints;
914 int armorbars = armor>100? 25 : armor/4;
915
916 // clear the widgets internal line
917 HUlib_clearTextLine(&w_armor);
918 // build the numeric amount init string
919 sprintf(armorstr,"%3d",armor);
920 // build the bargraph string
921 // full bargraph chars
922 for (i=4;i<4+armorbars/4;)
923 hud_armorstr[i++] = 123;
924 // plus one last character with 0,1,2,3 bars
925 switch(armorbars%4)
926 {
927 case 0:
928 break;
929 case 1:
930 hud_armorstr[i++] = 126;
931 break;
932 case 2:
933 hud_armorstr[i++] = 125;
934 break;
935 case 3:
936 hud_armorstr[i++] = 124;
937 break;
938 }
939 // pad string with blank bar characters
940 while(i<4+7)
941 hud_armorstr[i++] = 127;
942 hud_armorstr[i] = '\0';
943 strcat(hud_armorstr,armorstr);
944
945 // set the display color from the amount of armor posessed
946 if (armor<armor_red)
947 w_armor.cm = CR_RED;
948 else if (armor<armor_yellow)
949 w_armor.cm = CR_GOLD;
950 else if (armor<=armor_green)
951 w_armor.cm = CR_GREEN;
952 else
953 w_armor.cm = CR_BLUE;
954
955 // transfer the init string to the widget
956 s = hud_armorstr;
957 while (*s)
958 HUlib_addCharToTextLine(&w_armor, *(s++));
959 }
960 // display the armor widget every frame
961 HUlib_drawTextLine(&w_armor, false);
962
963 // do the hud weapon display
964 if (doit)
965 {
966 int w;
967 int ammo,fullammo,ammopct;
968
969 // clear the widgets internal line
970 HUlib_clearTextLine(&w_weapon);
971 i=4; hud_weapstr[i] = '\0'; //jff 3/7/98 make sure ammo goes away
972
973 // do each weapon that exists in current gamemode
974 for (w=0;w<=wp_supershotgun;w++) //jff 3/4/98 show fists too, why not?
975 {
976 int ok=1;
977 //jff avoid executing for weapons that do not exist
978 switch (gamemode)
979 {
980 case shareware:
981 if (w>=wp_plasma && w!=wp_chainsaw)
982 ok=0;
983 break;
984 case retail:
985 case registered:
986 if (w>=wp_supershotgun)
987 ok=0;
988 break;
989 default:
990 case commercial:
991 break;
992 }
993 if (!ok) continue;
994
995 ammo = plr->ammo[weaponinfo[w].ammo];
996 fullammo = plr->maxammo[weaponinfo[w].ammo];
997 ammopct=0;
998
999 // skip weapons not currently posessed
1000 if (!plr->weaponowned[w])
1001 continue;
1002
1003 ammopct = fullammo? (100*ammo)/fullammo : 100;
1004
1005 // display each weapon number in a color related to the ammo for it
1006 hud_weapstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1007 if (weaponinfo[w].ammo==am_noammo) //jff 3/14/98 show berserk on HUD
1008 hud_weapstr[i++] = plr->powers[pw_strength]? '0'+CR_GREEN : '0'+CR_GRAY;
1009 else if (ammopct<ammo_red)
1010 hud_weapstr[i++] = '0'+CR_RED;
1011 else if (ammopct<ammo_yellow)
1012 hud_weapstr[i++] = '0'+CR_GOLD;
1013 else
1014 hud_weapstr[i++] = '0'+CR_GREEN;
1015 hud_weapstr[i++] = '0'+w+1;
1016 hud_weapstr[i++] = ' ';
1017 hud_weapstr[i] = '\0';
1018 }
1019
1020 // transfer the init string to the widget
1021 s = hud_weapstr;
1022 while (*s)
1023 HUlib_addCharToTextLine(&w_weapon, *(s++));
1024 }
1025 // display the weapon widget every frame
1026 HUlib_drawTextLine(&w_weapon, false);
1027
1028 if (doit && hud_active>1)
1029 {
1030 int k;
1031
1032 hud_keysstr[4] = '\0'; //jff 3/7/98 make sure deleted keys go away
1033 //jff add case for graphic key display
1034 if (!deathmatch && hud_graph_keys)
1035 {
1036 i=0;
1037 hud_gkeysstr[i] = '\0'; //jff 3/7/98 init graphic keys widget string
1038 // build text string whose characters call out graphic keys from fontk
1039 for (k=0;k<6;k++)
1040 {
1041 // skip keys not possessed
1042 if (!plr->cards[k])
1043 continue;
1044
1045 hud_gkeysstr[i++] = '!'+k; // key number plus '!' is char for key
1046 hud_gkeysstr[i++] = ' '; // spacing
1047 hud_gkeysstr[i++] = ' ';
1048 }
1049 hud_gkeysstr[i]='\0';
1050 }
1051 else // not possible in current code, unless deathmatching,
1052 {
1053 i=4;
1054 hud_keysstr[i] = '\0'; //jff 3/7/98 make sure deleted keys go away
1055
1056 // if deathmatch, build string showing top four frag counts
1057 if (deathmatch) //jff 3/17/98 show frags, not keys, in deathmatch
1058 {
1059 int top1=-999,top2=-999,top3=-999,top4=-999;
1060 int idx1=-1,idx2=-1,idx3=-1,idx4=-1;
1061 int fragcount,m;
1062 char numbuf[32];
1063
1064 // scan thru players
1065 for (k=0;k<MAXPLAYERS;k++)
1066 {
1067 // skip players not in game
1068 if (!playeringame[k])
1069 continue;
1070
1071 fragcount = 0;
1072 // compute number of times they've fragged each player
1073 // minus number of times they've been fragged by them
1074 for (m=0;m<MAXPLAYERS;m++)
1075 {
1076 if (!playeringame[m]) continue;
1077 fragcount += (m!=k)? players[k].frags[m] : -players[k].frags[m];
1078 }
1079
1080 // very primitive sort of frags to find top four
1081 if (fragcount>top1)
1082 {
1083 top4=top3; top3=top2; top2 = top1; top1=fragcount;
1084 idx4=idx3; idx3=idx2; idx2 = idx1; idx1=k;
1085 }
1086 else if (fragcount>top2)
1087 {
1088 top4=top3; top3=top2; top2=fragcount;
1089 idx4=idx3; idx3=idx2; idx2=k;
1090 }
1091 else if (fragcount>top3)
1092 {
1093 top4=top3; top3=fragcount;
1094 idx4=idx3; idx3=k;
1095 }
1096 else if (fragcount>top4)
1097 {
1098 top4=fragcount;
1099 idx4=k;
1100 }
1101 }
1102 // if the biggest number exists, put it in the init string
1103 if (idx1>-1)
1104 {
1105 sprintf(numbuf,"%5d",top1);
1106 // make frag count in player's color via escape code
1107 hud_keysstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1108 hud_keysstr[i++] = '0'+plyrcoltran[idx1&3];
1109 s = numbuf;
1110 while (*s)
1111 hud_keysstr[i++] = *(s++);
1112 }
1113 // if the second biggest number exists, put it in the init string
1114 if (idx2>-1)
1115 {
1116 sprintf(numbuf,"%5d",top2);
1117 // make frag count in player's color via escape code
1118 hud_keysstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1119 hud_keysstr[i++] = '0'+plyrcoltran[idx2&3];
1120 s = numbuf;
1121 while (*s)
1122 hud_keysstr[i++] = *(s++);
1123 }
1124 // if the third biggest number exists, put it in the init string
1125 if (idx3>-1)
1126 {
1127 sprintf(numbuf,"%5d",top3);
1128 // make frag count in player's color via escape code
1129 hud_keysstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1130 hud_keysstr[i++] = '0'+plyrcoltran[idx3&3];
1131 s = numbuf;
1132 while (*s)
1133 hud_keysstr[i++] = *(s++);
1134 }
1135 // if the fourth biggest number exists, put it in the init string
1136 if (idx4>-1)
1137 {
1138 sprintf(numbuf,"%5d",top4);
1139 // make frag count in player's color via escape code
1140 hud_keysstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1141 hud_keysstr[i++] = '0'+plyrcoltran[idx4&3];
1142 s = numbuf;
1143 while (*s)
1144 hud_keysstr[i++] = *(s++);
1145 }
1146 hud_keysstr[i] = '\0';
1147 } //jff 3/17/98 end of deathmatch clause
1148 else // build alphabetical key display (not used currently)
1149 {
1150 // scan the keys
1151 for (k=0;k<6;k++)
1152 {
1153 // skip any not possessed by the displayed player's stats
1154 if (!plr->cards[k])
1155 continue;
1156
1157 // use color escapes to make text in key's color
1158 hud_keysstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
1159 switch(k)
1160 {
1161 case 0:
1162 hud_keysstr[i++] = '0'+CR_BLUE;
1163 hud_keysstr[i++] = 'B';
1164 hud_keysstr[i++] = 'C';
1165 hud_keysstr[i++] = ' ';
1166 break;
1167 case 1:
1168 hud_keysstr[i++] = '0'+CR_GOLD;
1169 hud_keysstr[i++] = 'Y';
1170 hud_keysstr[i++] = 'C';
1171 hud_keysstr[i++] = ' ';
1172 break;
1173 case 2:
1174 hud_keysstr[i++] = '0'+CR_RED;
1175 hud_keysstr[i++] = 'R';
1176 hud_keysstr[i++] = 'C';
1177 hud_keysstr[i++] = ' ';
1178 break;
1179 case 3:
1180 hud_keysstr[i++] = '0'+CR_BLUE;
1181 hud_keysstr[i++] = 'B';
1182 hud_keysstr[i++] = 'S';
1183 hud_keysstr[i++] = ' ';
1184 break;
1185 case 4:
1186 hud_keysstr[i++] = '0'+CR_GOLD;
1187 hud_keysstr[i++] = 'Y';
1188 hud_keysstr[i++] = 'S';
1189 hud_keysstr[i++] = ' ';
1190 break;
1191 case 5:
1192 hud_keysstr[i++] = '0'+CR_RED;
1193 hud_keysstr[i++] = 'R';
1194 hud_keysstr[i++] = 'S';
1195 hud_keysstr[i++] = ' ';
1196 break;
1197 }
1198 hud_keysstr[i]='\0';
1199 }
1200 }
1201 }
1202 }
1203 // display the keys/frags line each frame
1204 if (hud_active>1)
1205 {
1206 HUlib_clearTextLine(&w_keys); // clear the widget strings
1207 HUlib_clearTextLine(&w_gkeys);
1208
1209 // transfer the built string (frags or key title) to the widget
1210 s = hud_keysstr; //jff 3/7/98 display key titles/key text or frags
1211 while (*s)
1212 HUlib_addCharToTextLine(&w_keys, *(s++));
1213 HUlib_drawTextLine(&w_keys, false);
1214
1215 //jff 3/17/98 show graphic keys in non-DM only
1216 if (!deathmatch) //jff 3/7/98 display graphic keys
1217 {
1218 // transfer the graphic key text to the widget
1219 s = hud_gkeysstr;
1220 while (*s)
1221 HUlib_addCharToTextLine(&w_gkeys, *(s++));
1222 // display the widget
1223 HUlib_drawTextLine(&w_gkeys, false);
1224 }
1225 }
1226
1227 // display the hud kills/items/secret display if optioned
1228 if (!hud_nosecrets)
1229 {
1230 if (hud_active>1 && doit)
1231 {
1232 // clear the internal widget text buffer
1233 HUlib_clearTextLine(&w_monsec);
1234 //jff 3/26/98 use ESC not '\' for paths
1235 // build the init string with fixed colors
1236 sprintf
1237 (
1238 hud_monsecstr,
1239 "STS \x1b\x36K \x1b\x33%d \x1b\x36M \x1b\x33%d \x1b\x37I \x1b\x33%d/%d \x1b\x35S \x1b\x33%d/%d",
1240 plr->killcount,totallive,
1241 plr->itemcount,totalitems,
1242 plr->secretcount,totalsecret
1243 );
1244 // transfer the init string to the widget
1245 s = hud_monsecstr;
1246 while (*s)
1247 HUlib_addCharToTextLine(&w_monsec, *(s++));
1248 }
1249 // display the kills/items/secrets each frame, if optioned
1250 if (hud_active>1)
1251 HUlib_drawTextLine(&w_monsec, false);
1252 }
1253 }
1254
1255 //jff 3/4/98 display last to give priority
1256 HU_Erase(); // jff 4/24/98 Erase current lines before drawing current
1257 // needed when screen not fullsize
1258
1259 //jff 4/21/98 if setup has disabled message list while active, turn it off
1260 if (hud_msg_lines<=1)
1261 message_list = false;
1262
1263 // if the message review not enabled, show the standard message widget
1264 if (!message_list)
1265 HUlib_drawSText(&w_message);
1266
1267 // if the message review is enabled show the scrolling message review
1268 if (hud_msg_lines>1 && message_list)
1269 HUlib_drawMText(&w_rtext);
1270
1271 // display the interactive buffer for chat entry
1272 HUlib_drawIText(&w_chat);
1273}
1274
1275//
1276// HU_Erase()
1277//
1278// Erase hud display lines that can be trashed by small screen display
1279//
1280// Passed nothing, returns nothing
1281//
1282void HU_Erase(void)
1283{
1284 // erase the message display or the message review display
1285 if (!message_list)
1286 HUlib_eraseSText(&w_message);
1287 else
1288 HUlib_eraseMText(&w_rtext);
1289
1290 // erase the interactive text buffer for chat entry
1291 HUlib_eraseIText(&w_chat);
1292
1293 // erase the automap title
1294 HUlib_eraseTextLine(&w_title);
1295}
1296
1297//
1298// HU_Ticker()
1299//
1300// Update the hud displays once per frame
1301//
1302// Passed nothing, returns nothing
1303//
1304static boolean bsdown; // Is backspace down?
1305static int bscounter;
1306
1307void HU_Ticker(void)
1308{
1309 int i, rc;
1310 char c;
1311
1312 // tick down message counter if message is up
1313 if (message_counter && !--message_counter)
1314 {
1315 message_on = false;
1316 message_nottobefuckedwith = false;
1317 }
1318 if (bsdown && bscounter++ > 9) {
1319 HUlib_keyInIText(&w_chat, (unsigned char)key_backspace);
1320 bscounter = 8;
1321 }
1322
1323 // if messages on, or "Messages Off" is being displayed
1324 // this allows the notification of turning messages off to be seen
1325 if (showMessages || message_dontfuckwithme)
1326 {
1327 // display message if necessary
1328 if ((plr->message && !message_nottobefuckedwith)
1329 || (plr->message && message_dontfuckwithme))
1330 {
1331 //post the message to the message widget
1332 HUlib_addMessageToSText(&w_message, 0, plr->message);
1333 //jff 2/26/98 add message to refresh text widget too
1334 HUlib_addMessageToMText(&w_rtext, 0, plr->message);
1335
1336 // clear the message to avoid posting multiple times
1337 plr->message = 0;
1338 // note a message is displayed
1339 message_on = true;
1340 // start the message persistence counter
1341 message_counter = HU_MSGTIMEOUT;
1342 // transfer "Messages Off" exception to the "being displayed" variable
1343 message_nottobefuckedwith = message_dontfuckwithme;
1344 // clear the flag that "Messages Off" is being posted
1345 message_dontfuckwithme = 0;
1346 }
1347 }
1348
1349 // check for incoming chat characters
1350 if (netgame)
1351 {
1352 for (i=0; i<MAXPLAYERS; i++)
1353 {
1354 if (!playeringame[i])
1355 continue;
1356 if (i != consoleplayer
1357 && (c = players[i].cmd.chatchar))
1358 {
1359 if (c <= HU_BROADCAST)
1360 chat_dest[i] = c;
1361 else
1362 {
1363 if (c >= 'a' && c <= 'z')
1364 c = (char) shiftxform[(unsigned char) c];
1365 rc = HUlib_keyInIText(&w_inputbuffer[i], c);
1366 if (rc && c == KEYD_ENTER)
1367 {
1368 if (w_inputbuffer[i].l.len
1369 && (chat_dest[i] == consoleplayer+1
1370 || chat_dest[i] == HU_BROADCAST))
1371 {
1372 HUlib_addMessageToSText(&w_message,
1373 player_names[i],
1374 w_inputbuffer[i].l.l);
1375
1376 message_nottobefuckedwith = true;
1377 message_on = true;
1378 message_counter = HU_MSGTIMEOUT;
1379 if ( gamemode == commercial )
1380 S_StartSound(0, sfx_radio);
1381 else
1382 S_StartSound(0, sfx_tink);
1383 }
1384 HUlib_resetIText(&w_inputbuffer[i]);
1385 }
1386 }
1387 players[i].cmd.chatchar = 0;
1388 }
1389 }
1390 }
1391}
1392
1393#define QUEUESIZE 128
1394
1395static char chatchars[QUEUESIZE];
1396static int head = 0;
1397static int tail = 0;
1398
1399//
1400// HU_queueChatChar()
1401//
1402// Add an incoming character to the circular chat queue
1403//
1404// Passed the character to queue, returns nothing
1405//
1406static void HU_queueChatChar(char c)
1407{
1408 if (((head + 1) & (QUEUESIZE-1)) == tail)
1409 {
1410 plr->message = HUSTR_MSGU;
1411 }
1412 else
1413 {
1414 chatchars[head] = c;
1415 head = (head + 1) & (QUEUESIZE-1);
1416 }
1417}
1418
1419//
1420// HU_dequeueChatChar()
1421//
1422// Remove the earliest added character from the circular chat queue
1423//
1424// Passed nothing, returns the character dequeued
1425//
1426char HU_dequeueChatChar(void)
1427{
1428 char c;
1429
1430 if (head != tail)
1431 {
1432 c = chatchars[tail];
1433 tail = (tail + 1) & (QUEUESIZE-1);
1434 }
1435 else
1436 {
1437 c = 0;
1438 }
1439 return c;
1440}
1441
1442//
1443// HU_Responder()
1444//
1445// Responds to input events that affect the heads up displays
1446//
1447// Passed the event to respond to, returns true if the event was handled
1448//
1449boolean HU_Responder(event_t *ev)
1450{
1451
1452 static char lastmessage[HU_MAXLINELENGTH+1];
1453 const char* macromessage; // CPhipps - const char*
1454 boolean eatkey = false;
1455 static boolean shiftdown = false;
1456 static boolean altdown = false;
1457 unsigned char c;
1458 int i;
1459 int numplayers;
1460
1461 static int num_nobrainers = 0;
1462
1463 numplayers = 0;
1464 for (i=0 ; i<MAXPLAYERS ; i++)
1465 numplayers += playeringame[i];
1466
1467 if (ev->data1 == key_shift)
1468 {
1469 shiftdown = ev->type == ev_keydown;
1470 return false;
1471 }
1472 else if (ev->data1 == key_alt)
1473 {
1474 altdown = ev->type == ev_keydown;
1475 return false;
1476 }
1477 else if (ev->data1 == key_backspace)
1478 {
1479 bsdown = ev->type == ev_keydown;
1480 bscounter = 0;
1481 }
1482
1483 if (ev->type != ev_keydown)
1484 return false;
1485
1486 if (!chat_on)
1487 {
1488 if (ev->data1 == key_enter) // phares
1489 {
1490#ifndef INSTRUMENTED // never turn on message review if INSTRUMENTED defined
1491 if (hud_msg_lines>1) // it posts multi-line messages that will trash
1492 {
1493 if (message_list) HU_Erase(); //jff 4/28/98 erase behind messages
1494 message_list = !message_list; //jff 2/26/98 toggle list of messages
1495 }
1496#endif
1497 if (!message_list) // if not message list, refresh message
1498 {
1499 message_on = true;
1500 message_counter = HU_MSGTIMEOUT;
1501 }
1502 eatkey = true;
1503 }//jff 2/26/98 no chat if message review is displayed
1504 // killough 10/02/98: no chat if demo playback
1505 // no chat in -solo-net mode
1506 else if (!demoplayback && !message_list && netgame && numplayers > 1)
1507 {
1508 if (ev->data1 == key_chat)
1509 {
1510 eatkey = chat_on = true;
1511 HUlib_resetIText(&w_chat);
1512 HU_queueChatChar(HU_BROADCAST);
1513 }
1514 else if (numplayers > 2)
1515 {
1516 for (i=0; i<MAXPLAYERS ; i++)
1517 {
1518 if (ev->data1 == destination_keys[i])
1519 {
1520 if (playeringame[i] && i!=consoleplayer)
1521 {
1522 eatkey = chat_on = true;
1523 HUlib_resetIText(&w_chat);
1524 HU_queueChatChar((char)(i+1));
1525 break;
1526 }
1527 else if (i == consoleplayer)
1528 {
1529 num_nobrainers++;
1530 if (num_nobrainers < 3)
1531 plr->message = HUSTR_TALKTOSELF1;
1532 else if (num_nobrainers < 6)
1533 plr->message = HUSTR_TALKTOSELF2;
1534 else if (num_nobrainers < 9)
1535 plr->message = HUSTR_TALKTOSELF3;
1536 else if (num_nobrainers < 32)
1537 plr->message = HUSTR_TALKTOSELF4;
1538 else
1539 plr->message = HUSTR_TALKTOSELF5;
1540 }
1541 }
1542 }
1543 }
1544 }
1545 }//jff 2/26/98 no chat functions if message review is displayed
1546 else if (!message_list)
1547 {
1548 c = ev->data1;
1549 // send a macro
1550 if (altdown)
1551 {
1552 c = c - '0';
1553 if (c > 9)
1554 return false;
1555 macromessage = chat_macros[c];
1556
1557 // kill last message with a '\n'
1558 HU_queueChatChar((char)key_enter); // DEBUG!!! // phares
1559
1560 // send the macro message
1561 while (*macromessage)
1562 HU_queueChatChar(*macromessage++);
1563 HU_queueChatChar((char)key_enter); // phares
1564
1565 // leave chat mode and notify that it was sent
1566 chat_on = false;
1567 strcpy(lastmessage, chat_macros[c]);
1568 plr->message = lastmessage;
1569 eatkey = true;
1570 }
1571 else
1572 {
1573 if (shiftdown || (c >= 'a' && c <= 'z'))
1574 c = shiftxform[c];
1575 eatkey = HUlib_keyInIText(&w_chat, c);
1576 if (eatkey)
1577 HU_queueChatChar(c);
1578
1579 if (c == key_enter) // phares
1580 {
1581 chat_on = false;
1582 if (w_chat.l.len)
1583 {
1584 strcpy(lastmessage, w_chat.l.l);
1585 plr->message = lastmessage;
1586 }
1587 }
1588 else if (c == key_escape) // phares
1589 chat_on = false;
1590 }
1591 }
1592 return eatkey;
1593}