Split G_ExitLevel into G_BeginLevelExit and G_FinishExitLevel

- Save retry condition in G_BeginLevelExit
- Apply condition in G_FinishExitLevel

Preparation for ACS level end scripts, since the exit
condition will need be known when the countdown starts,
not when it ends (that'd be too late to do anything in the
level).
This commit is contained in:
James R 2023-08-15 16:40:00 -07:00
parent 07aabdfdb3
commit 8a72f42818
12 changed files with 126 additions and 91 deletions

View file

@ -1802,6 +1802,7 @@ bool CallFunc_MapWarp(ACSVM::Thread *thread, const ACSVM::Word *argV, ACSVM::Wor
if (argV[1] == 0)
skipstats = 1;
G_BeginLevelExit();
exitcountdown = 1;
if (server)

View file

@ -5776,7 +5776,7 @@ static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum)
if (G_GamestateUsesExitLevel() == false)
return;
G_ExitLevel();
G_FinishExitLevel();
}
static void Got_SetupVotecmd(UINT8 **cp, INT32 playernum)

View file

@ -762,8 +762,15 @@ extern UINT8 maxXtraLife; // Max extra lives from rings
extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations
struct exitcondition_t
{
boolean losing;
boolean retry;
};
// For racing
extern tic_t racecountdown, exitcountdown, musiccountdown;
extern exitcondition_t g_exit;
#define DEFAULT_GRAVITY (4*FRACUNIT/5)
extern fixed_t gravity;

View file

@ -4161,7 +4161,7 @@ boolean G_CheckDemoStatus(void)
I_Quit();
if (multiplayer && !demo.title)
G_ExitLevel();
G_FinishExitLevel();
else
{
G_StopDemo();

View file

@ -274,6 +274,7 @@ mobj_t *hunt2;
mobj_t *hunt3;
tic_t racecountdown, exitcountdown, musiccountdown; // for racing
exitcondition_t g_exit;
fixed_t gravity;
fixed_t mapobjectscale;
@ -2927,95 +2928,108 @@ void G_AddPlayer(INT32 playernum)
demo_extradata[playernum] |= DXD_JOINDATA|DXD_PLAYSTATE|DXD_COLOR|DXD_NAME|DXD_SKIN|DXD_FOLLOWER; // Set everything
}
void G_ExitLevel(void)
void G_BeginLevelExit(void)
{
g_exit.losing = true;
g_exit.retry = false;
if (grandprixinfo.gp == true)
{
UINT8 i;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && !players[i].spectator)
{
K_PlayerFinishGrandPrix(&players[i]);
}
}
}
if (!G_GametypeUsesLives() || skipstats != 0)
{
g_exit.losing = false; // never force a retry
}
else if (specialstageinfo.valid == true || (gametyperules & GTR_BOSS))
{
UINT8 i;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && !players[i].spectator && !players[i].bot)
{
if (!K_IsPlayerLosing(&players[i]))
{
g_exit.losing = false;
break;
}
}
}
}
else if (grandprixinfo.gp == true && grandprixinfo.eventmode == GPEVENT_NONE)
{
g_exit.losing = (grandprixinfo.wonround != true);
}
if (g_exit.losing)
{
// You didn't win...
UINT8 i;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && !players[i].spectator && !players[i].bot)
{
if (players[i].lives > 0)
{
g_exit.retry = true;
break;
}
}
}
}
if (g_exit.losing && specialstageinfo.valid)
{
exitcountdown = TICRATE;
}
else
{
exitcountdown = raceexittime+1;
}
}
void G_FinishExitLevel(void)
{
G_ResetAllDeviceRumbles();
if (gamestate == GS_LEVEL)
{
UINT8 i;
boolean doretry = false;
if (grandprixinfo.gp == true)
if (g_exit.retry)
{
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && !players[i].spectator)
{
K_PlayerFinishGrandPrix(&players[i]);
}
}
}
if (!G_GametypeUsesLives() || skipstats != 0)
; // never force a retry
else if (specialstageinfo.valid == true || (gametyperules & GTR_BOSS))
{
doretry = true;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && !players[i].spectator && !players[i].bot)
{
if (!K_IsPlayerLosing(&players[i]))
{
doretry = false;
break;
}
}
}
}
else if (grandprixinfo.gp == true && grandprixinfo.eventmode == GPEVENT_NONE)
{
doretry = (grandprixinfo.wonround != true);
}
if (doretry)
{
// You didn't win...
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && !players[i].spectator && !players[i].bot)
{
if (players[i].lives > 0)
{
break;
}
}
}
if (i == MAXPLAYERS)
{
// GAME OVER, try again from the start!
if (grandprixinfo.gp == true
&& grandprixinfo.eventmode == GPEVENT_SPECIAL)
{
// We were in a Special Stage.
// We can still progress to the podium when we game over here.
doretry = false;
}
else if (netgame)
{
; // Restart cup here whenever we do Online GP
}
else
{
// Back to the menu with you.
G_HandleSaveLevel(true);
D_QuitNetGame();
CL_Reset();
D_ClearState();
M_StartControlPanel();
}
}
else
// Restart cup here whenever we do Online GP
if (!netgame)
{
// We have lives, just redo this one course.
G_SetRetryFlag();
return;
}
}
else if (g_exit.losing)
{
// We were in a Special Stage.
// We can still progress to the podium when we game over here.
const boolean special = grandprixinfo.gp == true && grandprixinfo.eventmode == GPEVENT_SPECIAL;
if (doretry == true)
if (!netgame && !special)
{
// Back to the menu with you.
G_HandleSaveLevel(true);
D_QuitNetGame();
CL_Reset();
D_ClearState();
M_StartControlPanel();
return;
}
}

