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.
This commit is contained in:
James R 2023-08-20 15:21:13 -07:00 committed by toaster
parent 4f60d046ba
commit baf7f82af3
4 changed files with 112 additions and 39 deletions

View file

@ -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*>(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;

View file

@ -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);
}

View file

@ -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);

View file

@ -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;
}