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; paused = false;
demo.playback = false; demo.playback = false;
demo.title = false; demo.title = false;
titlemapinaction = TITLEMAP_OFF; titlemapinaction = false;
automapactive = false; automapactive = false;
// load a base level // load a base level

View file

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

View file

@ -2990,6 +2990,14 @@ void readwipes(MYFILE *f)
else if (fastcmp(pword, "FINAL")) else if (fastcmp(pword, "FINAL"))
wipeoffset = wipe_gameend_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)) else if (fastncmp(word, "ENCORE_", 7))
{ {
pword = word + 7; pword = word + 7;

View file

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

View file

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

View file

@ -64,6 +64,7 @@ UINT8 wipedefs[NUMWIPEDEFS] = {
99, // wipe_credits_toblack 99, // wipe_credits_toblack
0, // wipe_evaluation_toblack 0, // wipe_evaluation_toblack
0, // wipe_gameend_toblack 0, // wipe_gameend_toblack
0, // wipe_ceremony_toblack
UINT8_MAX, // wipe_intro_toblack (hardcoded) UINT8_MAX, // wipe_intro_toblack (hardcoded)
99, // wipe_ending_toblack (hardcoded) 99, // wipe_ending_toblack (hardcoded)
99, // wipe_cutscene_toblack (hardcoded) 99, // wipe_cutscene_toblack (hardcoded)
@ -80,6 +81,7 @@ UINT8 wipedefs[NUMWIPEDEFS] = {
99, // wipe_credits_final 99, // wipe_credits_final
0, // wipe_evaluation_final 0, // wipe_evaluation_final
0, // wipe_gameend_final 0, // wipe_gameend_final
0, // wipe_ceremony_final
99, // wipe_intro_final (hardcoded) 99, // wipe_intro_final (hardcoded)
99, // wipe_ending_final (hardcoded) 99, // wipe_ending_final (hardcoded)
99 // wipe_cutscene_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; boolean doAutomate = false;
INT32 i; INT32 i;
@ -1471,27 +1471,27 @@ void G_DoLoadLevel(boolean resetplayer)
Y_EndVote(); Y_EndVote();
// cleanup // 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) if (gamemap < 1 || gamemap > nummapheaders)
{ {
G_SetGamestate(GS_TITLESCREEN);
titlemapinaction = false;
Z_Free(titlemap); Z_Free(titlemap);
titlemap = NULL; // let's not infinite recursion ok titlemap = NULL; // let's not infinite recursion ok
Command_ExitGame_f(); Command_ExitGame_f();
return; return;
} }
titlemapinaction = TITLEMAP_RUNNING;
} }
else
titlemapinaction = TITLEMAP_OFF;
// Doing this matches HOSTMOD behavior. // Doing this matches HOSTMOD behavior.
// Is that desired? IDK // 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) if (wipegamestate == GS_MENU)
M_ClearMenus(true); M_ClearMenus(true);
I_UpdateMouseGrab(); 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. // Start the title card.
// //
@ -1566,7 +1571,7 @@ void G_StartTitleCard(void)
} }
// start the title card // start the title card
WipeStageTitle = (!titlemapinaction); WipeStageTitle = (gamestate == GS_LEVEL);
} }
// //
@ -2168,7 +2173,6 @@ void G_Ticker(boolean run)
F_TextPromptTicker(); F_TextPromptTicker();
AM_Ticker(); AM_Ticker();
HU_Ticker(); HU_Ticker();
break; break;
case GS_INTERMISSION: case GS_INTERMISSION:
@ -5340,6 +5344,22 @@ void G_SetGamestate(gamestate_t newstate)
#endif #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 /* These functions handle the exitgame flag. Before, when the user
chose to end a game, it happened immediately, which could cause chose to end a game, it happened immediately, which could cause
crashes if the game was in the middle of something. Now, a flag 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)); 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 // A normal game starts at map 1, but a warp test can start elsewhere
void G_DeferedInitNew(boolean pencoremode, INT32 map, INT32 pickedchar, void G_DeferedInitNew(boolean pencoremode, INT32 map, INT32 pickedchar,
UINT8 ssplayers, boolean FLS); UINT8 ssplayers, boolean FLS);
void G_DoLoadLevelEx(boolean resetplayer, gamestate_t newstate);
void G_DoLoadLevel(boolean resetplayer); void G_DoLoadLevel(boolean resetplayer);
void G_StartTitleCard(void); void G_StartTitleCard(void);
@ -250,8 +251,6 @@ void G_LoadGameSettings(void);
void G_SetGameModified(boolean silent, boolean major); void G_SetGameModified(boolean silent, boolean major);
void G_SetUsedCheats(void); void G_SetUsedCheats(void);
void G_SetGamestate(gamestate_t newstate);
// Gamedata record shit // Gamedata record shit
void G_AllocMainRecordData(INT16 i); void G_AllocMainRecordData(INT16 i);
void G_ClearRecords(void); void G_ClearRecords(void);

View file

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

View file

@ -1333,7 +1333,9 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
// Remove any existing controls // Remove any existing controls
memset(cmd, 0, sizeof(ticcmd_t)); 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. // Not in the level.
return; return;

View file

@ -53,21 +53,7 @@
boolean K_PodiumSequence(void) boolean K_PodiumSequence(void)
{ {
INT32 podiumMapNum = nummapheaders; return (gamestate == GS_CEREMONY);
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;
} }
boolean K_IsDuelItem(mobjtype_t type) 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); lua_pushstring(L, titlemap);
return 1; return 1;
} else if (fastcmp(word,"titlemapinaction")) { } else if (fastcmp(word,"titlemapinaction")) {
lua_pushboolean(L, (titlemapinaction != TITLEMAP_OFF)); lua_pushboolean(L, titlemapinaction);
return 1; return 1;
} else if (fastcmp(word,"bootmap")) { } else if (fastcmp(word,"bootmap")) {
lua_pushstring(L, bootmap); lua_pushstring(L, bootmap);

View file

@ -139,7 +139,7 @@ void COM_Lua_f(void);
// #define HAVE_LUA_SEGS // #define HAVE_LUA_SEGS
#define ISINLEVEL \ #define ISINLEVEL \
(gamestate == GS_LEVEL || titlemapinaction) (G_GamestateUsesLevel())
#define INLEVEL if (! ISINLEVEL)\ #define INLEVEL if (! ISINLEVEL)\
return luaL_error(L, "This can only be used in a level!"); 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}; perfstatcol_t batchcalls_col = {220, 200, V_PURPLEMAP, batchcalls_row};
boolean rendering = ( boolean rendering = G_GamestateUsesLevel();
gamestate == GS_LEVEL ||
(gamestate == GS_TITLESCREEN && titlemapinaction)
);
draw_row = 10; draw_row = 10;
M_DrawPerfTiming(&frametime_col); M_DrawPerfTiming(&frametime_col);
@ -619,8 +616,9 @@ void M_DrawPerfStats(void)
} }
else if (cv_perfstats.value == PS_THINKFRAME) // lua thinkframe else if (cv_perfstats.value == PS_THINKFRAME) // lua thinkframe
{ {
if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction))) if (G_GamestateUsesLevel() == false)
return; return;
if (vid.width < 640 || vid.height < 400) // low resolution if (vid.width < 640 || vid.height < 400) // low resolution
{ {
// it's not gonna fit very well.. // 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 // Start recording replay in multiplayer with a temp filename
//@TODO I'd like to fix dedis crashing when recording replays for the future too... //@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 buf[MAX_WADPATH];
char ver[128]; 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. // 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. // 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( S_FadeMusic(0, FixedMul(
FixedDiv((F_GetWipeLength(wipedefs[wipe_level_toblack])-2)*NEWTICRATERATIO, NEWTICRATE), MUSICRATE)); 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) if (rendermode != render_none)
V_ReloadPalette(); // Set the level palette V_ReloadPalette(); // Set the level palette
if (!(reloadinggamestate || titlemapinaction)) if (!(reloadinggamestate || gamestate != GS_LEVEL))
{ {
if (ranspecialwipe == 2) 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); 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 // Close text prompt before freeing the old level
F_EndTextPrompt(false, true); 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 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... // 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? if (!lastmaploaded) // Start a new game?
{ {