summaryrefslogtreecommitdiff
path: root/apps/plugins/doom/hu_stuff.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/doom/hu_stuff.c')
-rw-r--r--apps/plugins/doom/hu_stuff.c1753
1 files changed, 1753 insertions, 0 deletions
diff --git a/apps/plugins/doom/hu_stuff.c b/apps/plugins/doom/hu_stuff.c
new file mode 100644
index 0000000..fd7bd0d
--- /dev/null
+++ b/apps/plugins/doom/hu_stuff.c
@@ -0,0 +1,1753 @@
+/* Emacs style mode select -*- C++ -*-
+ *-----------------------------------------------------------------------------
+ *
+ *
+ * PrBoom a Doom port merged with LxDoom and LSDLDoom
+ * based on BOOM, a modified and improved DOOM engine
+ * Copyright (C) 1999 by
+ * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
+ * Copyright (C) 1999-2000 by
+ * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * DESCRIPTION: Heads-up displays
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+// killough 5/3/98: remove unnecessary headers
+
+#include "doomstat.h"
+#include "hu_stuff.h"
+#include "hu_lib.h"
+#include "st_stuff.h" /* jff 2/16/98 need loc of status bar */
+#include "w_wad.h"
+#include "s_sound.h"
+#include "dstrings.h"
+#include "sounds.h"
+//#include "d_deh.h" /* Ty 03/27/98 - externalization of mapnamesx arrays */
+#include "g_game.h"
+#include "m_swap.h"
+
+// global heads up display controls
+
+int hud_active; //jff 2/17/98 controls heads-up display mode
+int hud_displayed; //jff 2/23/98 turns heads-up display on/off
+int hud_nosecrets; //jff 2/18/98 allows secrets line to be disabled in HUD
+int hud_distributed; //jff 3/4/98 display HUD in different places on screen
+int hud_graph_keys=1; //jff 3/7/98 display HUD keys as graphics
+
+//
+// Locally used constants, shortcuts.
+//
+// Ty 03/28/98 -
+// These four shortcuts modifed to reflect char ** of mapnamesx[]
+#define HU_TITLE (mapnames[(gameepisode-1)*9+gamemap-1])
+#define HU_TITLE2 (mapnames2[gamemap-1])
+#define HU_TITLEP (mapnamesp[gamemap-1])
+#define HU_TITLET (mapnamest[gamemap-1])
+#define HU_TITLEHEIGHT 1
+#define HU_TITLEX 0
+//jff 2/16/98 change 167 to ST_Y-1
+// CPhipps - changed to ST_TY
+// proff - changed to 200-ST_HEIGHT for stretching
+#define HU_TITLEY ((200-ST_HEIGHT) - 1 - SHORT(hu_font[0].height))
+
+//jff 2/16/98 add coord text widget coordinates
+// proff - changed to SCREENWIDTH to 320 for stretching
+#define HU_COORDX (320 - 13*SHORT(hu_font2['A'-HU_FONTSTART].width))
+//jff 3/3/98 split coord widget into three lines in upper right of screen
+#define HU_COORDX_Y (1 + 0*SHORT(hu_font['A'-HU_FONTSTART].height))
+#define HU_COORDY_Y (2 + 1*SHORT(hu_font['A'-HU_FONTSTART].height))
+#define HU_COORDZ_Y (3 + 2*SHORT(hu_font['A'-HU_FONTSTART].height))
+
+//jff 2/16/98 add ammo, health, armor widgets, 2/22/98 less gap
+#define HU_GAPY 8
+#define HU_HUDHEIGHT (6*HU_GAPY)
+#define HU_HUDX 2
+#define HU_HUDY (200-HU_HUDHEIGHT-1)
+#define HU_MONSECX (HU_HUDX)
+#define HU_MONSECY (HU_HUDY+0*HU_GAPY)
+#define HU_KEYSX (HU_HUDX)
+//jff 3/7/98 add offset for graphic key widget
+#define HU_KEYSGX (HU_HUDX+4*SHORT(hu_font2['A'-HU_FONTSTART].width))
+#define HU_KEYSY (HU_HUDY+1*HU_GAPY)
+#define HU_WEAPX (HU_HUDX)
+#define HU_WEAPY (HU_HUDY+2*HU_GAPY)
+#define HU_AMMOX (HU_HUDX)
+#define HU_AMMOY (HU_HUDY+3*HU_GAPY)
+#define HU_HEALTHX (HU_HUDX)
+#define HU_HEALTHY (HU_HUDY+4*HU_GAPY)
+#define HU_ARMORX (HU_HUDX)
+#define HU_ARMORY (HU_HUDY+5*HU_GAPY)
+
+//jff 3/4/98 distributed HUD positions
+#define HU_HUDX_LL 2
+#define HU_HUDY_LL (200-2*HU_GAPY-1)
+// proff/nicolas 09/20/98: Changed for high-res
+#define HU_HUDX_LR (320-120)
+#define HU_HUDY_LR (200-2*HU_GAPY-1)
+// proff/nicolas 09/20/98: Changed for high-res
+#define HU_HUDX_UR (320-96)
+#define HU_HUDY_UR 2
+#define HU_MONSECX_D (HU_HUDX_LL)
+#define HU_MONSECY_D (HU_HUDY_LL+0*HU_GAPY)
+#define HU_KEYSX_D (HU_HUDX_LL)
+#define HU_KEYSGX_D (HU_HUDX_LL+4*SHORT(hu_font2['A'-HU_FONTSTART].width))
+#define HU_KEYSY_D (HU_HUDY_LL+1*HU_GAPY)
+#define HU_WEAPX_D (HU_HUDX_LR)
+#define HU_WEAPY_D (HU_HUDY_LR+0*HU_GAPY)
+#define HU_AMMOX_D (HU_HUDX_LR)
+#define HU_AMMOY_D (HU_HUDY_LR+1*HU_GAPY)
+#define HU_HEALTHX_D (HU_HUDX_UR)
+#define HU_HEALTHY_D (HU_HUDY_UR+0*HU_GAPY)
+#define HU_ARMORX_D (HU_HUDX_UR)
+#define HU_ARMORY_D (HU_HUDY_UR+1*HU_GAPY)
+
+//#define HU_INPUTTOGGLE 't' // not used // phares
+#define HU_INPUTX HU_MSGX
+#define HU_INPUTY (HU_MSGY + HU_MSGHEIGHT*(SHORT(hu_font[0].height) +1))
+#define HU_INPUTWIDTH 64
+#define HU_INPUTHEIGHT 1
+
+#define key_alt KEY_RALT
+#define key_shift KEY_RSHIFT
+
+const char* chat_macros[] =
+ // Ty 03/27/98 - *not* externalized
+ // CPhipps - const char*
+ {
+ HUSTR_CHATMACRO0,
+ HUSTR_CHATMACRO1,
+ HUSTR_CHATMACRO2,
+ HUSTR_CHATMACRO3,
+ HUSTR_CHATMACRO4,
+ HUSTR_CHATMACRO5,
+ HUSTR_CHATMACRO6,
+ HUSTR_CHATMACRO7,
+ HUSTR_CHATMACRO8,
+ HUSTR_CHATMACRO9
+ };
+
+const char* player_names[] =
+ // Ty 03/27/98 - *not* externalized
+ // CPhipps - const char*
+ {
+ HUSTR_PLRGREEN,
+ HUSTR_PLRINDIGO,
+ HUSTR_PLRBROWN,
+ HUSTR_PLRRED
+ };
+
+//jff 3/17/98 translate player colmap to text color ranges
+int plyrcoltran[MAXPLAYERS]={CR_GREEN,CR_GRAY,CR_BROWN,CR_RED};
+
+char chat_char; // remove later.
+static player_t* plr;
+
+// font sets
+patchnum_t hu_font[HU_FONTSIZE];
+patchnum_t hu_font2[HU_FONTSIZE];
+patchnum_t hu_fontk[HU_FONTSIZE];//jff 3/7/98 added for graphic key indicators
+patchnum_t hu_msgbg[9]; //jff 2/26/98 add patches for message background
+
+// widgets
+static hu_textline_t w_title;
+static hu_stext_t w_message;
+static hu_itext_t w_chat;
+static hu_itext_t w_inputbuffer[MAXPLAYERS];
+static hu_textline_t w_coordx; //jff 2/16/98 new coord widget for automap
+static hu_textline_t w_coordy; //jff 3/3/98 split coord widgets automap
+static hu_textline_t w_coordz; //jff 3/3/98 split coord widgets automap
+static hu_textline_t w_ammo; //jff 2/16/98 new ammo widget for hud
+static hu_textline_t w_health; //jff 2/16/98 new health widget for hud
+static hu_textline_t w_armor; //jff 2/16/98 new armor widget for hud
+static hu_textline_t w_weapon; //jff 2/16/98 new weapon widget for hud
+static hu_textline_t w_keys; //jff 2/16/98 new keys widget for hud
+static hu_textline_t w_gkeys; //jff 3/7/98 graphic keys widget for hud
+static hu_textline_t w_monsec; //jff 2/16/98 new kill/secret widget for hud
+static hu_mtext_t w_rtext; //jff 2/26/98 text message refresh widget
+
+static boolean always_off = false;
+static char chat_dest[MAXPLAYERS];
+boolean chat_on;
+static boolean message_on;
+static boolean message_list; //2/26/98 enable showing list of messages
+boolean message_dontfuckwithme;
+static boolean message_nottobefuckedwith;
+static int message_counter;
+extern int showMessages;
+extern boolean automapactive;
+static boolean headsupactive = false;
+
+//jff 2/16/98 hud supported automap colors added
+int hudcolor_titl; // color range of automap level title
+int hudcolor_xyco; // color range of new coords on automap
+//jff 2/16/98 hud text colors, controls added
+int hudcolor_mesg; // color range of scrolling messages
+int hudcolor_chat; // color range of chat lines
+int hud_msg_lines; // number of message lines in window
+//jff 2/26/98 hud text colors, controls added
+int hudcolor_list; // list of messages color
+int hud_list_bgon; // enable for solid window background for message list
+
+//jff 2/16/98 initialization strings for ammo, health, armor widgets
+static char hud_coordstrx[32];
+static char hud_coordstry[32];
+static char hud_coordstrz[32];
+static char hud_ammostr[80];
+static char hud_healthstr[80];
+static char hud_armorstr[80];
+static char hud_weapstr[80];
+static char hud_keysstr[80];
+static char hud_gkeysstr[80]; //jff 3/7/98 add support for graphic key display
+static char hud_monsecstr[80];
+
+//jff 2/16/98 declaration of color switch points
+extern int ammo_red;
+extern int ammo_yellow;
+extern int health_red;
+extern int health_yellow;
+extern int health_green;
+extern int armor_red;
+extern int armor_yellow;
+extern int armor_green;
+
+//
+// Builtin map names.
+// The actual names can be found in DStrings.h.
+//
+// Ty 03/27/98 - externalized map name arrays - now in d_deh.c
+// and converted to arrays of pointers to char *
+// See modified HUTITLEx macros
+char* mapnames[] = // DOOM shareware/registered/retail (Ultimate) names.
+ {
+
+ HUSTR_E1M1,
+ HUSTR_E1M2,
+ HUSTR_E1M3,
+ HUSTR_E1M4,
+ HUSTR_E1M5,
+ HUSTR_E1M6,
+ HUSTR_E1M7,
+ HUSTR_E1M8,
+ HUSTR_E1M9,
+
+ HUSTR_E2M1,
+ HUSTR_E2M2,
+ HUSTR_E2M3,
+ HUSTR_E2M4,
+ HUSTR_E2M5,
+ HUSTR_E2M6,
+ HUSTR_E2M7,
+ HUSTR_E2M8,
+ HUSTR_E2M9,
+
+ HUSTR_E3M1,
+ HUSTR_E3M2,
+ HUSTR_E3M3,
+ HUSTR_E3M4,
+ HUSTR_E3M5,
+ HUSTR_E3M6,
+ HUSTR_E3M7,
+ HUSTR_E3M8,
+ HUSTR_E3M9,
+
+ HUSTR_E4M1,
+ HUSTR_E4M2,
+ HUSTR_E4M3,
+ HUSTR_E4M4,
+ HUSTR_E4M5,
+ HUSTR_E4M6,
+ HUSTR_E4M7,
+ HUSTR_E4M8,
+ HUSTR_E4M9,
+
+ "NEWLEVEL",
+ "NEWLEVEL",
+ "NEWLEVEL",
+ "NEWLEVEL",
+ "NEWLEVEL",
+ "NEWLEVEL",
+ "NEWLEVEL",
+ "NEWLEVEL",
+ "NEWLEVEL"
+ };
+
+char* mapnames2[] = // DOOM 2 map names.
+ {
+ HUSTR_1,
+ HUSTR_2,
+ HUSTR_3,
+ HUSTR_4,
+ HUSTR_5,
+ HUSTR_6,
+ HUSTR_7,
+ HUSTR_8,
+ HUSTR_9,
+ HUSTR_10,
+ HUSTR_11,
+
+ HUSTR_12,
+ HUSTR_13,
+ HUSTR_14,
+ HUSTR_15,
+ HUSTR_16,
+ HUSTR_17,
+ HUSTR_18,
+ HUSTR_19,
+ HUSTR_20,
+
+ HUSTR_21,
+ HUSTR_22,
+ HUSTR_23,
+ HUSTR_24,
+ HUSTR_25,
+ HUSTR_26,
+ HUSTR_27,
+ HUSTR_28,
+ HUSTR_29,
+ HUSTR_30,
+ HUSTR_31,
+ HUSTR_32
+ };
+
+
+char* mapnamesp[] = // Plutonia WAD map names.
+ {
+ PHUSTR_1,
+ PHUSTR_2,
+ PHUSTR_3,
+ PHUSTR_4,
+ PHUSTR_5,
+ PHUSTR_6,
+ PHUSTR_7,
+ PHUSTR_8,
+ PHUSTR_9,
+ PHUSTR_10,
+ PHUSTR_11,
+
+ PHUSTR_12,
+ PHUSTR_13,
+ PHUSTR_14,
+ PHUSTR_15,
+ PHUSTR_16,
+ PHUSTR_17,
+ PHUSTR_18,
+ PHUSTR_19,
+ PHUSTR_20,
+
+ PHUSTR_21,
+ PHUSTR_22,
+ PHUSTR_23,
+ PHUSTR_24,
+ PHUSTR_25,
+ PHUSTR_26,
+ PHUSTR_27,
+ PHUSTR_28,
+ PHUSTR_29,
+ PHUSTR_30,
+ PHUSTR_31,
+ PHUSTR_32
+ };
+
+
+char *mapnamest[] = // TNT WAD map names.
+ {
+ THUSTR_1,
+ THUSTR_2,
+ THUSTR_3,
+ THUSTR_4,
+ THUSTR_5,
+ THUSTR_6,
+ THUSTR_7,
+ THUSTR_8,
+ THUSTR_9,
+ THUSTR_10,
+ THUSTR_11,
+
+ THUSTR_12,
+ THUSTR_13,
+ THUSTR_14,
+ THUSTR_15,
+ THUSTR_16,
+ THUSTR_17,
+ THUSTR_18,
+ THUSTR_19,
+ THUSTR_20,
+
+ THUSTR_21,
+ THUSTR_22,
+ THUSTR_23,
+ THUSTR_24,
+ THUSTR_25,
+ THUSTR_26,
+ THUSTR_27,
+ THUSTR_28,
+ THUSTR_29,
+ THUSTR_30,
+ THUSTR_31,
+ THUSTR_32
+ };
+
+// key tables
+// jff 5/10/98 french support removed,
+// as it was not being used and couldn't be easily tested
+//
+const char* shiftxform;
+
+const char english_shiftxform[] =
+ {
+ 0,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31,
+ ' ', '!', '"', '#', '$', '%', '&',
+ '"', // shift-'
+ '(', ')', '*', '+',
+ '<', // shift-,
+ '_', // shift--
+ '>', // shift-.
+ '?', // shift-/
+ ')', // shift-0
+ '!', // shift-1
+ '@', // shift-2
+ '#', // shift-3
+ '$', // shift-4
+ '%', // shift-5
+ '^', // shift-6
+ '&', // shift-7
+ '*', // shift-8
+ '(', // shift-9
+ ':',
+ ':', // shift-;
+ '<',
+ '+', // shift-=
+ '>', '?', '@',
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
+ 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ '[', // shift-[
+ '!', // shift-backslash - OH MY GOD DOES WATCOM SUCK
+ ']', // shift-]
+ '"', '_',
+ '\'', // shift-`
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
+ 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ '{', '|', '}', '~', 127
+ };
+
+//
+// HU_Init()
+//
+// Initialize the heads-up display, text that overwrites the primary display
+//
+// Passed nothing, returns nothing
+//
+void HU_Init(void)
+{
+ int i;
+ int j;
+ char buffer[9];
+
+ shiftxform = english_shiftxform;
+
+ // load the heads-up font
+ j = HU_FONTSTART;
+ for (i=0;i<HU_FONTSIZE;i++,j++)
+ {
+ if ('0'<=j && j<='9')
+ {
+ snprintf(buffer, sizeof(buffer), "DIG%d",j-48);
+ R_SetPatchNum(&hu_font2[i], buffer);
+ snprintf(buffer, sizeof(buffer), "STCFN%s%d", (j/10>0?"0":"00"), j); //NOTE ROCKHACK: "STCFN%.3d"
+ R_SetPatchNum(&hu_font[i], buffer);
+ }
+ else if ('A'<=j && j<='Z')
+ {
+ snprintf(buffer, sizeof(buffer), "DIG%c",j);
+ R_SetPatchNum(&hu_font2[i], buffer);
+ snprintf(buffer, sizeof(buffer), "STCFN%s%d", (j/10>0?"0":"00"), j); //NOTE ROCKHACK: "STCFN%.3d"
+ R_SetPatchNum(&hu_font[i], buffer);
+ }
+ else if (j=='-')
+ {
+ R_SetPatchNum(&hu_font2[i], "DIG45");
+ R_SetPatchNum(&hu_font[i], "STCFN045");
+ }
+ else if (j=='/')
+ {
+ R_SetPatchNum(&hu_font2[i], "DIG47");
+ R_SetPatchNum(&hu_font[i], "STCFN047");
+ }
+ else if (j==':')
+ {
+ R_SetPatchNum(&hu_font2[i], "DIG58");
+ R_SetPatchNum(&hu_font[i], "STCFN058");
+ }
+ else if (j=='[')
+ {
+ R_SetPatchNum(&hu_font2[i], "DIG91");
+ R_SetPatchNum(&hu_font[i], "STCFN091");
+ }
+ else if (j==']')
+ {
+ R_SetPatchNum(&hu_font2[i], "DIG93");
+ R_SetPatchNum(&hu_font[i], "STCFN093");
+ }
+ else if (j<97)
+ {
+ snprintf(buffer, sizeof(buffer), "STCFN%s%d", (j/10>0?"0":"00"), j); //NOTE ROCKHACK: "STCFN%.3d"
+ R_SetPatchNum(&hu_font2[i], buffer);
+ R_SetPatchNum(&hu_font[i], buffer);
+ //jff 2/23/98 make all font chars defined, useful or not
+ }
+ else if (j>122)
+ {
+ snprintf(buffer, sizeof(buffer), "STBR%d", j); //NOTE: "STBR%.3d"
+ R_SetPatchNum(&hu_font2[i], buffer);
+ R_SetPatchNum(&hu_font[i], buffer);
+ }
+ else
+ hu_font[i] = hu_font[0]; //jff 2/16/98 account for gap
+ }
+
+ // CPhipps - load patches for message background
+ for (i=0; i<9; i++) {
+ snprintf(buffer, sizeof(buffer), "BOX%c%c", "UCL"[i/3], "LCR"[i%3]);
+ R_SetPatchNum(&hu_msgbg[i], buffer);
+ }
+
+ // CPhipps - load patches for keys and double keys
+ for (i=0; i<6; i++) {
+ snprintf(buffer, sizeof(buffer), "STKEYS%d", i);
+ R_SetPatchNum(&hu_fontk[i], buffer);
+ }
+}
+
+//
+// HU_Stop()
+//
+// Make the heads-up displays inactive
+//
+// Passed nothing, returns nothing
+//
+void HU_Stop(void)
+{
+ headsupactive = false;
+}
+
+//
+// HU_Start(void)
+//
+// Create and initialize the heads-up widgets, software machines to
+// maintain, update, and display information over the primary display
+//
+// This routine must be called after any change to the heads up configuration
+// in order for the changes to take effect in the actual displays
+//
+// Passed nothing, returns nothing
+//
+void HU_Start(void)
+{
+
+ int i;
+ const char* s; /* cph - const */
+
+ if (headsupactive) // stop before starting
+ HU_Stop();
+
+ plr = &players[displayplayer]; // killough 3/7/98
+ message_on = false;
+ message_dontfuckwithme = false;
+ message_nottobefuckedwith = false;
+ chat_on = false;
+
+ // create the message widget
+ // messages to player in upper-left of screen
+ HUlib_initSText
+ (
+ &w_message,
+ HU_MSGX,
+ HU_MSGY,
+ HU_MSGHEIGHT,
+ hu_font,
+ HU_FONTSTART,
+ hudcolor_mesg,
+ &message_on
+ );
+
+ //jff 2/16/98 added some HUD widgets
+ // create the map title widget - map title display in lower left of automap
+ HUlib_initTextLine
+ (
+ &w_title,
+ HU_TITLEX,
+ HU_TITLEY,
+ hu_font,
+ HU_FONTSTART,
+ hudcolor_titl
+ );
+
+ // create the hud health widget
+ // bargraph and number for amount of health,
+ // lower left or upper right of screen
+ HUlib_initTextLine
+ (
+ &w_health,
+ hud_distributed? HU_HEALTHX_D : HU_HEALTHX, //3/4/98 distribute
+ hud_distributed? HU_HEALTHY_D : HU_HEALTHY,
+ hu_font2,
+ HU_FONTSTART,
+ CR_GREEN
+ );
+
+ // create the hud armor widget
+ // bargraph and number for amount of armor,
+ // lower left or upper right of screen
+ HUlib_initTextLine
+ (
+ &w_armor,
+ hud_distributed? HU_ARMORX_D : HU_ARMORX, //3/4/98 distribute
+ hud_distributed? HU_ARMORY_D : HU_ARMORY,
+ hu_font2,
+ HU_FONTSTART,
+ CR_GREEN
+ );
+
+ // create the hud ammo widget
+ // bargraph and number for amount of ammo for current weapon,
+ // lower left or lower right of screen
+ HUlib_initTextLine
+ (
+ &w_ammo,
+ hud_distributed? HU_AMMOX_D : HU_AMMOX, //3/4/98 distribute
+ hud_distributed? HU_AMMOY_D : HU_AMMOY,
+ hu_font2,
+ HU_FONTSTART,
+ CR_GOLD
+ );
+
+ // create the hud weapons widget
+ // list of numbers of weapons possessed
+ // lower left or lower right of screen
+ HUlib_initTextLine
+ (
+ &w_weapon,
+ hud_distributed? HU_WEAPX_D : HU_WEAPX, //3/4/98 distribute
+ hud_distributed? HU_WEAPY_D : HU_WEAPY,
+ hu_font2,
+ HU_FONTSTART,
+ CR_GRAY
+ );
+
+ // create the hud keys widget
+ // display of key letters possessed
+ // lower left of screen
+ HUlib_initTextLine
+ (
+ &w_keys,
+ hud_distributed? HU_KEYSX_D : HU_KEYSX, //3/4/98 distribute
+ hud_distributed? HU_KEYSY_D : HU_KEYSY,
+ hu_font2,
+ HU_FONTSTART,
+ CR_GRAY
+ );
+
+ // create the hud graphic keys widget
+ // display of key graphics possessed
+ // lower left of screen
+ HUlib_initTextLine
+ (
+ &w_gkeys,
+ hud_distributed? HU_KEYSGX_D : HU_KEYSGX, //3/4/98 distribute
+ hud_distributed? HU_KEYSY_D : HU_KEYSY,
+ hu_fontk,
+ HU_FONTSTART,
+ CR_RED
+ );
+
+ // create the hud monster/secret widget
+ // totals and current values for kills, items, secrets
+ // lower left of screen
+ HUlib_initTextLine
+ (
+ &w_monsec,
+ hud_distributed? HU_MONSECX_D : HU_MONSECX, //3/4/98 distribute
+ hud_distributed? HU_MONSECY_D : HU_MONSECY,
+ hu_font2,
+ HU_FONTSTART,
+ CR_GRAY
+ );
+
+ // create the hud text refresh widget
+ // scrolling display of last hud_msg_lines messages received
+ if (hud_msg_lines>HU_MAXMESSAGES)
+ hud_msg_lines=HU_MAXMESSAGES;
+ //jff 4/21/98 if setup has disabled message list while active, turn it off
+ message_list = hud_msg_lines > 1; //jff 8/8/98 initialize both ways
+ //jff 2/26/98 add the text refresh widget initialization
+ HUlib_initMText
+ (
+ &w_rtext,
+ 0,
+ 0,
+ 320,
+ // SCREENWIDTH,
+ (hud_msg_lines+2)*HU_REFRESHSPACING,
+ hu_font,
+ HU_FONTSTART,
+ hudcolor_list,
+ hu_msgbg,
+ &message_list
+ );
+
+ // initialize the automap's level title widget
+ if (gamestate == GS_LEVEL) /* cph - stop SEGV here when not in level */
+ switch (gamemode)
+ {
+ case shareware:
+ case registered:
+ case retail:
+ s = HU_TITLE;
+ break;
+
+ case commercial:
+ default: // Ty 08/27/98 - modified to check mission for TNT/Plutonia
+ s = (gamemission==pack_tnt) ? HU_TITLET :
+ (gamemission==pack_plut) ? HU_TITLEP : HU_TITLE2;
+ break;
+ } else s = "";
+ while (*s)
+ HUlib_addCharToTextLine(&w_title, *(s++));
+
+ // create the automaps coordinate widget
+ // jff 3/3/98 split coord widget into three lines: x,y,z
+ // jff 2/16/98 added
+ HUlib_initTextLine
+ (
+ &w_coordx,
+ HU_COORDX,
+ HU_COORDX_Y,
+ hu_font,
+ HU_FONTSTART,
+ hudcolor_xyco
+ );
+ HUlib_initTextLine
+ (
+ &w_coordy,
+ HU_COORDX,
+ HU_COORDY_Y,
+ hu_font,
+ HU_FONTSTART,
+ hudcolor_xyco
+ );
+ HUlib_initTextLine
+ (
+ &w_coordz,
+ HU_COORDX,
+ HU_COORDZ_Y,
+ hu_font,
+ HU_FONTSTART,
+ hudcolor_xyco
+ );
+
+ // initialize the automaps coordinate widget
+ //jff 3/3/98 split coordstr widget into 3 parts
+ snprintf(hud_coordstrx,sizeof(hud_coordstrx),"X: %-5d",0); //jff 2/22/98 added z
+ s = hud_coordstrx;
+ while (*s)
+ HUlib_addCharToTextLine(&w_coordx, *(s++));
+ snprintf(hud_coordstry,sizeof(hud_coordstry),"Y: %-5d",0); //jff 3/3/98 split x,y,z
+ s = hud_coordstry;
+ while (*s)
+ HUlib_addCharToTextLine(&w_coordy, *(s++));
+ snprintf(hud_coordstrz,sizeof(hud_coordstrz),"Z: %-5d",0); //jff 3/3/98 split x,y,z
+ s = hud_coordstrz;
+ while (*s)
+ HUlib_addCharToTextLine(&w_coordz, *(s++));
+
+ //jff 2/16/98 initialize ammo widget
+ strcpy(hud_ammostr,"AMM ");
+ s = hud_ammostr;
+ while (*s)
+ HUlib_addCharToTextLine(&w_ammo, *(s++));
+
+ //jff 2/16/98 initialize health widget
+ strcpy(hud_healthstr,"HEL ");
+ s = hud_healthstr;
+ while (*s)
+ HUlib_addCharToTextLine(&w_health, *(s++));
+
+ //jff 2/16/98 initialize armor widget
+ strcpy(hud_armorstr,"ARM ");
+ s = hud_armorstr;
+ while (*s)
+ HUlib_addCharToTextLine(&w_armor, *(s++));
+
+ //jff 2/17/98 initialize weapons widget
+ strcpy(hud_weapstr,"WEA ");
+ s = hud_weapstr;
+ while (*s)
+ HUlib_addCharToTextLine(&w_weapon, *(s++));
+
+ //jff 2/17/98 initialize keys widget
+ if (!deathmatch) //jff 3/17/98 show frags in deathmatch mode
+ strcpy(hud_keysstr,"KEY ");
+ else
+ strcpy(hud_keysstr,"FRG ");
+ s = hud_keysstr;
+ while (*s)
+ HUlib_addCharToTextLine(&w_keys, *(s++));
+
+ //jff 2/17/98 initialize graphic keys widget
+ strcpy(hud_gkeysstr," ");
+ s = hud_gkeysstr;
+ while (*s)
+ HUlib_addCharToTextLine(&w_gkeys, *(s++));
+
+ //jff 2/17/98 initialize kills/items/secret widget
+ strcpy(hud_monsecstr,"STS ");
+ s = hud_monsecstr;
+ while (*s)
+ HUlib_addCharToTextLine(&w_monsec, *(s++));
+
+ // create the chat widget
+ HUlib_initIText
+ (
+ &w_chat,
+ HU_INPUTX,
+ HU_INPUTY,
+ hu_font,
+ HU_FONTSTART,
+ hudcolor_chat,
+ &chat_on
+ );
+
+ // create the inputbuffer widgets, one per player
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ HUlib_initIText
+ (
+ &w_inputbuffer[i],
+ 0,
+ 0,
+ 0,
+ 0,
+ hudcolor_chat,
+ &always_off
+ );
+
+ // now allow the heads-up display to run
+ headsupactive = true;
+}
+
+//
+// HU_MoveHud()
+//
+// Move the HUD display from distributed to compact mode or vice-versa
+//
+// Passed nothing, returns nothing
+//
+//jff 3/9/98 create this externally callable to avoid glitch
+// when menu scatter's HUD due to delay in change of position
+//
+void HU_MoveHud(void)
+{
+ static int ohud_distributed=-1;
+
+ //jff 3/4/98 move displays around on F5 changing hud_distributed
+ if (hud_distributed!=ohud_distributed)
+ {
+ w_ammo.x = hud_distributed? HU_AMMOX_D : HU_AMMOX;
+ w_ammo.y = hud_distributed? HU_AMMOY_D : HU_AMMOY;
+ w_weapon.x = hud_distributed? HU_WEAPX_D : HU_WEAPX;
+ w_weapon.y = hud_distributed? HU_WEAPY_D : HU_WEAPY;
+ w_keys.x = hud_distributed? HU_KEYSX_D : HU_KEYSX;
+ w_keys.y = hud_distributed? HU_KEYSY_D : HU_KEYSY;
+ w_gkeys.x = hud_distributed? HU_KEYSGX_D : HU_KEYSGX;
+ w_gkeys.y = hud_distributed? HU_KEYSY_D : HU_KEYSY;
+ w_monsec.x = hud_distributed? HU_MONSECX_D : HU_MONSECX;
+ w_monsec.y = hud_distributed? HU_MONSECY_D : HU_MONSECY;
+ w_health.x = hud_distributed? HU_HEALTHX_D : HU_HEALTHX;
+ w_health.y = hud_distributed? HU_HEALTHY_D : HU_HEALTHY;
+ w_armor.x = hud_distributed? HU_ARMORX_D : HU_ARMORX;
+ w_armor.y = hud_distributed? HU_ARMORY_D : HU_ARMORY;
+ }
+ ohud_distributed = hud_distributed;
+}
+
+//
+// HU_Drawer()
+//
+// Draw all the pieces of the heads-up display
+//
+// Passed nothing, returns nothing
+//
+void HU_Drawer(void)
+{
+ char *s;
+ player_t *plr;
+ char ammostr[80]; //jff 3/8/98 allow plenty room for dehacked mods
+ char healthstr[80];//jff
+ char armorstr[80]; //jff
+ int i,doit;
+
+ plr = &players[displayplayer]; // killough 3/7/98
+ // draw the automap widgets if automap is displayed
+ if (automapmode & am_active)
+ {
+ // map title
+ HUlib_drawTextLine(&w_title, false);
+
+ //jff 2/16/98 output new coord display
+ // x-coord
+ snprintf(hud_coordstrx,sizeof(hud_coordstrx),"X: %-5d", (plr->mo->x)>>FRACBITS);
+ HUlib_clearTextLine(&w_coordx);
+ s = hud_coordstrx;
+ while (*s)
+ HUlib_addCharToTextLine(&w_coordx, *(s++));
+ HUlib_drawTextLine(&w_coordx, false);
+
+ //jff 3/3/98 split coord display into x,y,z lines
+ // y-coord
+ snprintf(hud_coordstry,sizeof(hud_coordstry),"Y: %-5d", (plr->mo->y)>>FRACBITS);
+ HUlib_clearTextLine(&w_coordy);
+ s = hud_coordstry;
+ while (*s)
+ HUlib_addCharToTextLine(&w_coordy, *(s++));
+ HUlib_drawTextLine(&w_coordy, false);
+
+ //jff 3/3/98 split coord display into x,y,z lines
+ //jff 2/22/98 added z
+ // z-coord
+ snprintf(hud_coordstrz,sizeof(hud_coordstrz),"Z: %-5d", (plr->mo->z)>>FRACBITS);
+ HUlib_clearTextLine(&w_coordz);
+ s = hud_coordstrz;
+ while (*s)
+ HUlib_addCharToTextLine(&w_coordz, *(s++));
+ HUlib_drawTextLine(&w_coordz, false);
+ }
+
+ // draw the weapon/health/ammo/armor/kills/keys displays if optioned
+ //jff 2/17/98 allow new hud stuff to be turned off
+ // killough 2/21/98: really allow new hud stuff to be turned off COMPLETELY
+ if
+ (
+ hud_active>0 && // hud optioned on
+ hud_displayed && // hud on from fullscreen key
+ viewheight==SCREENHEIGHT && // fullscreen mode is active
+ !(automapmode & am_active) // automap is not active
+ )
+ {
+ doit = !(gametic&1); //jff 3/4/98 speed update up for slow systems
+ if (doit) //jff 8/7/98 update every time, avoid lag in update
+ {
+ HU_MoveHud(); // insure HUD display coords are correct
+
+ // do the hud ammo display
+ // clear the widgets internal line
+ HUlib_clearTextLine(&w_ammo);
+ strcpy(hud_ammostr,"AMM ");
+ if (weaponinfo[plr->readyweapon].ammo == am_noammo)
+ { // special case for weapon with no ammo selected - blank bargraph + N/A
+ strcat(hud_ammostr,"\x7f\x7f\x7f\x7f\x7f\x7f\x7f N/A");
+ w_ammo.cm = CR_GRAY;
+ }
+ else
+ {
+ int ammo = plr->ammo[weaponinfo[plr->readyweapon].ammo];
+ int fullammo = plr->maxammo[weaponinfo[plr->readyweapon].ammo];
+ int ammopct = (100*ammo)/fullammo;
+ int ammobars = ammopct/4;
+
+ // build the numeric amount init string
+ snprintf(ammostr,sizeof(ammostr),"%d/%d",ammo,fullammo);
+ // build the bargraph string
+ // full bargraph chars
+ for (i=4;i<4+ammobars/4;)
+ hud_ammostr[i++] = 123;
+ // plus one last character with 0,1,2,3 bars
+ switch(ammobars%4)
+ {
+ case 0:
+ break;
+ case 1:
+ hud_ammostr[i++] = 126;
+ break;
+ case 2:
+ hud_ammostr[i++] = 125;
+ break;
+ case 3:
+ hud_ammostr[i++] = 124;
+ break;
+ }
+ // pad string with blank bar characters
+ while(i<4+7)
+ hud_ammostr[i++] = 127;
+ hud_ammostr[i] = '\0';
+ strcat(hud_ammostr,ammostr);
+
+ // set the display color from the percentage of total ammo held
+ if (ammopct<ammo_red)
+ w_ammo.cm = CR_RED;
+ else if (ammopct<ammo_yellow)
+ w_ammo.cm = CR_GOLD;
+ else
+ w_ammo.cm = CR_GREEN;
+ }
+ // transfer the init string to the widget
+ s = hud_ammostr;
+ while (*s)
+ HUlib_addCharToTextLine(&w_ammo, *(s++));
+ }
+ // display the ammo widget every frame
+ HUlib_drawTextLine(&w_ammo, false);
+
+ // do the hud health display
+ if (doit)
+ {
+ int health = plr->health;
+ int healthbars = health>100? 25 : health/4;
+
+ // clear the widgets internal line
+ HUlib_clearTextLine(&w_health);
+
+ // build the numeric amount init string
+ snprintf(healthstr,sizeof(healthstr),"%3d",health);
+ // build the bargraph string
+ // full bargraph chars
+ for (i=4;i<4+healthbars/4;)
+ hud_healthstr[i++] = 123;
+ // plus one last character with 0,1,2,3 bars
+ switch(healthbars%4)
+ {
+ case 0:
+ break;
+ case 1:
+ hud_healthstr[i++] = 126;
+ break;
+ case 2:
+ hud_healthstr[i++] = 125;
+ break;
+ case 3:
+ hud_healthstr[i++] = 124;
+ break;
+ }
+ // pad string with blank bar characters
+ while(i<4+7)
+ hud_healthstr[i++] = 127;
+ hud_healthstr[i] = '\0';
+ strcat(hud_healthstr,healthstr);
+
+ // set the display color from the amount of health posessed
+ if (health<health_red)
+ w_health.cm = CR_RED;
+ else if (health<health_yellow)
+ w_health.cm = CR_GOLD;
+ else if (health<=health_green)
+ w_health.cm = CR_GREEN;
+ else
+ w_health.cm = CR_BLUE;
+
+ // transfer the init string to the widget
+ s = hud_healthstr;
+ while (*s)
+ HUlib_addCharToTextLine(&w_health, *(s++));
+ }
+ // display the health widget every frame
+ HUlib_drawTextLine(&w_health, false);
+
+ // do the hud armor display
+ if (doit)
+ {
+ int armor = plr->armorpoints;
+ int armorbars = armor>100? 25 : armor/4;
+
+ // clear the widgets internal line
+ HUlib_clearTextLine(&w_armor);
+ // build the numeric amount init string
+ snprintf(armorstr,sizeof(armorstr),"%3d",armor);
+ // build the bargraph string
+ // full bargraph chars
+ for (i=4;i<4+armorbars/4;)
+ hud_armorstr[i++] = 123;
+ // plus one last character with 0,1,2,3 bars
+ switch(armorbars%4)
+ {
+ case 0:
+ break;
+ case 1:
+ hud_armorstr[i++] = 126;
+ break;
+ case 2:
+ hud_armorstr[i++] = 125;
+ break;
+ case 3:
+ hud_armorstr[i++] = 124;
+ break;
+ }
+ // pad string with blank bar characters
+ while(i<4+7)
+ hud_armorstr[i++] = 127;
+ hud_armorstr[i] = '\0';
+ strcat(hud_armorstr,armorstr);
+
+ // set the display color from the amount of armor posessed
+ if (armor<armor_red)
+ w_armor.cm = CR_RED;
+ else if (armor<armor_yellow)
+ w_armor.cm = CR_GOLD;
+ else if (armor<=armor_green)
+ w_armor.cm = CR_GREEN;
+ else
+ w_armor.cm = CR_BLUE;
+
+ // transfer the init string to the widget
+ s = hud_armorstr;
+ while (*s)
+ HUlib_addCharToTextLine(&w_armor, *(s++));
+ }
+ // display the armor widget every frame
+ HUlib_drawTextLine(&w_armor, false);
+
+ // do the hud weapon display
+ if (doit)
+ {
+ int w;
+ int ammo,fullammo,ammopct;
+
+ // clear the widgets internal line
+ HUlib_clearTextLine(&w_weapon);
+ i=4; hud_weapstr[i] = '\0'; //jff 3/7/98 make sure ammo goes away
+
+ // do each weapon that exists in current gamemode
+ for (w=0;w<=wp_supershotgun;w++) //jff 3/4/98 show fists too, why not?
+ {
+ int ok=1;
+ //jff avoid executing for weapons that do not exist
+ switch (gamemode)
+ {
+ case shareware:
+ if (w>=wp_plasma && w!=wp_chainsaw)
+ ok=0;
+ break;
+ case retail:
+ case registered:
+ if (w>=wp_supershotgun)
+ ok=0;
+ break;
+ default:
+ case commercial:
+ break;
+ }
+ if (!ok) continue;
+
+ ammo = plr->ammo[weaponinfo[w].ammo];
+ fullammo = plr->maxammo[weaponinfo[w].ammo];
+ ammopct=0;
+
+ // skip weapons not currently posessed
+ if (!plr->weaponowned[w])
+ continue;
+
+ ammopct = fullammo? (100*ammo)/fullammo : 100;
+
+ // display each weapon number in a color related to the ammo for it
+ hud_weapstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
+ if (weaponinfo[w].ammo==am_noammo) //jff 3/14/98 show berserk on HUD
+ hud_weapstr[i++] = plr->powers[pw_strength]? '0'+CR_GREEN : '0'+CR_GRAY;
+ else if (ammopct<ammo_red)
+ hud_weapstr[i++] = '0'+CR_RED;
+ else if (ammopct<ammo_yellow)
+ hud_weapstr[i++] = '0'+CR_GOLD;
+ else
+ hud_weapstr[i++] = '0'+CR_GREEN;
+ hud_weapstr[i++] = '0'+w+1;
+ hud_weapstr[i++] = ' ';
+ hud_weapstr[i] = '\0';
+ }
+
+ // transfer the init string to the widget
+ s = hud_weapstr;
+ while (*s)
+ HUlib_addCharToTextLine(&w_weapon, *(s++));
+ }
+ // display the weapon widget every frame
+ HUlib_drawTextLine(&w_weapon, false);
+
+ if (doit && hud_active>1)
+ {
+ int k;
+
+ hud_keysstr[4] = '\0'; //jff 3/7/98 make sure deleted keys go away
+ //jff add case for graphic key display
+ if (!deathmatch && hud_graph_keys)
+ {
+ i=0;
+ hud_gkeysstr[i] = '\0'; //jff 3/7/98 init graphic keys widget string
+ // build text string whose characters call out graphic keys from fontk
+ for (k=0;k<6;k++)
+ {
+ // skip keys not possessed
+ if (!plr->cards[k])
+ continue;
+
+ hud_gkeysstr[i++] = '!'+k; // key number plus '!' is char for key
+ hud_gkeysstr[i++] = ' '; // spacing
+ hud_gkeysstr[i++] = ' ';
+ }
+ hud_gkeysstr[i]='\0';
+ }
+ else // not possible in current code, unless deathmatching,
+ {
+ i=4;
+ hud_keysstr[i] = '\0'; //jff 3/7/98 make sure deleted keys go away
+
+ // if deathmatch, build string showing top four frag counts
+ if (deathmatch) //jff 3/17/98 show frags, not keys, in deathmatch
+ {
+ int top1=-999,top2=-999,top3=-999,top4=-999;
+ int idx1=-1,idx2=-1,idx3=-1,idx4=-1;
+ int fragcount,m;
+ char numbuf[32];
+
+ // scan thru players
+ for (k=0;k<MAXPLAYERS;k++)
+ {
+ // skip players not in game
+ if (!playeringame[k])
+ continue;
+
+ fragcount = 0;
+ // compute number of times they've fragged each player
+ // minus number of times they've been fragged by them
+ for (m=0;m<MAXPLAYERS;m++)
+ {
+ if (!playeringame[m]) continue;
+ fragcount += (m!=k)? players[k].frags[m] : -players[k].frags[m];
+ }
+
+ // very primitive sort of frags to find top four
+ if (fragcount>top1)
+ {
+ top4=top3; top3=top2; top2 = top1; top1=fragcount;
+ idx4=idx3; idx3=idx2; idx2 = idx1; idx1=k;
+ }
+ else if (fragcount>top2)
+ {
+ top4=top3; top3=top2; top2=fragcount;
+ idx4=idx3; idx3=idx2; idx2=k;
+ }
+ else if (fragcount>top3)
+ {
+ top4=top3; top3=fragcount;
+ idx4=idx3; idx3=k;
+ }
+ else if (fragcount>top4)
+ {
+ top4=fragcount;
+ idx4=k;
+ }
+ }
+ // if the biggest number exists, put it in the init string
+ if (idx1>-1)
+ {
+ snprintf(numbuf,sizeof(numbuf),"%5d",top1);
+ // make frag count in player's color via escape code
+ hud_keysstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
+ hud_keysstr[i++] = '0'+plyrcoltran[idx1&3];
+ s = numbuf;
+ while (*s)
+ hud_keysstr[i++] = *(s++);
+ }
+ // if the second biggest number exists, put it in the init string
+ if (idx2>-1)
+ {
+ snprintf(numbuf,sizeof(numbuf),"%5d",top2);
+ // make frag count in player's color via escape code
+ hud_keysstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
+ hud_keysstr[i++] = '0'+plyrcoltran[idx2&3];
+ s = numbuf;
+ while (*s)
+ hud_keysstr[i++] = *(s++);
+ }
+ // if the third biggest number exists, put it in the init string
+ if (idx3>-1)
+ {
+ snprintf(numbuf,sizeof(numbuf),"%5d",top3);
+ // make frag count in player's color via escape code
+ hud_keysstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
+ hud_keysstr[i++] = '0'+plyrcoltran[idx3&3];
+ s = numbuf;
+ while (*s)
+ hud_keysstr[i++] = *(s++);
+ }
+ // if the fourth biggest number exists, put it in the init string
+ if (idx4>-1)
+ {
+ snprintf(numbuf,sizeof(numbuf),"%5d",top4);
+ // make frag count in player's color via escape code
+ hud_keysstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
+ hud_keysstr[i++] = '0'+plyrcoltran[idx4&3];
+ s = numbuf;
+ while (*s)
+ hud_keysstr[i++] = *(s++);
+ }
+ hud_keysstr[i] = '\0';
+ } //jff 3/17/98 end of deathmatch clause
+ else // build alphabetical key display (not used currently)
+ {
+ // scan the keys
+ for (k=0;k<6;k++)
+ {
+ // skip any not possessed by the displayed player's stats
+ if (!plr->cards[k])
+ continue;
+
+ // use color escapes to make text in key's color
+ hud_keysstr[i++] = '\x1b'; //jff 3/26/98 use ESC not '\' for paths
+ switch(k)
+ {
+ case 0:
+ hud_keysstr[i++] = '0'+CR_BLUE;
+ hud_keysstr[i++] = 'B';
+ hud_keysstr[i++] = 'C';
+ hud_keysstr[i++] = ' ';
+ break;
+ case 1:
+ hud_keysstr[i++] = '0'+CR_GOLD;
+ hud_keysstr[i++] = 'Y';
+ hud_keysstr[i++] = 'C';
+ hud_keysstr[i++] = ' ';
+ break;
+ case 2:
+ hud_keysstr[i++] = '0'+CR_RED;
+ hud_keysstr[i++] = 'R';
+ hud_keysstr[i++] = 'C';
+ hud_keysstr[i++] = ' ';
+ break;
+ case 3:
+ hud_keysstr[i++] = '0'+CR_BLUE;
+ hud_keysstr[i++] = 'B';
+ hud_keysstr[i++] = 'S';
+ hud_keysstr[i++] = ' ';
+ break;
+ case 4:
+ hud_keysstr[i++] = '0'+CR_GOLD;
+ hud_keysstr[i++] = 'Y';
+ hud_keysstr[i++] = 'S';
+ hud_keysstr[i++] = ' ';
+ break;
+ case 5:
+ hud_keysstr[i++] = '0'+CR_RED;
+ hud_keysstr[i++] = 'R';
+ hud_keysstr[i++] = 'S';
+ hud_keysstr[i++] = ' ';
+ break;
+ }
+ hud_keysstr[i]='\0';
+ }
+ }
+ }
+ }
+ // display the keys/frags line each frame
+ if (hud_active>1)
+ {
+ HUlib_clearTextLine(&w_keys); // clear the widget strings
+ HUlib_clearTextLine(&w_gkeys);
+
+ // transfer the built string (frags or key title) to the widget
+ s = hud_keysstr; //jff 3/7/98 display key titles/key text or frags
+ while (*s)
+ HUlib_addCharToTextLine(&w_keys, *(s++));
+ HUlib_drawTextLine(&w_keys, false);
+
+ //jff 3/17/98 show graphic keys in non-DM only
+ if (!deathmatch) //jff 3/7/98 display graphic keys
+ {
+ // transfer the graphic key text to the widget
+ s = hud_gkeysstr;
+ while (*s)
+ HUlib_addCharToTextLine(&w_gkeys, *(s++));
+ // display the widget
+ HUlib_drawTextLine(&w_gkeys, false);
+ }
+ }
+
+ // display the hud kills/items/secret display if optioned
+ if (!hud_nosecrets)
+ {
+ if (hud_active>1 && doit)
+ {
+ // clear the internal widget text buffer
+ HUlib_clearTextLine(&w_monsec);
+ //jff 3/26/98 use ESC not '\' for paths
+ // build the init string with fixed colors
+ snprintf
+ (
+ hud_monsecstr,sizeof(hud_monsecstr),
+ "STS \x1b\x36K \x1b\x33%d \x1b\x36M \x1b\x33%d \x1b\x37I \x1b\x33%d/%d \x1b\x35S \x1b\x33%d/%d",
+ plr->killcount,totallive,
+ plr->itemcount,totalitems,
+ plr->secretcount,totalsecret
+ );
+ // transfer the init string to the widget
+ s = hud_monsecstr;
+ while (*s)
+ HUlib_addCharToTextLine(&w_monsec, *(s++));
+ }
+ // display the kills/items/secrets each frame, if optioned
+ if (hud_active>1)
+ HUlib_drawTextLine(&w_monsec, false);
+ }
+ }
+
+ //jff 3/4/98 display last to give priority
+ HU_Erase(); // jff 4/24/98 Erase current lines before drawing current
+ // needed when screen not fullsize
+
+ //jff 4/21/98 if setup has disabled message list while active, turn it off
+ if (hud_msg_lines<=1)
+ message_list = false;
+
+ // if the message review not enabled, show the standard message widget
+ if (!message_list)
+ HUlib_drawSText(&w_message);
+
+ // if the message review is enabled show the scrolling message review
+ if (hud_msg_lines>1 && message_list)
+ HUlib_drawMText(&w_rtext);
+
+ // display the interactive buffer for chat entry
+ HUlib_drawIText(&w_chat);
+}
+
+//
+// HU_Erase()
+//
+// Erase hud display lines that can be trashed by small screen display
+//
+// Passed nothing, returns nothing
+//
+void HU_Erase(void)
+{
+ // erase the message display or the message review display
+ if (!message_list)
+ HUlib_eraseSText(&w_message);
+ else
+ HUlib_eraseMText(&w_rtext);
+
+ // erase the interactive text buffer for chat entry
+ HUlib_eraseIText(&w_chat);
+
+ // erase the automap title
+ HUlib_eraseTextLine(&w_title);
+}
+
+//
+// HU_Ticker()
+//
+// Update the hud displays once per frame
+//
+// Passed nothing, returns nothing
+//
+static boolean bsdown; // Is backspace down?
+static int bscounter;
+
+void HU_Ticker(void)
+{
+ int i, rc;
+ char c;
+
+ // tick down message counter if message is up
+ if (message_counter && !--message_counter)
+ {
+ message_on = false;
+ message_nottobefuckedwith = false;
+ }
+ if (bsdown && bscounter++ > 9) {
+ HUlib_keyInIText(&w_chat, (unsigned char)key_backspace);
+ bscounter = 8;
+ }
+
+ // if messages on, or "Messages Off" is being displayed
+ // this allows the notification of turning messages off to be seen
+ if (showMessages || message_dontfuckwithme)
+ {
+ // display message if necessary
+ if ((plr->message && !message_nottobefuckedwith)
+ || (plr->message && message_dontfuckwithme))
+ {
+ //post the message to the message widget
+ HUlib_addMessageToSText(&w_message, 0, plr->message);
+ //jff 2/26/98 add message to refresh text widget too
+ HUlib_addMessageToMText(&w_rtext, 0, plr->message);
+
+ // clear the message to avoid posting multiple times
+ plr->message = 0;
+ // note a message is displayed
+ message_on = true;
+ // start the message persistence counter
+ message_counter = HU_MSGTIMEOUT;
+ // transfer "Messages Off" exception to the "being displayed" variable
+ message_nottobefuckedwith = message_dontfuckwithme;
+ // clear the flag that "Messages Off" is being posted
+ message_dontfuckwithme = 0;
+ }
+ }
+
+ // check for incoming chat characters
+ if (netgame)
+ {
+ for (i=0; i<MAXPLAYERS; i++)
+ {
+ if (!playeringame[i])
+ continue;
+ if (i != consoleplayer
+ && (c = players[i].cmd.chatchar))
+ {
+ if (c <= HU_BROADCAST)
+ chat_dest[i] = c;
+ else
+ {
+ if (c >= 'a' && c <= 'z')
+ c = (char) shiftxform[(unsigned char) c];
+ rc = HUlib_keyInIText(&w_inputbuffer[i], c);
+ if (rc && c == KEY_ENTER)
+ {
+ if (w_inputbuffer[i].l.len
+ && (chat_dest[i] == consoleplayer+1
+ || chat_dest[i] == HU_BROADCAST))
+ {
+ HUlib_addMessageToSText(&w_message,
+ player_names[i],
+ w_inputbuffer[i].l.l);
+
+ message_nottobefuckedwith = true;
+ message_on = true;
+ message_counter = HU_MSGTIMEOUT;
+ if ( gamemode == commercial )
+ S_StartSound(0, sfx_radio);
+ else
+ S_StartSound(0, sfx_tink);
+ }
+ HUlib_resetIText(&w_inputbuffer[i]);
+ }
+ }
+ players[i].cmd.chatchar = 0;
+ }
+ }
+ }
+}
+
+#define QUEUESIZE 128
+
+static char chatchars[QUEUESIZE];
+static int head = 0;
+static int tail = 0;
+
+//
+// HU_queueChatChar()
+//
+// Add an incoming character to the circular chat queue
+//
+// Passed the character to queue, returns nothing
+//
+void HU_queueChatChar(char c)
+{
+ if (((head + 1) & (QUEUESIZE-1)) == tail)
+ {
+ plr->message = HUSTR_MSGU;
+ }
+ else
+ {
+ chatchars[head] = c;
+ head = (head + 1) & (QUEUESIZE-1);
+ }
+}
+
+//
+// HU_dequeueChatChar()
+//
+// Remove the earliest added character from the circular chat queue
+//
+// Passed nothing, returns the character dequeued
+//
+char HU_dequeueChatChar(void)
+{
+ char c;
+
+ if (head != tail)
+ {
+ c = chatchars[tail];
+ tail = (tail + 1) & (QUEUESIZE-1);
+ }
+ else
+ {
+ c = 0;
+ }
+ return c;
+}
+
+//
+// HU_Responder()
+//
+// Responds to input events that affect the heads up displays
+//
+// Passed the event to respond to, returns true if the event was handled
+//
+boolean HU_Responder(event_t *ev)
+{
+
+ static char lastmessage[HU_MAXLINELENGTH+1];
+ const char* macromessage; // CPhipps - const char*
+ boolean eatkey = false;
+ static boolean shiftdown = false;
+ static boolean altdown = false;
+ unsigned char c;
+ int i;
+ int numplayers;
+
+ static int num_nobrainers = 0;
+
+ numplayers = 0;
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ numplayers += playeringame[i];
+
+ if (ev->data1 == key_shift)
+ {
+ shiftdown = ev->type == ev_keydown;
+ return false;
+ }
+ else if (ev->data1 == key_alt)
+ {
+ altdown = ev->type == ev_keydown;
+ return false;
+ }
+ else if (ev->data1 == key_backspace)
+ {
+ bsdown = ev->type == ev_keydown;
+ bscounter = 0;
+ }
+
+ if (ev->type != ev_keydown)
+ return false;
+
+ if (!chat_on)
+ {
+ if (ev->data1 == key_enter) // phares
+ {
+#ifndef INSTRUMENTED // never turn on message review if INSTRUMENTED defined
+ if (hud_msg_lines>1) // it posts multi-line messages that will trash
+ {
+ if (message_list) HU_Erase(); //jff 4/28/98 erase behind messages
+ message_list = !message_list; //jff 2/26/98 toggle list of messages
+ }
+#endif
+ if (!message_list) // if not message list, refresh message
+ {
+ message_on = true;
+ message_counter = HU_MSGTIMEOUT;
+ }
+ eatkey = true;
+ }//jff 2/26/98 no chat if message review is displayed
+ else if (!message_list && netgame && ev->data1 == key_chat)
+ {
+ eatkey = chat_on = true;
+ HUlib_resetIText(&w_chat);
+ HU_queueChatChar(HU_BROADCAST);
+ }//jff 2/26/98 no chat if message review is displayed
+ // killough 10/02/98: no chat if demo playback
+ else if (!demoplayback && !message_list && netgame && numplayers > 2)
+ {
+ for (i=0; i<MAXPLAYERS ; i++)
+ {
+ if (ev->data1 == destination_keys[i])
+ {
+ if (playeringame[i] && i!=consoleplayer)
+ {
+ eatkey = chat_on = true;
+ HUlib_resetIText(&w_chat);
+ HU_queueChatChar((char)(i+1));
+ break;
+ }
+ else if (i == consoleplayer)
+ {
+ num_nobrainers++;
+ if (num_nobrainers < 3)
+ plr->message = HUSTR_TALKTOSELF1;
+ else if (num_nobrainers < 6)
+ plr->message = HUSTR_TALKTOSELF2;
+ else if (num_nobrainers < 9)
+ plr->message = HUSTR_TALKTOSELF3;
+ else if (num_nobrainers < 32)
+ plr->message = HUSTR_TALKTOSELF4;
+ else
+ plr->message = HUSTR_TALKTOSELF5;
+ }
+ }
+ }
+ }
+ }//jff 2/26/98 no chat functions if message review is displayed
+ else if (!message_list)
+ {
+ c = ev->data1;
+ // send a macro
+ if (altdown)
+ {
+ c = c - '0';
+ if (c > 9)
+ return false;
+ macromessage = chat_macros[c];
+
+ // kill last message with a '\n'
+ HU_queueChatChar((char)key_enter); // DEBUG!!! // phares
+
+ // send the macro message
+ while (*macromessage)
+ HU_queueChatChar(*macromessage++);
+ HU_queueChatChar((char)key_enter); // phares
+
+ // leave chat mode and notify that it was sent
+ chat_on = false;
+ strcpy(lastmessage, chat_macros[c]);
+ plr->message = lastmessage;
+ eatkey = true;
+ }
+ else
+ {
+ if (shiftdown || (c >= 'a' && c <= 'z'))
+ c = shiftxform[c];
+ eatkey = HUlib_keyInIText(&w_chat, c);
+ if (eatkey)
+ HU_queueChatChar(c);
+
+ if (c == key_enter) // phares
+ {
+ chat_on = false;
+ if (w_chat.l.len)
+ {
+ strcpy(lastmessage, w_chat.l.l);
+ plr->message = lastmessage;
+ }
+ }
+ else if (c == key_escape) // phares
+ chat_on = false;
+ }
+ }
+ return eatkey;
+}