/* 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;i122) { 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 ; imo->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 (ammopcthealth; 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 (healtharmorpoints; 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=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 (ammopct1) { 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;ktop1) { 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= '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 ; idata1 == 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; idata1 == 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; }