- route all game state changes through game actions.

This is to avoid problems with the main loop not calling Ticker and Render in sync.
This commit is contained in:
Christoph Oelckers 2020-09-05 15:43:34 +02:00
parent 7a5dca7d5d
commit c1786001b2
17 changed files with 57 additions and 94 deletions

View file

@ -254,7 +254,7 @@ void NewLevel(MapRecord *sng, int skill)
gSkill = skill; gSkill = skill;
cheatReset(); cheatReset();
StartLevel(sng); StartLevel(sng);
gamestate = GS_LEVEL; gameaction = ga_level;
}; };
bool startedCutscene = false; bool startedCutscene = false;
@ -485,7 +485,7 @@ void GameInterface::Startup()
if (!userConfig.nologo && gGameOptions.nGameType == 0) playlogos(); if (!userConfig.nologo && gGameOptions.nGameType == 0) playlogos();
else else
{ {
startmainmenu(); gameaction = ga_mainmenu;
} }
} }
} }

View file

@ -94,9 +94,7 @@ void playlogos()
jobs[job++] = { Create<DImageScreen>(2518, DScreenJob::fadein) }; jobs[job++] = { Create<DImageScreen>(2518, DScreenJob::fadein) };
RunScreenJob(jobs, job, [](bool) { RunScreenJob(jobs, job, [](bool) {
gamestate = GS_MENUSCREEN; gameaction = ga_mainmenu;
M_StartControlPanel(false);
M_SetMenu(NAME_Mainmenu);
}, true, true); }, true, true);
} }

View file

@ -506,7 +506,6 @@ bool GameInterface::LoadGame(FSaveGameNode* node)
viewSetErrorMessage(""); viewSetErrorMessage("");
Net_ClearFifo(); Net_ClearFifo();
paused = 0; paused = 0;
gamestate = GS_LEVEL;
bVanilla = false; bVanilla = false;

View file