View file

@ -206,7 +206,8 @@ boolean G_GametypeUsesLives(void);
boolean G_GametypeHasTeams(void);
boolean G_GametypeHasSpectators(void);
INT16 G_SometimesGetDifferentEncore(void);
void G_ExitLevel(void);
void G_BeginLevelExit(void);
void G_FinishExitLevel(void);
void G_NextLevel(void);
void G_GetNextMap(void);
void G_Continue(void);

View file

@ -844,6 +844,12 @@ boolean K_CanChangeRules(boolean allowdemos)
--------------------------------------------------*/
void K_PlayerFinishGrandPrix(player_t *player)
{
if (grandprixinfo.wonround == true)
{
// This was already completed.
return;
}
if (player->exiting == false)
{
// You did not finish

View file

@ -2869,7 +2869,8 @@ static int lib_gExitLevel(lua_State *L)
// Moved this bit to G_SetCustomExitVars
if (n >= 1) // Don't run the reset to defaults option
lib_gSetCustomExitVars(L);
G_ExitLevel();
G_BeginLevelExit();
G_FinishExitLevel();
return 0;
}

View file

@ -5731,6 +5731,10 @@ static void P_NetArchiveMisc(savebuffer_t *save, boolean resending)
WRITEUINT32(save->p, racecountdown);
WRITEUINT32(save->p, exitcountdown);
// exitcondition_t
WRITEUINT8(save->p, g_exit.losing);
WRITEUINT8(save->p, g_exit.retry);
WRITEFIXED(save->p, gravity);
WRITEFIXED(save->p, mapobjectscale);
@ -5906,6 +5910,10 @@ static boolean P_NetUnArchiveMisc(savebuffer_t *save, boolean reloading)
racecountdown = READUINT32(save->p);
exitcountdown = READUINT32(save->p);
// exitcondition_t
g_exit.losing = READUINT8(save->p);
g_exit.retry = READUINT8(save->p);
gravity = READFIXED(save->p);
mapobjectscale = READFIXED(save->p);

View file

@ -7505,6 +7505,9 @@ static void P_InitLevelSettings(void)
racecountdown = exitcountdown = musiccountdown = exitfadestarted = 0;
curlap = bestlap = 0; // SRB2Kart
g_exit.losing = false;
g_exit.retry = false;
// Gamespeed and frantic items
gamespeed = KARTSPEED_EASY;
franticitems = false;

View file

@ -1318,19 +1318,12 @@ void P_DoPlayerExit(player_t *player, pflags_t flags)
if (P_CheckRacers() && !exitcountdown)
{
if (specialout == true)
{
exitcountdown = TICRATE;
}
else
{
exitcountdown = raceexittime+1;
}
G_BeginLevelExit();
}
}
else if (!exitcountdown) // All other gametypes
{
exitcountdown = raceexittime+1;
G_BeginLevelExit();
}
if (grandprixinfo.gp == true && player->bot == false && losing == false)
@ -3777,7 +3770,7 @@ void P_DoTimeOver(player_t *player)
if (!exitcountdown)
{
exitcountdown = raceexittime;
G_BeginLevelExit();
}
}

View file

@ -134,6 +134,7 @@ TYPEDEF (unloaded_mapheader_t);
TYPEDEF (tolinfo_t);
TYPEDEF (cupheader_t);
TYPEDEF (unloaded_cupheader_t);
TYPEDEF (exitcondition_t);
// font.h
TYPEDEF (font_t);