mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'sealed-star-lose-text' into 'master'
Sealed Stars: show text on the screen for loss conditions; improved titlecard cecho centering, splitscreen support See merge request KartKrew/Kart!1404
This commit is contained in:
commit
1db1eaedff
21 changed files with 371 additions and 91 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -777,15 +777,17 @@ 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';
|
||||
|
||||
HU_DoCEcho(cechotext);
|
||||
HU_DoTitlecardCEcho(NULL, cechotext, true);
|
||||
}
|
||||
|
||||
/** Sets drawing flags for the CECHO command.
|
||||
|
|
|
|||
|
|
@ -1276,6 +1276,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;
|
||||
}
|
||||
|
|
|
|||
141
src/hu_stuff.c
141
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;
|
||||
|
||||
|
|
@ -283,6 +289,12 @@ void HU_Init(void)
|
|||
PR ("GTFN");
|
||||
REG;
|
||||
|
||||
PR ("4GTOL");
|
||||
REG;
|
||||
|
||||
PR ("4GTFN");
|
||||
REG;
|
||||
|
||||
DIG (1);
|
||||
|
||||
DIM (0, 10);
|
||||
|
|
@ -961,13 +973,6 @@ void HU_Ticker(void)
|
|||
if (cechotimer)
|
||||
cechotimer--;
|
||||
|
||||
if (tcechotimer)
|
||||
{
|
||||
tcechotimer++;
|
||||
if (tcechotimer > tcechoduration)
|
||||
tcechotimer = 0;
|
||||
}
|
||||
|
||||
if (gamestate != GS_LEVEL)
|
||||
{
|
||||
return;
|
||||
|
|
@ -1829,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;
|
||||
|
||||
|
|
@ -1842,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)
|
||||
|
|
@ -1856,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 ofs;
|
||||
INT32 timer = (INT32)(elapsed - timeroffset);
|
||||
|
||||
if (timer <= 0)
|
||||
return; // we don't care.
|
||||
|
|
@ -1874,10 +1915,10 @@ static void HU_DrawTitlecardCEcho(void)
|
|||
|
||||
*line = '\0';
|
||||
|
||||
w = V_TitleCardStringWidth(echoptr);
|
||||
V_DrawTitleCardString(BASEVIDWIDTH/2 -w/2, y, echoptr, 0, false, timer, TICRATE*4);
|
||||
ofs = V_CenteredTitleCardStringOffset(echoptr, p4);
|
||||
V_DrawTitleCardString(x - ofs, y, echoptr, 0, false, timer, TICRATE*4, p4);
|
||||
|
||||
y += 32;
|
||||
y += p4 ? 18 : 32;
|
||||
|
||||
// offset the timer for the next line.
|
||||
timeroffset += strlen(echoptr);
|
||||
|
|
@ -2038,8 +2079,22 @@ drawontop:
|
|||
if (cechotimer)
|
||||
HU_DrawCEcho();
|
||||
|
||||
if (tcechotimer)
|
||||
HU_DrawTitlecardCEcho();
|
||||
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 = 1; i < NUM_TCECHO_STATES; ++i)
|
||||
{
|
||||
HU_DrawTitlecardCEcho(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
|
|
@ -2576,17 +2631,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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,6 +77,9 @@ enum
|
|||
X (GTOL),
|
||||
X (GTFN),
|
||||
|
||||
X (GTOL4),
|
||||
X (GTFN4),
|
||||
|
||||
X (TALLNUM),
|
||||
X (NIGHTSNUM),
|
||||
X (PINGNUM),
|
||||
|
|
@ -163,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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -3515,8 +3515,11 @@ 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -8245,8 +8245,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;
|
||||
|
|
@ -8254,6 +8263,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
}
|
||||
else if (skipstats == 1)
|
||||
{
|
||||
// MapWarp
|
||||
if (ranspecialwipe != 2)
|
||||
S_StartSound(NULL, sfx_s3k73);
|
||||
levelfadecol = 0;
|
||||
|
|
@ -8261,11 +8271,13 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
}
|
||||
else if (encoremode)
|
||||
{
|
||||
// Encore
|
||||
levelfadecol = 0;
|
||||
wipetype = wipe_encore_towhite;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default
|
||||
levelfadecol = 31;
|
||||
}
|
||||
|
||||
|
|
|
|||
12
src/p_spec.c
12
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);
|
||||
|
|
@ -2053,6 +2061,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
11
src/p_user.c
11
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))
|
||||
{
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
@ -1407,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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
165
src/v_video.cpp
165
src/v_video.cpp
|
|
@ -1852,50 +1852,155 @@ 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)
|
||||
template <bool Centered>
|
||||
static INT32 Internal_TitleCardStringOffset(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;
|
||||
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);
|
||||
}
|
||||
|
||||
c = *ch;
|
||||
c = toupper(c);
|
||||
c -= LT_FONTSTART;
|
||||
return true;
|
||||
};
|
||||
|
||||
// check if character exists, if not, it's a space.
|
||||
if (c < 0 || c >= LT_FONTSIZE || !fontv[GTOL_FONT].font[(INT32)c])
|
||||
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:
|
||||
// - Check patch width directly for monospace or
|
||||
// punctuation that isn't necessarily thin.
|
||||
// - Apply to all centered string drawing.
|
||||
if constexpr (Centered)
|
||||
{
|
||||
xoffs += 10;
|
||||
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;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
scan([](int c) { return c; });
|
||||
}
|
||||
|
||||
pp = fontv[GTFN_FONT].font[(INT32)c];
|
||||
|
||||
xoffs += pp->width-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<false>(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<true>(str, p4);
|
||||
}
|
||||
|
||||
// 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 +2021,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 +2038,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 +2049,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 +2109,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -347,10 +347,13 @@ 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);
|
||||
|
||||
// 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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue