Fixes for CEREMONY gamestate

- Made titlemap + ceremony code more straight-forward by being able to set gamestate in G_DoLoadLevel directly
- Demos are only recorded on GS_LEVEL (fixes crash for ceremony + titlemaps)
- Added G_GamestateUsesLevel to encapsulate all checks for using level rendering
- Added GS_CEREMONY to wipedefs
- K_PodiumSequence just checks for GS_CEREMONY now (optimization)

The game can now properly go to the podium after GP
This commit is contained in:
Sally Coolatta 2023-02-25 12:32:36 -05:00
parent 7760d6688b
commit f78b3f7794
15 changed files with 95 additions and 65 deletions

View file

@ -1272,7 +1272,7 @@ static void CL_LoadReceivedSavegame(boolean reloading)
paused = false;
demo.playback = false;
demo.title = false;
titlemapinaction = TITLEMAP_OFF;
titlemapinaction = false;
automapactive = false;
// load a base level

View file

@ -337,8 +337,8 @@ static void D_Display(void)
if (rendermode != render_none)
{
// Fade to black first
if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)) // fades to black on its own timing, always
&& wipetypepre != UINT8_MAX)
if (G_GamestateUsesLevel() == false // fades to black on its own timing, always
&& wipetypepre != UINT8_MAX)
{
F_WipeStartScreen();
F_WipeColorFill(31);
@ -464,7 +464,7 @@ static void D_Display(void)
// clean up border stuff
// see if the border needs to be initially drawn
if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction && curbghide && (!hidetitlemap)))
if (G_GamestateUsesLevel() == true || (gamestate == GS_TITLESCREEN && titlemapinaction && curbghide && (!hidetitlemap)))
{
if (!automapactive && !dedicated && cv_renderview.value)
{
@ -560,14 +560,25 @@ static void D_Display(void)
ps_uitime = I_GetPreciseTime();
if (gamestate == GS_LEVEL)
switch (gamestate)
{
ST_Drawer();
F_TextPromptDrawer();
HU_Drawer();
case GS_LEVEL:
{
ST_Drawer();
F_TextPromptDrawer();
HU_Drawer();
break;
}
case GS_TITLESCREEN:
{
F_TitleScreenDrawer();
break;
}
default:
{
break;
}
}
else
F_TitleScreenDrawer();
}
else
{
@ -577,7 +588,7 @@ static void D_Display(void)
// change gamma if needed
// (GS_LEVEL handles this already due to level-specific palettes)
if (forcerefresh && !(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)))
if (forcerefresh && G_GamestateUsesLevel() == false)
V_SetPalette(0);
// draw pause pic

View file

@ -2990,6 +2990,14 @@ void readwipes(MYFILE *f)
else if (fastcmp(pword, "FINAL"))
wipeoffset = wipe_gameend_final;
}
else if (fastncmp(word, "CEREMONY_", 9))
{
pword = word + 9;
if (fastcmp(pword, "TOBLACK"))
wipeoffset = wipe_ceremony_toblack;
else if (fastcmp(pword, "FINAL"))
wipeoffset = wipe_ceremony_final;
}
else if (fastncmp(word, "ENCORE_", 7))
{
pword = word + 7;

View file

@ -50,7 +50,7 @@
INT32 finalecount;
INT32 titlescrollxspeed = 16;
INT32 titlescrollyspeed = 0;
UINT8 titlemapinaction = TITLEMAP_OFF;
boolean titlemapinaction = false;
static INT32 timetonext; // Delay between screen changes
@ -1835,14 +1835,14 @@ void F_StartTitleScreen(void)
mapthing_t *startpos;
gamestate_t prevwipegamestate = wipegamestate;
titlemapinaction = TITLEMAP_LOADING;
titlemapinaction = true;
titlemapcameraref = NULL;
gamemap = titleMapNum+1;
maptol = mapheaderinfo[titleMapNum]->typeoflevel;
globalweather = mapheaderinfo[titleMapNum]->weather;
G_DoLoadLevel(true);
G_DoLoadLevelEx(true, GS_TITLESCREEN);
if (!titlemap)
return;
@ -1878,13 +1878,12 @@ void F_StartTitleScreen(void)
}
else
{
titlemapinaction = TITLEMAP_OFF;
G_SetGamestate(GS_TITLESCREEN);
titlemapinaction = false;
gamemap = 1; // g_game.c
CON_ClearHUD();
}
G_SetGamestate(GS_TITLESCREEN);
// IWAD dependent stuff.
animtimer = skullAnimCounter = 0;
@ -3149,9 +3148,7 @@ boolean F_StartCeremony(void)
maptol = mapheaderinfo[gamemap-1]->typeoflevel;
globalweather = mapheaderinfo[gamemap-1]->weather;
G_DoLoadLevel(false);
G_SetGamestate(GS_CEREMONY);
G_DoLoadLevelEx(false, GS_CEREMONY);
return true;
}

View file

@ -185,6 +185,7 @@ enum
wipe_credits_toblack,
wipe_evaluation_toblack,
wipe_gameend_toblack,
wipe_ceremony_toblack,
wipe_intro_toblack,
wipe_ending_toblack,
wipe_cutscene_toblack,
@ -203,6 +204,7 @@ enum
wipe_credits_final,
wipe_evaluation_final,
wipe_gameend_final,
wipe_ceremony_final,
wipe_intro_final,
wipe_ending_final,
wipe_cutscene_final,

View file

@ -64,6 +64,7 @@ UINT8 wipedefs[NUMWIPEDEFS] = {
99, // wipe_credits_toblack
0, // wipe_evaluation_toblack
0, // wipe_gameend_toblack
0, // wipe_ceremony_toblack
UINT8_MAX, // wipe_intro_toblack (hardcoded)
99, // wipe_ending_toblack (hardcoded)
99, // wipe_cutscene_toblack (hardcoded)
@ -80,6 +81,7 @@ UINT8 wipedefs[NUMWIPEDEFS] = {
99, // wipe_credits_final
0, // wipe_evaluation_final
0, // wipe_gameend_final
0, // wipe_ceremony_final
99, // wipe_intro_final (hardcoded)
99, // wipe_ending_final (hardcoded)
99 // wipe_cutscene_final (hardcoded)

View file

@ -1442,9 +1442,9 @@ static void weaponPrefChange4(void)
}
//
// G_DoLoadLevel
// G_DoLoadLevelEx
//
void G_DoLoadLevel(boolean resetplayer)
void G_DoLoadLevelEx(boolean resetplayer, gamestate_t newstate)
{
boolean doAutomate = false;
INT32 i;
@ -1471,27 +1471,27 @@ void G_DoLoadLevel(boolean resetplayer)
Y_EndVote();
// cleanup
if (titlemapinaction == TITLEMAP_LOADING)
// Is this actually necessary? Doesn't F_StartTitleScreen already do a significantly more comprehensive check?
if (newstate == GS_TITLESCREEN)
{
//if (W_CheckNumForName(G_BuildMapName(gamemap)) == LUMPERROR)
if (gamemap < 1 || gamemap > nummapheaders)
{
G_SetGamestate(GS_TITLESCREEN);
titlemapinaction = false;
Z_Free(titlemap);
titlemap = NULL; // let's not infinite recursion ok
Command_ExitGame_f();
return;
}
titlemapinaction = TITLEMAP_RUNNING;
}
else
titlemapinaction = TITLEMAP_OFF;
// Doing this matches HOSTMOD behavior.
// Is that desired? IDK
doAutomate = (gamestate != GS_LEVEL);
doAutomate = (gamestate != GS_LEVEL && newstate == GS_LEVEL);
G_SetGamestate(GS_LEVEL);
G_SetGamestate(newstate);
if (wipegamestate == GS_MENU)
M_ClearMenus(true);
I_UpdateMouseGrab();
@ -1536,6 +1536,11 @@ void G_DoLoadLevel(boolean resetplayer)
}
}
void G_DoLoadLevel(boolean resetplayer)
{
G_DoLoadLevelEx(resetplayer, GS_LEVEL);
}
//
// Start the title card.
//
@ -1566,7 +1571,7 @@ void G_StartTitleCard(void)
}
// start the title card
WipeStageTitle = (!titlemapinaction);
WipeStageTitle = (gamestate == GS_LEVEL);
}
//
@ -2168,7 +2173,6 @@ void G_Ticker(boolean run)
F_TextPromptTicker();
AM_Ticker();
HU_Ticker();
break;
case GS_INTERMISSION:
@ -5340,6 +5344,22 @@ void G_SetGamestate(gamestate_t newstate)
#endif
}
boolean G_GamestateUsesLevel(void)
{
switch (gamestate)
{
case GS_TITLESCREEN:
return titlemapinaction;
case GS_LEVEL:
case GS_CEREMONY:
return true;
default:
return false;
}
}
/* These functions handle the exitgame flag. Before, when the user
chose to end a game, it happened immediately, which could cause
crashes if the game was in the middle of something. Now, a flag
@ -5423,4 +5443,3 @@ INT32 G_TicsToMilliseconds(tic_t tics)
{
return (INT32)((tics%TICRATE) * (1000.00f/TICRATE));
}

View file

@ -164,6 +164,7 @@ void G_SpawnPlayer(INT32 playernum);
// A normal game starts at map 1, but a warp test can start elsewhere
void G_DeferedInitNew(boolean pencoremode, INT32 map, INT32 pickedchar,
UINT8 ssplayers, boolean FLS);
void G_DoLoadLevelEx(boolean resetplayer, gamestate_t newstate);
void G_DoLoadLevel(boolean resetplayer);
void G_StartTitleCard(void);
@ -250,8 +251,6 @@ void G_LoadGameSettings(void);
void G_SetGameModified(boolean silent, boolean major);
void G_SetUsedCheats(void);
void G_SetGamestate(gamestate_t newstate);
// Gamedata record shit
void G_AllocMainRecordData(INT16 i);
void G_ClearRecords(void);

View file

@ -59,10 +59,13 @@ typedef enum
} gameaction_t;
extern gamestate_t gamestate;
extern UINT8 titlemapinaction;
extern boolean titlemapinaction;
extern UINT8 ultimatemode; // was sk_insane
extern gameaction_t gameaction;
void G_SetGamestate(gamestate_t newstate);
boolean G_GamestateUsesLevel(void);
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -1333,7 +1333,9 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
// Remove any existing controls
memset(cmd, 0, sizeof(ticcmd_t));
if (gamestate != GS_LEVEL || !player->mo || player->spectator)
if (player->mo == NULL
|| player->spectator == true
|| G_GamestateUsesLevel() == false)
{
// Not in the level.
return;

View file

@ -53,21 +53,7 @@
boolean K_PodiumSequence(void)
{
INT32 podiumMapNum = nummapheaders;
if (grandprixinfo.gp == false)
{
return false;
}
// FIXME: This function is used a lot during gameplay.
// Cache so we don't have to iterate all map headers every time.
if (podiummap && ((podiumMapNum = G_MapNumber(podiummap)) < nummapheaders))
{
return (gamemap == podiumMapNum+1);
}
return false;
return (gamestate == GS_CEREMONY);
}
boolean K_IsDuelItem(mobjtype_t type)

View file

@ -212,7 +212,7 @@ int LUA_PushGlobals(lua_State *L, const char *word)
lua_pushstring(L, titlemap);
return 1;
} else if (fastcmp(word,"titlemapinaction")) {
lua_pushboolean(L, (titlemapinaction != TITLEMAP_OFF));
lua_pushboolean(L, titlemapinaction);
return 1;
} else if (fastcmp(word,"bootmap")) {
lua_pushstring(L, bootmap);

View file

@ -139,7 +139,7 @@ void COM_Lua_f(void);
// #define HAVE_LUA_SEGS
#define ISINLEVEL \
(gamestate == GS_LEVEL || titlemapinaction)
(G_GamestateUsesLevel())
#define INLEVEL if (! ISINLEVEL)\
return luaL_error(L, "This can only be used in a level!");

View file

@ -255,10 +255,7 @@ static void M_DrawRenderStats(void)
perfstatcol_t batchcalls_col = {220, 200, V_PURPLEMAP, batchcalls_row};
boolean rendering = (
gamestate == GS_LEVEL ||
(gamestate == GS_TITLESCREEN && titlemapinaction)
);
boolean rendering = G_GamestateUsesLevel();
draw_row = 10;
M_DrawPerfTiming(&frametime_col);
@ -619,8 +616,9 @@ void M_DrawPerfStats(void)
}
else if (cv_perfstats.value == PS_THINKFRAME) // lua thinkframe
{
if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)))
if (G_GamestateUsesLevel() == false)
return;
if (vid.width < 640 || vid.height < 400) // low resolution
{
// it's not gonna fit very well..

View file

@ -7419,7 +7419,7 @@ static void P_InitGametype(void)
// Start recording replay in multiplayer with a temp filename
//@TODO I'd like to fix dedis crashing when recording replays for the future too...
if (!demo.playback && multiplayer && !dedicated)
if (gamestate == GS_LEVEL && !demo.playback && multiplayer && !dedicated)
{
char buf[MAX_WADPATH];
char ver[128];
@ -7697,7 +7697,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
// Fade out music here. Deduct 2 tics so the fade volume actually reaches 0.
// But don't halt the music! S_Start will take care of that. This dodges a MIDI crash bug.
if (!(reloadinggamestate || titlemapinaction))
if (!(reloadinggamestate || gamestate != GS_LEVEL))
S_FadeMusic(0, FixedMul(
FixedDiv((F_GetWipeLength(wipedefs[wipe_level_toblack])-2)*NEWTICRATERATIO, NEWTICRATE), MUSICRATE));
@ -7705,7 +7705,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
if (rendermode != render_none)
V_ReloadPalette(); // Set the level palette
if (!(reloadinggamestate || titlemapinaction))
if (!(reloadinggamestate || gamestate != GS_LEVEL))
{
if (ranspecialwipe == 2)
{
@ -7745,8 +7745,11 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
F_RunWipe(wipetype, wipedefs[wipetype], false, ((levelfadecol == 0) ? "FADEMAP1" : "FADEMAP0"), false, false);
}
/*if (!titlemapinaction)
wipegamestate = GS_LEVEL;*/
/*
if (!titlemapinaction)
wipegamestate = GS_LEVEL;
*/
// Close text prompt before freeing the old level
F_EndTextPrompt(false, true);
@ -7948,7 +7951,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
P_MapEnd(); // tm.thing is no longer needed from this point onwards
// Took me 3 hours to figure out why my progression kept on getting overwritten with the titlemap...
if (!titlemapinaction)
if (gamestate == GS_LEVEL)
{
if (!lastmaploaded) // Start a new game?
{