@ -1179,15 +1179,6 @@ CCMD(taunt)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void startmainmenu()
{
gamestate = GS_MENUSCREEN;
M_StartControlPanel(false);
M_SetMenu(NAME_Mainmenu);
FX_StopAllSounds();
}
void GameInterface::FreeLevelData() void GameInterface::FreeLevelData()
{ {
// Make sure that there is no more level to toy around with. // Make sure that there is no more level to toy around with.

View file

@ -55,7 +55,6 @@ extern FStringCVar* const CombatMacros[];
void CONFIG_ReadCombatMacros(); void CONFIG_ReadCombatMacros();
int GameMain(); int GameMain();
void startmainmenu();
int GetAutomapZoom(int gZoom); int GetAutomapZoom(int gZoom);
void DrawCrosshair(int deftile, int health, double xdelta, double scale, PalEntry color = 0xffffffff); void DrawCrosshair(int deftile, int health, double xdelta, double scale, PalEntry color = 0xffffffff);
void updatePauseStatus(); void updatePauseStatus();

View file

@ -24,8 +24,13 @@ enum gamestate_t : int
enum gameaction_t : int enum gameaction_t : int
{ {
ga_nothing, ga_nothing,
ga_level, // Switch to play mode without any initialization
ga_intro,
ga_intermission,
ga_startup, // go back to intro after uninitializing the game state ga_startup, // go back to intro after uninitializing the game state
ga_mainmenu, // go back to main menu after uninitializing the game state ga_mainmenu, // go back to main menu after uninitializing the game state
ga_mainmenunostopsound, // Same but doesn't stop playing sounds.
ga_creditsmenu, // go to the credits menu after uninitializing the game state ga_creditsmenu, // go to the credits menu after uninitializing the game state
ga_newgame, // start a new game ga_newgame, // start a new game
ga_recordgame, // start a new demo recording (later) ga_recordgame, // start a new demo recording (later)

View file

@ -140,6 +140,7 @@ static void GameTicker()
FX_SetReverb(0); FX_SetReverb(0);
gi->FreeLevelData(); gi->FreeLevelData();
C_ClearMessages(); C_ClearMessages();
gameaction = ga_level;
gi->NewGame(g_nextmap, -1); gi->NewGame(g_nextmap, -1);
break; break;
@ -150,16 +151,19 @@ static void GameTicker()
{ {
// if the same level is restarted, skip any progression stuff like summary screens or cutscenes. // if the same level is restarted, skip any progression stuff like summary screens or cutscenes.
gi->FreeLevelData(); gi->FreeLevelData();
gamestate = GS_LEVEL; gameaction = ga_level;
gi->NextLevel(g_nextmap, g_nextskill); gi->NextLevel(g_nextmap, g_nextskill);
} }
else else
{
gi->LevelCompleted(g_nextmap, g_nextskill); gi->LevelCompleted(g_nextmap, g_nextskill);
assert(gameaction != ga_nothing);
}
break; break;
case ga_nextlevel: case ga_nextlevel:
gi->FreeLevelData(); gi->FreeLevelData();
gamestate = GS_LEVEL; gameaction = ga_level;
gi->NextLevel(g_nextmap, g_nextskill); gi->NextLevel(g_nextmap, g_nextskill);
break; break;
@ -168,23 +172,32 @@ static void GameTicker()
FX_SetReverb(0); FX_SetReverb(0);
gi->FreeLevelData(); gi->FreeLevelData();
C_ClearMessages(); C_ClearMessages();
gamestate = GS_LEVEL; gameaction = ga_level;
gi->NewGame(g_nextmap, g_nextskill); gi->NewGame(g_nextmap, g_nextskill);
break; break;
case ga_startup: case ga_startup:
Mus_Stop();
FX_StopAllSounds();
gi->FreeLevelData(); gi->FreeLevelData();
gamestate = GS_STARTUP; gamestate = GS_STARTUP;
break; break;
case ga_mainmenu: case ga_mainmenu:
FX_StopAllSounds();
case ga_mainmenunostopsound:
gi->FreeLevelData(); gi->FreeLevelData();
startmainmenu(); gamestate = GS_MENUSCREEN;
M_StartControlPanel(false);
M_SetMenu(NAME_Mainmenu);
break; break;
case ga_creditsmenu: case ga_creditsmenu:
FX_StopAllSounds();
gi->FreeLevelData(); gi->FreeLevelData();
startmainmenu(); gamestate = GS_MENUSCREEN;
M_StartControlPanel(false);
M_SetMenu(NAME_Mainmenu);
M_SetMenu(NAME_CreditsMenu); M_SetMenu(NAME_CreditsMenu);
break; break;
@ -194,7 +207,19 @@ static void GameTicker()
break; break;
case ga_autosave: case ga_autosave:
M_Autosave(); if (gamestate == GS_LEVEL) M_Autosave();
break;
case ga_level:
gamestate = GS_LEVEL;
break;
case ga_intro:
gamestate = GS_INTRO;
break;
case ga_intermission:
gamestate = GS_INTERMISSION;
break; break;
// for later // for later

View file

@ -66,7 +66,7 @@ void FSavegameManager::LoadGame(FSaveGameNode* node)
{ {
if (gi->LoadGame(node)) if (gi->LoadGame(node))
{ {
gamestate = GS_LEVEL; gameaction = ga_level;
} }
else else
{ {

View file

@ -729,7 +729,11 @@ void RunScreenJob(JobDesc* jobs, int count, CompletionFunc completion, bool clea
if (count) if (count)
{ {
runner = new ScreenJobRunner(jobs, count, completion, clearbefore); runner = new ScreenJobRunner(jobs, count, completion, clearbefore);
gamestate = blockingui? GS_INTRO : GS_INTERMISSION; gameaction = blockingui? ga_intro : ga_intermission;
}
else
{
completion(false);
} }
} }

View file

@ -1283,7 +1283,7 @@ void DoGameOverScene(bool finallevel)
PlayGameOverSound(); PlayGameOverSound();
job = { Create<DImageScreen>(tileGetTexture(kTile3591), DScreenJob::fadein | DScreenJob::fadeout, 0x7fffffff) }; job = { Create<DImageScreen>(tileGetTexture(kTile3591), DScreenJob::fadein | DScreenJob::fadeout, 0x7fffffff) };
} }
RunScreenJob(&job, 1, [](bool) { gamestate = GS_STARTUP; }); RunScreenJob(&job, 1, [](bool) { gameaction = ga_startup; });
} }

View file

@ -221,7 +221,7 @@ void GameInterface::NewGame(MapRecord *map, int skill)
void GameInterface::LevelCompleted(MapRecord *map, int skill) void GameInterface::LevelCompleted(MapRecord *map, int skill)
{ {
if (currentLevel->levelNumber == 0) startmainmenu(); if (currentLevel->levelNumber == 0) gameaction = ga_mainmenu;
else Intermission(currentLevel, map); else Intermission(currentLevel, map);
} }
@ -247,8 +247,8 @@ void GameInterface::Startup()
} }
else else
{ {
if (!userConfig.nologo) DoTitle([](bool) { startmainmenu(); }); if (!userConfig.nologo) DoTitle([](bool) { gameaction = ga_mainmenu; });
else startmainmenu(); else gameaction = ga_mainmenu;
} }
} }

