aced667f48
The new vuprintf makes unnecessary workarounds due to formatting limitations. I checked grep output for whatever appeared to fit but it's possible I missed some instances because they weren't so obvious. Also, this means sound settings can dynamically work with any number of decimals rather than the current assumption of one or two. Add an ipow() function to help and take advantage of dynamic field width and precision. Consolidate string formatting of sound settings. Change-Id: I46caf534859dfd1916cd440cd25e5206b192fcd8
1590 lines
49 KiB
C
1590 lines
49 KiB
C
/* 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_CHATMACRO1,
|
|
HUSTR_CHATMACRO1,
|
|
HUSTR_CHATMACRO1,
|
|
HUSTR_CHATMACRO1,
|
|
HUSTR_CHATMACRO1,
|
|
HUSTR_CHATMACRO1,
|
|
HUSTR_CHATMACRO1,
|
|
HUSTR_CHATMACRO1,
|
|
HUSTR_CHATMACRO1,
|
|
HUSTR_CHATMACRO1
|
|
};
|
|
|
|
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;
|
|
patchnum_t *hu_fontk;//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;
|
|
static char *hud_coordstry;
|
|
static char *hud_coordstrz;
|
|
static char *hud_ammostr;
|
|
static char *hud_healthstr;
|
|
static char *hud_armorstr;
|
|
static char *hud_weapstr;
|
|
static char *hud_keysstr;
|
|
static char *hud_gkeysstr; //jff 3/7/98 add support for graphic key display
|
|
static char *hud_monsecstr;
|
|
|
|
//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;
|
|
|
|
// 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;
|
|
|
|
// malloc all the strings, trying to get size down
|
|
hud_ammostr=malloc(80*sizeof(char));
|
|
hud_healthstr=malloc(80*sizeof(char));
|
|
hud_armorstr=malloc(80*sizeof(char));
|
|
hud_weapstr=malloc(80*sizeof(char));
|
|
hud_keysstr=malloc(80*sizeof(char));
|
|
hud_gkeysstr=malloc(80*sizeof(char));
|
|
hud_monsecstr=malloc(80*sizeof(char));
|
|
hud_coordstrx=malloc(32*sizeof(char));
|
|
hud_coordstry=malloc(32*sizeof(char));
|
|
hud_coordstrz=malloc(32*sizeof(char));
|
|
hu_fontk=malloc(HU_FONTSIZE*sizeof(patchnum_t));
|
|
hu_font2=malloc(HU_FONTSIZE*sizeof(patchnum_t));
|
|
|
|
// 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%.3d", j);
|
|
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%.3d", j);
|
|
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%.3d", j);
|
|
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%.3d", j);
|
|
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,32*sizeof(char),"X: %d",0); //jff 2/22/98 added z
|
|
s = hud_coordstrx;
|
|
while (*s)
|
|
HUlib_addCharToTextLine(&w_coordx, *(s++));
|
|
snprintf(hud_coordstry,32*sizeof(char),"Y: %d",0); //jff 3/3/98 split x,y,z
|
|
s = hud_coordstry;
|
|
while (*s)
|
|
HUlib_addCharToTextLine(&w_coordy, *(s++));
|
|
snprintf(hud_coordstrz,32*sizeof(char),"Z: %d",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,32*sizeof(char),"X: %d", (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,32*sizeof(char),"Y: %d", (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,32*sizeof(char),"Z: %d", (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,80*sizeof(char),
|
|
"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;
|
|
}
|