// DR. ROBOTNIK'S RING RACERS //----------------------------------------------------------------------------- // Copyright (C) 2025 by Kart Krew. // Copyright (C) 2020 by Sonic Team Junior. // Copyright (C) 2000 by DooM Legacy Team. // Copyright (C) 1996 by id Software, Inc. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- /// \file hu_stuff.c /// \brief Heads up display #include "doomdef.h" #include "byteptr.h" #include "hu_stuff.h" #include "font.h" #include "k_menu.h" // highlightflags #include "m_cond.h" // emblems #include "m_misc.h" // word jumping #include "d_clisrv.h" #include "g_game.h" #include "g_input.h" #include "i_video.h" #include "i_system.h" #include "st_stuff.h" // ST_HEIGHT #include "r_local.h" #include "keys.h" #include "v_video.h" #include "w_wad.h" #include "z_zone.h" #include "console.h" #include "am_map.h" #include "d_main.h" #include "p_local.h" // camera[] #include "p_tick.h" #ifdef HWRENDER #include "hardware/hw_main.h" #endif #include "lua_hud.h" #include "lua_hudlib_drawlist.h" #include "lua_hook.h" // SRB2Kart #include "s_sound.h" // song credits #include "k_kart.h" #include "k_battle.h" #include "k_grandprix.h" #include "k_color.h" #include "k_hud.h" #include "r_fps.h" #include "d_clisrv.h" #include "y_inter.h" // Y_PlayerStandingsDrawer #include "g_party.h" // coords are scaled #define HU_INPUTX 0 #define HU_INPUTY 0 //------------------------------------------- // heads up font //------------------------------------------- // ping font // Note: I'd like to adress that at this point we might *REALLY* want to work towards a common drawString function that can take any font we want because this is really turning into a MESS. :V -Lat' patch_t *pinggfx[5]; // small ping graphic patch_t *mping[5]; // smaller ping graphic patch_t *pingmeasure[2]; // ping measurement graphic patch_t *pinglocal[2]; // mindelay indecator patch_t *framecounter; patch_t *frameslash; // framerate stuff. Used in screen.c static player_t *plr; boolean hu_keystrokes; // :) boolean chat_on; // entering a chat message? boolean g_voicepushtotalk_on; // holding PTT? static char w_chat[HU_MAXMSGLEN + 1]; static size_t c_input = 0; // let's try to make the chat input less shitty. static boolean headsupactive = false; boolean hu_showscores; // draw rankings static char hu_tick; //------------------------------------------- // misc vars //------------------------------------------- patch_t *missingpat; patch_t *blanklvl, *nolvl; patch_t *unvisitedlvl[4]; // song credits static patch_t *songcreditbg; // ------- // protos. // ------- static void HU_DrawRankings(void); //====================================================================== // KEYBOARD LAYOUTS FOR ENTERING TEXT //====================================================================== char *shiftxform; 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 }; static char cechotext[1024]; static tic_t cechotimer = 0; static tic_t cechoduration = 5*TICRATE; static INT32 cechoflags = 0; struct tcecho_state { char text[1024]; // buffer for the titlecard text tic_t start; // gametic that the message started tic_t duration; // Set automatically }; #define NUM_TCECHO_STATES (1 + MAXSPLITSCREENPLAYERS) static struct tcecho_state g_tcecho[NUM_TCECHO_STATES]; static tic_t resynch_ticker = 0; static huddrawlist_h luahuddrawlist_scores; //====================================================================== // HEADS UP INIT //====================================================================== // just after static void Command_Say_f(void); static void Command_Sayto_f(void); static void Command_Sayteam_f(void); static void Command_CSay_f(void); static void Command_Shout(void); static void Got_Saycmd(const UINT8 **p, INT32 playernum); void HU_LoadGraphics(void) { INT32 i; if (dedicated) return; Font_Load(); HU_UpdatePatch(&blanklvl, "BLANKLVL"); HU_UpdatePatch(&nolvl, "M_NOLVL"); for (i = 0; i < 4; i++) { HU_UpdatePatch(&unvisitedlvl[i], "PREVST0%d", i+1); } HU_UpdatePatch(&songcreditbg, "K_SONGCR"); // cache ping gfx: for (i = 0; i < 5; i++) { HU_UpdatePatch(&pinggfx[i], "PINGGFX%d", i+1); HU_UpdatePatch(&mping[i], "MPING%d", i+1); } HU_UpdatePatch(&pingmeasure[0], "PINGD"); HU_UpdatePatch(&pingmeasure[1], "PINGMS"); HU_UpdatePatch(&pinglocal[0], "PINGGFXL"); HU_UpdatePatch(&pinglocal[1], "MPINGL"); // fps stuff HU_UpdatePatch(&framecounter, "FRAMER"); HU_UpdatePatch(&frameslash, "FRAMESL"); } // Initialise Heads up // once at game startup. // void HU_Init(void) { font_t font; COM_AddCommand("say", Command_Say_f); COM_AddCommand("sayto", Command_Sayto_f); COM_AddCommand("sayteam", Command_Sayteam_f); COM_AddCommand("csay", Command_CSay_f); COM_AddCommand("shout", Command_Shout); RegisterNetXCmd(XD_SAY, Got_Saycmd); // only allocate if not present, to save us a lot of headache if (missingpat == NULL) { lumpnum_t missingnum = W_GetNumForName("MISSING"); if (missingnum == LUMPERROR) I_Error("HU_LoadGraphics: \"MISSING\" patch not present in resource files."); missingpat = W_CachePatchNum(missingnum, PU_STATIC); } // set shift translation table shiftxform = english_shiftxform; /* Setup fonts */ if (!dedicated) { #define DIM( s, n ) ( font.start = s, font.size = n ) #define ADIM( name ) DIM (name ## _FONTSTART, name ## _FONTSIZE) #define PR( s ) strcpy(font.prefix, s) #define DIG( n ) ( font.digits = n ) #define REG Font_DumbRegister(&font) DIG (3); ADIM (HU); PR ("STCFN"); REG; PR ("MNUFN"); REG; PR ("TNYFN"); REG; PR ("MDFN"); REG; PR ("FILEF"); REG; ADIM (LT); PR ("LTFNT"); REG; ADIM (CRED); PR ("CRFNT"); REG; DIG (3); ADIM (LT); PR ("GTOL"); REG; PR ("GTFN"); REG; PR ("4GTOL"); REG; PR ("4GTFN"); REG; DIG (2); PR ("GENEFN"); REG; DIG (1); DIM (0, 10); PR ("STTNUM"); REG; PR ("NGTNUM"); REG; PR ("PINGN"); REG; PR ("PRFN"); REG; DIM ('0', 10); DIG (2); PR ("ROLNUM"); REG; PR ("RO4NUM"); REG; DIG (3); ADIM (KART); PR ("MKFNT"); REG; ADIM (NUM); PR ("TMFNT"); REG; PR ("TMFNS"); REG; ADIM (LT); PR ("GAMEM"); REG; ADIM (LT); PR ("THIFN"); REG; PR ("TLWFN"); REG; ADIM (NUM); PR ("OPPRF"); REG; ADIM (NUM); PR ("PINGF"); REG; #undef REG #undef DIG #undef PR #undef ADMIN #undef DIM } HU_LoadGraphics(); luahuddrawlist_scores = LUA_HUD_CreateDrawList(); } patch_t *HU_UpdateOrBlankPatch(patch_t **user, boolean required, const char *format, ...) { va_list ap; char buffer[9]; lumpnum_t lump = INT16_MAX; patch_t *patch; va_start (ap, format); vsnprintf(buffer, sizeof buffer, format, ap); va_end (ap); if (user && partadd_earliestfile != UINT16_MAX) { UINT16 fileref = numwadfiles; lump = INT16_MAX; while ((lump == INT16_MAX) && ((--fileref) >= partadd_earliestfile)) { lump = W_CheckNumForNamePwad(buffer, fileref, 0); } /* no update in this wad */ if (fileref < partadd_earliestfile) return *user; lump |= (fileref << 16); } else { lump = W_CheckNumForName(buffer); if (lump == LUMPERROR) { if (required == true) *user = missingpat; return *user; } } patch = W_CachePatchNum(lump, PU_HUDGFX); if (user) { if (*user) Patch_Free(*user); *user = patch; } return patch; } static inline void HU_Stop(void) { headsupactive = false; } // // Reset Heads up when consoleplayer spawns // void HU_Start(void) { if (headsupactive) HU_Stop(); plr = &players[consoleplayer]; headsupactive = true; } //====================================================================== // EXECUTION //====================================================================== // EVERY CHANGE IN THIS SCRIPT IS LOL XD! BY VINCYTM static UINT32 chat_nummsg_log = 0; static UINT32 chat_nummsg_min = 0; static UINT32 chat_scroll = 0; static tic_t chat_scrolltime = 0; static UINT32 chat_maxscroll = 0; // how far can we scroll? //static chatmsg_t chat_mini[CHAT_BUFSIZE]; // Display the last few messages sent. //static chatmsg_t chat_log[CHAT_BUFSIZE]; // Keep every message sent to us in memory so we can scroll n shit, it's cool. static char chat_log[CHAT_BUFSIZE][255]; // hold the last 48 or so messages in that log. static char chat_mini[8][255]; // display up to 8 messages that will fade away / get overwritten static tic_t chat_timers[8]; static boolean chat_scrollmedown = false; // force instant scroll down on the chat log. Happens when you open it / send a message. // remove text from minichat table static INT16 addy = 0; // use this to make the messages scroll smoothly when one fades away static void HU_removeChatText_Mini(void) { // MPC: Don't create new arrays, just iterate through an existing one size_t i; for(i=0;i