View file

@ -640,56 +640,5 @@ void PrintLevelName_r(double alpha)
BigText(160, 114, currentLevel->DisplayName(), 0, alpha); BigText(160, 114, currentLevel->DisplayName(), 0, alpha);
} }
// Utility for testing the above screens
CCMD(testrscreen)
{
JobDesc jobs[10];
int job = 0;
C_HideConsole();
FX_StopAllSounds();
Mus_Stop();
auto gs = gamestate;
auto completion = [=](bool)
{
if (gs == GS_LEVEL || gs == GS_MENUSCREEN) gamestate = gs;
else gamestate = GS_STARTUP;
};
if (argv.argc() > 1)
{
int screen = strtol(argv[1], nullptr, 0);
switch (screen)
{
case 0:
case 1:
if (!isRRRA())
{
bonussequence_r(screen, jobs, job);
RunScreenJob(jobs, job, completion);
}
break;
case 2:
jobs[job++] = { Create<DRRMultiplayerBonusScreen>(6) };
RunScreenJob(jobs, job, completion);
break;
case 3:
jobs[job++] = { Create<DRRLevelSummaryScreen>() };
RunScreenJob(jobs, job, completion);
break;
case 4:
jobs[job++] = { Create<DRRRAEndOfGame>() };
RunScreenJob(jobs, job, completion);
break;
default:
break;
}
}
}
END_DUKE_NS END_DUKE_NS

View file

@ -133,8 +133,8 @@ void GameInterface::Startup()
} }
else else
{ {
if (!userConfig.nologo) fi.ShowLogo([](bool) { startmainmenu(); }); if (!userConfig.nologo) fi.ShowLogo([](bool) { gameaction = ga_mainmenu; });
else startmainmenu(); else gameaction = ga_mainmenu;
} }
} }

View file

@ -1017,7 +1017,7 @@ void startnewgame(MapRecord* map, int skill)
{ {
if (enterlevel(map, 0)) if (enterlevel(map, 0))
{ {
startmainmenu(); gameaction = ga_mainmenu;
} }
else else
{ {
@ -1025,7 +1025,7 @@ void startnewgame(MapRecord* map, int skill)
setlocalplayerinput(&ps[myconnectindex]); setlocalplayerinput(&ps[myconnectindex]);
PlayerColorChanged(); PlayerColorChanged();
inputState.ClearAllInput(); inputState.ClearAllInput();
gamestate = GS_LEVEL; gameaction = ga_level;
} }
}); });
} }
@ -1087,7 +1087,7 @@ void exitlevel(MapRecord *nextlevel)
// Clear potentially loaded per-map ART only after the bonus screens. // Clear potentially loaded per-map ART only after the bonus screens.
artClearMapArt(); artClearMapArt();
gamestate = GS_LEVEL; gameaction = ga_level;
if (endofgame) if (endofgame)
{ {
if (ud.multimode < 2) if (ud.multimode < 2)

View file

@ -486,7 +486,6 @@ void GameInterface::SerializeGameState(FSerializer& arc)
if (arc.isReading()) if (arc.isReading())
{ {
screenpeek = myconnectindex; screenpeek = myconnectindex;
gamestate = GS_LEVEL;
ud.recstat = 0; ud.recstat = 0;
ud.m_player_skill = ud.player_skill; ud.m_player_skill = ud.player_skill;

View file

@ -149,11 +149,7 @@ void GameInterface::DrawNativeMenuText(int fontnum, int state, double xpos, doub
void GameInterface::QuitToTitle() void GameInterface::QuitToTitle()
{ {
Mus_Stop(); Mus_Stop();
TerminateLevel(); gameaction = ga_mainmenu;
currentLevel = nullptr;
M_StartControlPanel(false);
M_SetMenu(NAME_Mainmenu);
gamestate = GS_MENUSCREEN;
} }

View file

@ -678,9 +678,7 @@ void GameInterface::Startup()
{ {
if (!userConfig.nologo) Logo([](bool) if (!userConfig.nologo) Logo([](bool)
{ {
gamestate = GS_MENUSCREEN; gameaction = ga_mainmenunostopsound;
M_StartControlPanel(false);
M_SetMenu(NAME_Mainmenu);
}); });
else gameaction = ga_mainmenu; else gameaction = ga_mainmenu;
} }