From 4f60d046ba7a0db37cce28e9fb7dd983fa28863d Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 20 Aug 2023 15:18:26 -0700 Subject: [PATCH 01/11] V_DrawTitleCardString, V_TitleCardStringWidth: add 4P font support --- src/hu_stuff.c | 10 +++++++-- src/hu_stuff.h | 3 +++ src/lua_hudlib.c | 8 +++++--- src/lua_hudlib_drawlist.c | 7 +++++-- src/lua_hudlib_drawlist.h | 3 ++- src/st_stuff.c | 8 ++++---- src/v_video.cpp | 43 +++++++++++++++++++++++++++------------ src/v_video.h | 4 ++-- src/y_inter.c | 4 ++-- 9 files changed, 61 insertions(+), 29 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index fd9fa3c97..a32365fb6 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -283,6 +283,12 @@ void HU_Init(void) PR ("GTFN"); REG; + PR ("4GTOL"); + REG; + + PR ("4GTFN"); + REG; + DIG (1); DIM (0, 10); @@ -1874,8 +1880,8 @@ static void HU_DrawTitlecardCEcho(void) *line = '\0'; - w = V_TitleCardStringWidth(echoptr); - V_DrawTitleCardString(BASEVIDWIDTH/2 -w/2, y, echoptr, 0, false, timer, TICRATE*4); + w = V_TitleCardStringWidth(echoptr, false); + V_DrawTitleCardString(BASEVIDWIDTH/2 -w/2, y, echoptr, 0, false, timer, TICRATE*4, false); y += 32; diff --git a/src/hu_stuff.h b/src/hu_stuff.h index 92ecdbc41..ed483c3a6 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -77,6 +77,9 @@ enum X (GTOL), X (GTFN), + X (GTOL4), + X (GTFN4), + X (TALLNUM), X (NIGHTSNUM), X (PINGNUM), diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 5a5583f1a..a95ff78c2 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -948,6 +948,7 @@ static int libd_drawTitleCardString(lua_State *L) boolean rightalign = lua_optboolean(L, 5); INT32 timer = luaL_optinteger(L, 6, 0); INT32 threshold = luaL_optinteger(L, 7, 0); + boolean p4 = lua_optboolean(L, 8); huddrawlist_h list; flags &= ~V_PARAMMASK; // Don't let crashes happen. @@ -958,9 +959,9 @@ static int libd_drawTitleCardString(lua_State *L) lua_pop(L, 1); if (LUA_HUD_IsDrawListValid(list)) - LUA_HUD_AddDrawTitleCardString(list, x, y, flags, str, rightalign, timer, threshold); + LUA_HUD_AddDrawTitleCardString(list, x, y, flags, str, rightalign, timer, threshold, p4); else - V_DrawTitleCardString(x, y, str, flags, rightalign, timer, threshold); + V_DrawTitleCardString(x, y, str, flags, rightalign, timer, threshold, p4); return 0; } @@ -989,9 +990,10 @@ static int libd_drawKartString(lua_State *L) static int libd_titleCardStringWidth(lua_State *L) { const char *str = luaL_checkstring(L, 1); + boolean p4 = lua_optboolean(L, 2); HUDONLY - lua_pushinteger(L, V_TitleCardStringWidth(str)); + lua_pushinteger(L, V_TitleCardStringWidth(str, p4)); return 1; } diff --git a/src/lua_hudlib_drawlist.c b/src/lua_hudlib_drawlist.c index 68515ae20..8418f1b5a 100644 --- a/src/lua_hudlib_drawlist.c +++ b/src/lua_hudlib_drawlist.c @@ -61,6 +61,7 @@ typedef struct drawitem_s { INT32 timer; INT32 threshold; boolean bossmode; + boolean p4; } drawitem_t; // The internal structure of a drawlist. @@ -358,7 +359,8 @@ void LUA_HUD_AddDrawTitleCardString( const char *str, boolean bossmode, INT32 timer, - INT32 threshold + INT32 threshold, + boolean p4 ) { size_t i = AllocateDrawItem(list); @@ -371,6 +373,7 @@ void LUA_HUD_AddDrawTitleCardString( item->bossmode = bossmode; item->timer = timer; item->threshold = threshold; + item->p4 = p4; } void LUA_HUD_AddDrawKartString( @@ -465,7 +468,7 @@ void LUA_HUD_DrawList(huddrawlist_h list) V_DrawFadeScreen(item->color, item->strength); break; case DI_DrawTitleCardString: - V_DrawTitleCardString(item->x, item->y, itemstr, item->flags, item->bossmode, item->timer, item->threshold); + V_DrawTitleCardString(item->x, item->y, itemstr, item->flags, item->bossmode, item->timer, item->threshold, item->p4); break; case DI_DrawKartString: V_DrawTimerString(item->x, item->y, item->flags, itemstr); diff --git a/src/lua_hudlib_drawlist.h b/src/lua_hudlib_drawlist.h index 15249e4f9..bf2a161e2 100644 --- a/src/lua_hudlib_drawlist.h +++ b/src/lua_hudlib_drawlist.h @@ -111,7 +111,8 @@ void LUA_HUD_AddDrawTitleCardString( const char *str, boolean bossmode, INT32 timer, - INT32 threshold + INT32 threshold, + boolean p4 ); void LUA_HUD_AddDrawKartString( huddrawlist_h list, diff --git a/src/st_stuff.c b/src/st_stuff.c index c1ff32972..1e738dc5f 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -943,10 +943,10 @@ void ST_drawTitleCard(void) // Everything else... if (bossinfo.enemyname) { - bx = V_TitleCardStringWidth(bossinfo.enemyname); + bx = V_TitleCardStringWidth(bossinfo.enemyname, false); // Name. - V_DrawTitleCardString((BASEVIDWIDTH - bx)/2, 75, bossinfo.enemyname, 0, true, bossinfo.titleshow, lt_exitticker); + V_DrawTitleCardString((BASEVIDWIDTH - bx)/2, 75, bossinfo.enemyname, 0, true, bossinfo.titleshow, lt_exitticker, false); // Under-bar. { @@ -1067,10 +1067,10 @@ void ST_drawTitleCard(void) V_DrawFixedPatch(eggx2*FRACUNIT, eggy2*FRACUNIT, FRACUNIT, V_SNAPTOBOTTOM|V_SNAPTOLEFT, tccirclebottom, NULL); // Now the level name. - V_DrawTitleCardString((actnum) ? 265 : 280, 60, lvlttl, V_SNAPTORIGHT, false, lt_ticker, TTANIMENDTHRESHOLD); + V_DrawTitleCardString((actnum) ? 265 : 280, 60, lvlttl, V_SNAPTORIGHT, false, lt_ticker, TTANIMENDTHRESHOLD, false); if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) - V_DrawTitleCardString((actnum) ? 265 : 280, 60+32, strlen(zonttl) ? zonttl : "ZONE", V_SNAPTORIGHT, false, lt_ticker - strlen(lvlttl), TTANIMENDTHRESHOLD); + V_DrawTitleCardString((actnum) ? 265 : 280, 60+32, strlen(zonttl) ? zonttl : "ZONE", V_SNAPTORIGHT, false, lt_ticker - strlen(lvlttl), TTANIMENDTHRESHOLD, false); // the act has a similar graphic animation, but we'll handle it here since it's only like 2 graphics lmfao. if (actnum && actnum < 10) diff --git a/src/v_video.cpp b/src/v_video.cpp index 9c6583916..224530269 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1854,8 +1854,17 @@ void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercase, UINT8 *co // V_TitleCardStringWidth // Get the string's width using the titlecard font. -INT32 V_TitleCardStringWidth(const char *str) +INT32 V_TitleCardStringWidth(const char *str, boolean p4) { + int bg_font = GTOL_FONT; + int fg_font = GTFN_FONT; + + if (p4) + { + bg_font = GTOL4_FONT; + fg_font = GTFN4_FONT; + } + INT32 xoffs = 0; const char *ch = str; char c; @@ -1877,15 +1886,15 @@ INT32 V_TitleCardStringWidth(const char *str) c -= LT_FONTSTART; // check if character exists, if not, it's a space. - if (c < 0 || c >= LT_FONTSIZE || !fontv[GTOL_FONT].font[(INT32)c]) + if (c < 0 || c >= LT_FONTSIZE || !fontv[bg_font].font[(INT32)c]) { - xoffs += 10; + xoffs += p4 ? 5 : 10; continue; } - pp = fontv[GTFN_FONT].font[(INT32)c]; + pp = fontv[fg_font].font[(INT32)c]; - xoffs += pp->width-5; + xoffs += pp->width - (p4 ? 3 : 5); } return xoffs; @@ -1894,8 +1903,16 @@ INT32 V_TitleCardStringWidth(const char *str) // V_DrawTitleCardScreen. // see v_video.h's prototype for more information. // -void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boolean bossmode, INT32 timer, INT32 threshold) +void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boolean bossmode, INT32 timer, INT32 threshold, boolean p4) { + int bg_font = GTOL_FONT; + int fg_font = GTFN_FONT; + + if (p4) + { + bg_font = GTOL4_FONT; + fg_font = GTFN4_FONT; + } INT32 xoffs = 0; INT32 yoffs = 0; @@ -1916,7 +1933,7 @@ void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boole x -= 2; // Account for patch width... if (flags & V_SNAPTORIGHT) - x -= V_TitleCardStringWidth(str); + x -= V_TitleCardStringWidth(str, p4); for (;;ch++, i++) @@ -1933,7 +1950,7 @@ void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boole if (*ch == '\n') { xoffs = x; - yoffs += 32; + yoffs += p4 ? 18 : 32; continue; } @@ -1944,14 +1961,14 @@ void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boole c -= LT_FONTSTART; // check if character exists, if not, it's a space. - if (c < 0 || c >= LT_FONTSIZE || !fontv[GTFN_FONT].font[(INT32)c]) + if (c < 0 || c >= LT_FONTSIZE || !fontv[fg_font].font[(INT32)c]) { - xoffs += 10; + xoffs += p4 ? 5 : 10; continue; } - ol = fontv[GTOL_FONT].font[(INT32)c]; - pp = fontv[GTFN_FONT].font[(INT32)c]; + ol = fontv[bg_font].font[(INT32)c]; + pp = fontv[fg_font].font[(INT32)c]; if (bossmode) { @@ -2004,7 +2021,7 @@ void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boole V_DrawStretchyFixedPatch((x + xoffs)*FRACUNIT + offs, (y+yoffs)*FRACUNIT, abs(scalex), FRACUNIT, flags|flipflag, pp, NULL); } - xoffs += pp->width -5; + xoffs += pp->width - (p4 ? 3 : 5); } } diff --git a/src/v_video.h b/src/v_video.h index f7c32505c..b1e47b73d 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -347,10 +347,10 @@ void V_DrawRightAlignedThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, con // threshold: when the letters start disappearing (leave to 0 to disable) (both are INT32 in case you supply negative values...) // NOTE: This function ignores most conventional string flags (V_RETURN8, V_FORCEUPPERCASE ...) // NOTE: This font only works with uppercase letters. -void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boolean bossmode, INT32 timer, INT32 threshold); +void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boolean bossmode, INT32 timer, INT32 threshold, boolean p4); // returns thr width of a string drawn using the above function. -INT32 V_TitleCardStringWidth(const char *str); +INT32 V_TitleCardStringWidth(const char *str, boolean p4); // Draw tall nums, used for menu, HUD, intermission void V_DrawTallNum(INT32 x, INT32 y, INT32 flags, INT32 num); diff --git a/src/y_inter.c b/src/y_inter.c index 6c980a7ee..9ea49d4a0 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1462,7 +1462,7 @@ void Y_IntermissionDrawer(void) } else { - headerwidth = V_TitleCardStringWidth(data.headerstring); + headerwidth = V_TitleCardStringWidth(data.headerstring, false); headerx = (BASEVIDWIDTH - headerwidth)/2; headery = 17; @@ -1490,7 +1490,7 @@ void Y_IntermissionDrawer(void) V_DrawMappedPatch(x + roundx, 39, 0, roundpatch, NULL); } - V_DrawTitleCardString(x + headerx, headery, data.headerstring, 0, false, 0, 0); + V_DrawTitleCardString(x + headerx, headery, data.headerstring, 0, false, 0, 0, false); } // Returns early if there's no players to draw From baf7f82af35f67c39ec63784e3dd3ab44189590c Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 20 Aug 2023 15:21:13 -0700 Subject: [PATCH 02/11] HU_DoTitlecardCEcho: add splitscreen support and interrupt feature - Takes player argument and only appears on the screen if they're a display player. - Uses 4P font when in splitscreen. - Uses 1P font if not in splitscreen, or player argument is NULL -- message to everyone. - Interrupt argument controls whether the message should overwrite another message that's already playing. - Global and player specific messages are considered separately. --- src/acs/call-funcs.cpp | 11 +++- src/hu_stuff.c | 129 +++++++++++++++++++++++++++++++---------- src/hu_stuff.h | 2 +- src/lua_baselib.c | 9 ++- 4 files changed, 112 insertions(+), 39 deletions(-) diff --git a/src/acs/call-funcs.cpp b/src/acs/call-funcs.cpp index c7ff38591..24170bf41 100644 --- a/src/acs/call-funcs.cpp +++ b/src/acs/call-funcs.cpp @@ -338,6 +338,8 @@ static bool ACS_CountThing(mobj_t *mobj, mobjtype_t type) return false; } +// Unused, but it's here if you need it. +#if 0 /*-------------------------------------------------- static bool ACS_ActivatorIsLocal(ACSVM::Thread *thread) @@ -365,6 +367,7 @@ static bool ACS_ActivatorIsLocal(ACSVM::Thread *thread) return false; } +#endif /*-------------------------------------------------- static UINT32 ACS_SectorThingCounter(sector_t *sec, mtag_t thingTag, bool (*filter)(mobj_t *)) @@ -823,8 +826,10 @@ bool CallFunc_EndPrint(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Wo (void)argV; (void)argC; - if (ACS_ActivatorIsLocal(thread) == true) - HU_DoTitlecardCEcho(thread->printBuf.data()); + auto& info = static_cast(thread)->info; + + if (P_MobjWasRemoved(info.mo) == false && info.mo->player != nullptr) + HU_DoTitlecardCEcho(info.mo->player, thread->printBuf.data(), true); thread->printBuf.drop(); return false; @@ -1203,7 +1208,7 @@ bool CallFunc_EndPrintBold(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM (void)argV; (void)argC; - HU_DoTitlecardCEcho(thread->printBuf.data()); + HU_DoTitlecardCEcho(nullptr, thread->printBuf.data(), true); thread->printBuf.drop(); return false; diff --git a/src/hu_stuff.c b/src/hu_stuff.c index a32365fb6..7ab2e7b36 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -62,6 +62,7 @@ #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 @@ -157,10 +158,15 @@ static tic_t cechotimer = 0; static tic_t cechoduration = 5*TICRATE; static INT32 cechoflags = 0; -static char tcechotext[1024]; // buffer for the titlecard text -static tic_t tcechotimer = 0; // goes up by 1 each frame this is active -static tic_t tcechoduration = 0; // Set automatically +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; @@ -966,13 +972,6 @@ void HU_Ticker(void) if (cechotimer) cechotimer--; - - if (tcechotimer) - { - tcechotimer++; - if (tcechotimer > tcechoduration) - tcechotimer = 0; - } if (gamestate != GS_LEVEL) { @@ -1835,12 +1834,31 @@ static void HU_DrawCEcho(void) } } -static void HU_DrawTitlecardCEcho(void) +static tic_t HU_TitlecardCEchoElapsed(const struct tcecho_state *state) { - if (tcechotimer) + return max(gametic, state->start) - state->start; +} + +static void HU_DrawTitlecardCEcho(size_t num) +{ + const struct tcecho_state *state = &g_tcecho[num]; + + tic_t elapsed = HU_TitlecardCEchoElapsed(state); + UINT8 viewnum = max(1, num) - 1; + boolean p4 = (num != 0 && r_splitscreen); + + // If the splitscreens were somehow decreased in the + // middle of drawing this, don't draw it. + if (viewnum > r_splitscreen) + { + return; + } + + if (elapsed < state->duration) { INT32 i = 0; - INT32 y = (BASEVIDHEIGHT/2)-16; + INT32 x = BASEVIDWIDTH/2; + INT32 y = BASEVIDHEIGHT/2; INT32 pnumlines = 0; INT32 timeroffset = 0; @@ -1848,11 +1866,28 @@ static void HU_DrawTitlecardCEcho(void) char *echoptr; char temp[1024]; - for (i = 0; tcechotext[i] != '\0'; ++i) - if (tcechotext[i] == '\\') + for (i = 0; state->text[i] != '\0'; ++i) + if (state->text[i] == '\\') pnumlines++; - y -= (pnumlines-1)*16; + if (p4) + { + if (r_splitscreen == 1) // 2P + { + y -= (1 - (viewnum * 2)) * (y / 2); + } + else // 3P / 4P + { + x -= (1 - ((viewnum % 2) * 2)) * (x / 2); + y -= (1 - ((viewnum / 2) * 2)) * (y / 2); + } + + y -= 11 + ((pnumlines-1) * 9); + } + else + { + y -= 18 + ((pnumlines-1) * 16); + } // Prevent crashing because I'm sick of this if (y < 0) @@ -1862,13 +1897,13 @@ static void HU_DrawTitlecardCEcho(void) return; } - strcpy(temp, tcechotext); + strcpy(temp, state->text); echoptr = &temp[0]; while (*echoptr != '\0') { INT32 w; - INT32 timer = (INT32)(tcechotimer - timeroffset); + INT32 timer = (INT32)(elapsed - timeroffset); if (timer <= 0) return; // we don't care. @@ -1880,10 +1915,10 @@ static void HU_DrawTitlecardCEcho(void) *line = '\0'; - w = V_TitleCardStringWidth(echoptr, false); - V_DrawTitleCardString(BASEVIDWIDTH/2 -w/2, y, echoptr, 0, false, timer, TICRATE*4, false); + w = V_TitleCardStringWidth(echoptr, p4); + V_DrawTitleCardString(x -w/2, y, echoptr, 0, false, timer, TICRATE*4, p4); - y += 32; + y += p4 ? 18 : 32; // offset the timer for the next line. timeroffset += strlen(echoptr); @@ -2043,9 +2078,15 @@ drawontop: if (cechotimer) HU_DrawCEcho(); - - if (tcechotimer) - HU_DrawTitlecardCEcho(); + + { + size_t i; + + for (i = 0; i < NUM_TCECHO_STATES; ++i) + { + HU_DrawTitlecardCEcho(i); + } + } } //====================================================================== @@ -2582,17 +2623,41 @@ void HU_DoCEcho(const char *msg) // No need to bother clearing the buffer or anything. void HU_ClearTitlecardCEcho(void) { - tcechotimer = 0; + size_t i; + + for (i = 0; i < NUM_TCECHO_STATES; ++i) + { + g_tcecho[i].duration = 0; + } } // Similar but for titlecard CEcho and also way less convoluted because I have no clue whatever the fuck they were trying above. -void HU_DoTitlecardCEcho(const char *msg) +void HU_DoTitlecardCEcho(player_t *player, const char *msg, boolean interrupt) { + if (player && !P_IsDisplayPlayer(player)) + { + return; + } + + struct tcecho_state *state = &g_tcecho[0]; + + if (player) + { + state = &g_tcecho[1 + G_PartyPosition(player - players)]; + } + + // If this message should not interrupt an existing + // message. Check if another message is already running. + if (!interrupt && HU_TitlecardCEchoElapsed(state) < state->duration) + { + return; + } + I_OutputMsg("%s\n", msg); // print to log - - strncpy(tcechotext, msg, sizeof(tcechotext)); - strncat(tcechotext, "\\", sizeof(tcechotext) - strlen(tcechotext) - 1); - tcechotext[sizeof(tcechotext) - 1] = '\0'; - tcechotimer = 1; - tcechoduration = TICRATE*6 + strlen(tcechotext); + + strncpy(state->text, msg, sizeof(state->text)); + strncat(state->text, "\\", sizeof(state->text) - strlen(state->text) - 1); + state->text[sizeof(state->text) - 1] = '\0'; + state->start = gametic; + state->duration = TICRATE*6 + strlen(state->text); } diff --git a/src/hu_stuff.h b/src/hu_stuff.h index ed483c3a6..db1cfcc57 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -166,7 +166,7 @@ void HU_SetCEchoFlags(INT32 flags); void HU_DoCEcho(const char *msg); // Titlecard CECHO shite -void HU_DoTitlecardCEcho(const char *msg); +void HU_DoTitlecardCEcho(player_t *player, const char *msg, boolean interrupt); void HU_ClearTitlecardCEcho(void); void DoSayCommand(char *message, SINT8 target, UINT8 flags, UINT8 source); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index bd1771a89..69f0aed21 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3515,9 +3515,12 @@ static int lib_getTimeMicros(lua_State *L) static int lib_startTitlecardCecho(lua_State *L) { - const char *str = luaL_checkstring(L, 1); - HU_DoTitlecardCEcho(str); - + player_t *player = lua_isnil(L, 1) ? NULL : *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + const char *str = luaL_checkstring(L, 2); + boolean interrupt = lua_optboolean(L, 3); + + HU_DoTitlecardCEcho(player, str, interrupt); + return 1; } From ae2fdcbd12ac107476a9c950424b848db6f6f28c Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 19 Aug 2023 18:18:17 -0700 Subject: [PATCH 03/11] cecho command: use titlecard font --- src/command.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/command.c b/src/command.c index fd5044e8b..7ff65cb05 100644 --- a/src/command.c +++ b/src/command.c @@ -785,7 +785,7 @@ static void COM_CEcho_f(void) cechotext[sizeof(cechotext) - 1] = '\0'; - HU_DoCEcho(cechotext); + HU_DoTitlecardCEcho(NULL, cechotext, true); } /** Sets drawing flags for the CECHO command. From 2328ceb4bcaab01da2fa455191d16ecaba664ce9 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 16 Aug 2023 00:43:40 -0700 Subject: [PATCH 04/11] V_TitleCardStringWidth: don't count punctuation, in order to help centering Punctuation, like ellipsis, normally offsets the centered position of text. But this looks subjectively weird. By not counting it, punctuation is basically allowed to extend further off to the sides. The difference looks like: CENTER || \/ || OLD: | TOO LATE... | || NEW: | TOO LATE... | || /\ || CENTER --- src/v_video.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/v_video.cpp b/src/v_video.cpp index 224530269..740df7b80 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1881,6 +1881,17 @@ INT32 V_TitleCardStringWidth(const char *str, boolean p4) continue; } + // For the sake of centering, don't count punctuation. + // TODO: This should ideally be more sophisticated: + // - Only apply on the ends of each line. + // - Check patch width directly for monospace or + // punctuation that isn't necessarily thin. + // - Apply to all string drawing. + if (ispunct(*ch)) + { + continue; + } + c = *ch; c = toupper(c); c -= LT_FONTSTART; From 5d8efb66a4ae3597a81aa03e46d647b4502e3af4 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 16 Aug 2023 00:40:24 -0700 Subject: [PATCH 05/11] Sealed Stars: show text on the screen for loss conditions Player dies: FALL OUT! Player finishes before collecting the emerald: EMPTY HANDED? UFO finishes before player: TOO LATE... --- src/objects/ufo.c | 3 +++ src/p_inter.c | 5 +++++ src/p_spec.c | 2 ++ 3 files changed, 10 insertions(+) diff --git a/src/objects/ufo.c b/src/objects/ufo.c index 6a9f4bbdc..71ae0b585 100644 --- a/src/objects/ufo.c +++ b/src/objects/ufo.c @@ -26,6 +26,7 @@ #include "../r_skins.h" #include "../k_hitlag.h" #include "../acs/interface.h" +#include "../hu_stuff.h" #define UFO_BASE_SPEED (42 * FRACUNIT) // UFO's slowest speed. #define UFO_SPEEDUP (FRACUNIT >> 1) // Acceleration @@ -453,6 +454,8 @@ static void UFOMove(mobj_t *ufo) // Disable player P_DoAllPlayersExit(PF_NOCONTEST, false); + + HU_DoTitlecardCEcho(NULL, "TOO LATE...", false); } if (pathfindsuccess == true) diff --git a/src/p_inter.c b/src/p_inter.c index 890644320..e56e68400 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2069,6 +2069,11 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, #else P_DoPlayerExit(player, PF_NOCONTEST); #endif + + if (specialstageinfo.valid == true) + { + HU_DoTitlecardCEcho(player, "FALL OUT!", false); + } } if (player->exiting) diff --git a/src/p_spec.c b/src/p_spec.c index 85003e43e..1c454f8b5 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2053,6 +2053,8 @@ static void K_HandleLapIncrement(player_t *player) if (!(specialstageinfo.ufo == NULL || P_MobjWasRemoved(specialstageinfo.ufo))) { applyflags |= PF_NOCONTEST; + + HU_DoTitlecardCEcho(player, "EMPTY\\HANDED?", false); } } From 908022c8219351e8bb717f47b20af2abbf73ae29 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 26 Aug 2023 21:44:51 +0100 Subject: [PATCH 06/11] Fix overlapping Title CEcho text If an admin title cecho is active, do not render individual viewport title cechos. Some information is lost, but currently everything expressed through them is not unique while admin title cechos generally are, so they're a safe thing to sacrifice given limited screen space. --- src/hu_stuff.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 7ab2e7b36..4433adf0d 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2079,10 +2079,18 @@ drawontop: if (cechotimer) HU_DrawCEcho(); + const struct tcecho_state *firststate = &g_tcecho[0]; + + // Server messages overwrite player-specific messages + if (HU_TitlecardCEchoElapsed(firststate) < firststate->duration) + { + HU_DrawTitlecardCEcho(0); + } + else { size_t i; - for (i = 0; i < NUM_TCECHO_STATES; ++i) + for (i = 1; i < NUM_TCECHO_STATES; ++i) { HU_DrawTitlecardCEcho(i); } From 6869496843741725e9b42239500a4cf7f5d1d4e4 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 26 Aug 2023 23:30:12 +0100 Subject: [PATCH 07/11] Fade to white before the Podium if you successfully get the Emerald/Prize Further Sealed Star polish requested on the gitlab. --- src/g_game.c | 4 ++++ src/k_podium.c | 16 ++++++++++++++++ src/k_podium.h | 14 ++++++++++++++ src/p_setup.c | 14 +++++++++++++- 4 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/g_game.c b/src/g_game.c index 345b65d95..a2804a566 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1249,6 +1249,10 @@ boolean G_IsTitleCardAvailable(void) if (gametyperules & GTR_SPECIALSTART) return false; + // ALso. + if (K_PodiumSequence() == true) + return false; + // The title card is available. return true; } diff --git a/src/k_podium.c b/src/k_podium.c index 2f1694f52..ef455475b 100644 --- a/src/k_podium.c +++ b/src/k_podium.c @@ -94,6 +94,21 @@ gp_rank_e K_PodiumGrade(void) return podiumData.grade; } +/*-------------------------------------------------- + boolean K_PodiumHasEmerald(void) + + See header file for description. +--------------------------------------------------*/ +boolean K_PodiumHasEmerald(void) +{ + if (K_PodiumSequence() == false) + { + return false; + } + + return podiumData.rank.specialWon; +} + /*-------------------------------------------------- UINT8 K_GetPodiumPosition(player_t *player) @@ -284,6 +299,7 @@ boolean K_StartCeremony(void) G_SetGametype(GT_RACE); G_DoLoadLevelEx(false, GS_CEREMONY); + wipegamestate = GS_CEREMONY; // I don't know what else to do here r_splitscreen = 0; // Only one screen for the ceremony R_ExecuteSetViewSize(); diff --git a/src/k_podium.h b/src/k_podium.h index d7b04e3e4..eb73a7aae 100644 --- a/src/k_podium.h +++ b/src/k_podium.h @@ -69,6 +69,20 @@ boolean K_PodiumRanking(void); gp_rank_e K_PodiumGrade(void); +/*-------------------------------------------------- + boolean K_PodiumHasEmerald(void) + + Returns whether the Emerald or Prize was collected. + + Input Arguments:- + N/A + + Return:- + true if the Emerald/Prize was collected during the GP, otherwise false. +--------------------------------------------------*/ +boolean K_PodiumHasEmerald(void); + + /*-------------------------------------------------- UINT8 K_GetPodiumPosition(player_t *player); diff --git a/src/p_setup.c b/src/p_setup.c index 958bfa22e..ee0c5d2eb 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -8216,8 +8216,17 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) } } - if (gametyperules & GTR_SPECIALSTART) + if (K_PodiumHasEmerald()) { + // Special Stage out + if (ranspecialwipe != 2) + S_StartSound(NULL, sfx_s3k6a); + levelfadecol = 0; + wipetype = wipe_encore_towhite; + } + else if (gametyperules & GTR_SPECIALSTART) + { + // Special Stage in if (ranspecialwipe != 2) S_StartSound(NULL, sfx_s3kaf); levelfadecol = 0; @@ -8225,6 +8234,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) } else if (skipstats == 1) { + // MapWarp if (ranspecialwipe != 2) S_StartSound(NULL, sfx_s3k73); levelfadecol = 0; @@ -8232,11 +8242,13 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) } else if (encoremode) { + // Encore levelfadecol = 0; wipetype = wipe_encore_towhite; } else { + // Default levelfadecol = 31; } From 6fb7d16c85be4022b7721890c404d48ad9facca2 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 26 Aug 2023 23:47:36 +0100 Subject: [PATCH 08/11] Don't give extra lives in the final entry on a Round Queue (which fixes sealed star sound overload) --- src/p_user.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index a5176e580..11a213730 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1326,7 +1326,9 @@ void P_DoPlayerExit(player_t *player, pflags_t flags) G_BeginLevelExit(); } - if (grandprixinfo.gp == true && player->bot == false && losing == false) + if (grandprixinfo.gp == true + && (roundqueue.size && roundqueue.position < roundqueue.size) // Not the last map of GP + && player->bot == false && losing == false) { const UINT8 lifethreshold = 20; From 79699f47d5aa433bd8d0f0bba992452639a89ebb Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 26 Aug 2023 23:48:18 +0100 Subject: [PATCH 09/11] Sealed Star finish cleanup - No FINISH text - No voices - Warp sound on crossing the line, not any other stuff --- src/k_hud.c | 3 +++ src/p_spec.c | 10 +++++++++- src/p_user.c | 7 ++++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index af15b474a..5b64059d3 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -4332,6 +4332,9 @@ static void K_drawKartFinish(boolean finish) if (finish) { + if (gametyperules & GTR_SPECIALSTART) + return; + timer = stplyr->karthud[khud_finish]; kptodraw = kp_racefinish; minsplitstationary = 2; diff --git a/src/p_spec.c b/src/p_spec.c index 1c454f8b5..d3efd7ae5 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1987,7 +1987,15 @@ static void K_HandleLapIncrement(player_t *player) player->starpostnum = 0; - if (P_IsDisplayPlayer(player)) + if (gametyperules & GTR_SPECIALSTART) + { + if (player->laps > numlaps) + { + // Warp out + S_StartSound(NULL, sfx_s3kb3); + } + } + else if (P_IsDisplayPlayer(player)) { if (numlaps > 1 && player->laps == numlaps) // final lap S_StartSound(NULL, sfx_s3k68); diff --git a/src/p_user.c b/src/p_user.c index 11a213730..0fb242fbf 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1296,7 +1296,7 @@ void P_DoPlayerExit(player_t *player, pflags_t flags) { K_UpdateAllPlayerPositions(); - if (cv_kartvoices.value) + if (cv_kartvoices.value && !(gametyperules & GTR_SPECIALSTART)) { if (P_IsDisplayPlayer(player)) { @@ -1409,6 +1409,11 @@ void P_DoAllPlayersExit(pflags_t flags, boolean trygivelife) // You've already finished, don't play again ; } + else if (gametyperules & GTR_SPECIALSTART) + { + // Warp out + S_StartSound(NULL, sfx_s3kb3); + } else if (musiccountdown == 0) { // Other people finish From 2e748636d71051e6b25a94b9ded81afdcd476d54 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 27 Aug 2023 15:06:51 -0700 Subject: [PATCH 10/11] Create V_CenteredTitleCardStringOffset - V_TitleCardStringWidth no longer has the special case for punctuation, moved to this function instead. - Handles both leading and trailing punctuation, and even spaces. toaster-assisted, thank-you-toaster --- src/hu_stuff.c | 6 +-- src/v_video.cpp | 135 +++++++++++++++++++++++++++++++++++++----------- src/v_video.h | 3 ++ 3 files changed, 112 insertions(+), 32 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 4433adf0d..0b0434f70 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1902,7 +1902,7 @@ static void HU_DrawTitlecardCEcho(size_t num) while (*echoptr != '\0') { - INT32 w; + INT32 ofs; INT32 timer = (INT32)(elapsed - timeroffset); if (timer <= 0) @@ -1915,8 +1915,8 @@ static void HU_DrawTitlecardCEcho(size_t num) *line = '\0'; - w = V_TitleCardStringWidth(echoptr, p4); - V_DrawTitleCardString(x -w/2, y, echoptr, 0, false, timer, TICRATE*4, p4); + ofs = V_CenteredTitleCardStringOffset(echoptr, p4); + V_DrawTitleCardString(x - ofs, y, echoptr, 0, false, timer, TICRATE*4, p4); y += p4 ? 18 : 32; diff --git a/src/v_video.cpp b/src/v_video.cpp index 740df7b80..d472d4ab3 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1852,9 +1852,8 @@ void V_DrawChatCharacter(INT32 x, INT32 y, INT32 c, boolean lowercase, UINT8 *co ); } -// V_TitleCardStringWidth -// Get the string's width using the titlecard font. -INT32 V_TitleCardStringWidth(const char *str, boolean p4) +template +static INT32 Internal_TitleCardStringOffset(const char *str, boolean p4) { int bg_font = GTOL_FONT; int fg_font = GTFN_FONT; @@ -1870,45 +1869,123 @@ INT32 V_TitleCardStringWidth(const char *str, boolean p4) char c; patch_t *pp; - for (;;ch++) + // Returns true if it reached the end, false if interrupted. + auto scan = [&](auto keep_going) { - if (!*ch) - break; - - if (*ch == '\n') + for (;;ch++) { - xoffs = 0; - continue; + if (*ch == '\n') + { + xoffs = 0; + return false; + } + + if (!keep_going(*ch)) + { + break; + } + + c = *ch; + c = toupper(c); + c -= LT_FONTSTART; + + // check if character exists, if not, it's a space. + if (c < 0 || c >= LT_FONTSIZE || !fontv[bg_font].font[(INT32)c]) + { + xoffs += p4 ? 5 : 10; + continue; + } + + pp = fontv[fg_font].font[(INT32)c]; + + xoffs += pp->width - (p4 ? 3 : 5); } - // For the sake of centering, don't count punctuation. + return true; + }; + + do + { + // For the sake of centering, don't count spaces or + // punctuation at each end of a line. // TODO: This should ideally be more sophisticated: - // - Only apply on the ends of each line. // - Check patch width directly for monospace or // punctuation that isn't necessarily thin. - // - Apply to all string drawing. - if (ispunct(*ch)) + // - Apply to all centered string drawing. + if constexpr (Centered) { - continue; + // Count leading fluff + if (!scan([](int c) { return c && !isalnum(c); })) + { + continue; + } + + if (!*ch) + { + // ALL fluff, so center it normally. + break; + } + + // xoffs gets halved later, which centers the + // string. If we don't want leading fluff to push + // everything to the right, its full width needs + // to be subtracted, so it's doubled here to + // cancel out the division. + xoffs *= 2; + + INT32 trim = -1; + + bool reached_end = scan( + [&trim, &xoffs](int c) + { + if (isalnum(c)) + { + trim = -1; + } + else if (trim < 0) + { + trim = xoffs; + } + + return c; + } + ); + + // Discount trailing fluff + if (reached_end && trim >= 0) + { + xoffs = trim; + } } - - c = *ch; - c = toupper(c); - c -= LT_FONTSTART; - - // check if character exists, if not, it's a space. - if (c < 0 || c >= LT_FONTSIZE || !fontv[bg_font].font[(INT32)c]) + else { - xoffs += p4 ? 5 : 10; - continue; + scan([](int c) { return c; }); } - - pp = fontv[fg_font].font[(INT32)c]; - - xoffs += pp->width - (p4 ? 3 : 5); } + while (*(ch++)); - return xoffs; + if constexpr (Centered) + { + return xoffs / 2; + } + else + { + return xoffs; + } +} + +// V_TitleCardStringWidth +// Get the string's width using the titlecard font. +INT32 V_TitleCardStringWidth(const char *str, boolean p4) +{ + return Internal_TitleCardStringOffset(str, p4); +} + +// V_CenteredTitleCardStringOffset +// Subtract this offset from an X coordinate to center the string around that point. +INT32 V_CenteredTitleCardStringOffset(const char *str, boolean p4) +{ + return Internal_TitleCardStringOffset(str, p4); } // V_DrawTitleCardScreen. diff --git a/src/v_video.h b/src/v_video.h index b1e47b73d..2f4989a24 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -352,6 +352,9 @@ void V_DrawTitleCardString(INT32 x, INT32 y, const char *str, INT32 flags, boole // returns thr width of a string drawn using the above function. INT32 V_TitleCardStringWidth(const char *str, boolean p4); +// offset that can be subtracted to center align. +INT32 V_CenteredTitleCardStringOffset(const char *str, boolean p4); + // Draw tall nums, used for menu, HUD, intermission void V_DrawTallNum(INT32 x, INT32 y, INT32 flags, INT32 num); void V_DrawPaddedTallNum(INT32 x, INT32 y, INT32 flags, INT32 num, INT32 digits); From e3da0611923836d60754ebbc41d38d7cacf4bcc7 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 27 Aug 2023 15:11:12 -0700 Subject: [PATCH 11/11] cecho command: don't add trailing space Fixes centering for cechos of only punctuation. --- src/command.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/command.c b/src/command.c index 7ff65cb05..8f0574f03 100644 --- a/src/command.c +++ b/src/command.c @@ -777,10 +777,12 @@ static void COM_CEcho_f(void) size_t i; char cechotext[1024] = ""; - for (i = 1; i < COM_Argc(); i++) + strncpy(cechotext, COM_Argv(1), sizeof(cechotext)-1); + + for (i = 2; i < COM_Argc(); i++) { - strncat(cechotext, COM_Argv(i), sizeof(cechotext)-1); strncat(cechotext, " ", sizeof(cechotext)-1); + strncat(cechotext, COM_Argv(i), sizeof(cechotext)-1); } cechotext[sizeof(cechotext) - 1] = '\0';