dvr/app/jni/prboom/hu_stuff.c
2016-03-03 22:28:59 +00:00

1593 lines
45 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
* Copyright 2005, 2006 by
* Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
*
* 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 "r_main.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 - 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*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*hu_font['A'-HU_FONTSTART].height)
#define HU_COORDY_Y (2 + 1*hu_font['A'-HU_FONTSTART].height)
#define HU_COORDZ_Y (3 + 2*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*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*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*(hu_font[0].height) +1)
#define HU_INPUTWIDTH 64
#define HU_INPUTHEIGHT 1
#define key_alt KEYD_RALT
#define key_shift KEYD_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];
//
// 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
extern char **mapnames[];
extern char **mapnames2[];
extern char **mapnamesp[];
extern char **mapnamest[];
extern int map_point_coordinates;
// 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')
{
sprintf(buffer, "DIG%.1d",j-48);
R_SetPatchNum(&hu_font2[i], buffer);
sprintf(buffer, "STCFN%.3d",j);
R_SetPatchNum(&hu_font[i], buffer);
}
else if ('A'<=j && j<='Z')
{
sprintf(buffer, "DIG%c",j);
R_SetPatchNum(&hu_font2[i], buffer);
sprintf(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)
{
sprintf(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)
{
sprintf(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++) {
sprintf(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++) {
sprintf(buffer, "STKEYS%d", i);
R_SetPatchNum(&hu_fontk[i], buffer);
}
}
//
// HU_Stop()
//
// Make the heads-up displays inactive
//
// Passed nothing, returns nothing
//
static 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
if (map_point_coordinates)
{
sprintf(hud_coordstrx,"X: %-5d",0); //jff 2/22/98 added z
s = hud_coordstrx;
while (*s)
HUlib_addCharToTextLine(&w_coordx, *(s++));
sprintf(hud_coordstry,"Y: %-5d",0); //jff 3/3/98 split x,y,z
s = hud_coordstry;
while (*s)
HUlib_addCharToTextLine(&w_coordy, *(s++));
sprintf(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
if (map_point_coordinates)
{
sprintf(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
sprintf(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
sprintf(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
sprintf(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
sprintf(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
sprintf(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)
{
sprintf(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)
{
sprintf(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)
{
sprintf(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)
{
sprintf(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
sprintf
(
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 == KEYD_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
//
static 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
// killough 10/02/98: no chat if demo playback
// no chat in -solo-net mode
else if (!demoplayback && !message_list && netgame && numplayers > 1)
{
if (ev->data1 == key_chat)
{
eatkey = chat_on = true;
HUlib_resetIText(&w_chat);
HU_queueChatChar(HU_BROADCAST);
}
else if (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;
}