From 869dbd70e5fa5983f769d3f26a2caa5ee0934ba7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 28 Apr 2021 01:15:15 +0200 Subject: [PATCH] - fixed the design by merging the episode start handler into ShowIntermission. Tying the start-of-episode cutscene to the cluster does not really work because it gets triggered by all maps of the cluster. All currently existing intro cutscenes are tied to the map anyway. Also correcting transition movie name for RRRA E2L1. --- source/core/mainloop.cpp | 15 +++- source/core/mapinfo.h | 3 +- source/core/parsefuncs.h | 1 + source/core/screenjob.cpp | 87 +++++++------------ source/core/screenjob.h | 1 - source/games/blood/src/namelist.h | 2 + wadsrc/static/filter/duke/engine/engine.def | 12 ++- .../static/filter/redneck/engine/engine.def | 1 + .../static/zscript/games/duke/ui/cutscenes.zs | 3 +- 9 files changed, 58 insertions(+), 67 deletions(-) diff --git a/source/core/mainloop.cpp b/source/core/mainloop.cpp index 9be356b4c..6969ebdf5 100644 --- a/source/core/mainloop.cpp +++ b/source/core/mainloop.cpp @@ -133,6 +133,18 @@ void G_BuildTiccmd(ticcmd_t* cmd) //========================================================================== bool newGameStarted; +void NewGame(MapRecord* map, int skill, bool ns = false) +{ + newGameStarted = true; + ShowIntermission(nullptr, map, nullptr, [=](bool) { gi->NewGame(map, skill, ns); }); +} + +//========================================================================== +// +// +// +//========================================================================== + static void GameTicker() { int i; @@ -159,7 +171,6 @@ static void GameTicker() FX_SetReverb(0); gi->FreeLevelData(); gameaction = ga_level; - newGameStarted = true; NewGame(g_nextmap, -1); BackupSaveGame = ""; } @@ -197,7 +208,6 @@ static void GameTicker() C_FlushDisplay(); gameaction = ga_level; BackupSaveGame = ""; - newGameStarted = true; NewGame(g_nextmap, g_nextskill, ga == ga_newgamenostopsound); break; @@ -648,7 +658,6 @@ void MainLoop () userConfig.CommandMap = ""; if (maprecord) { - newGameStarted = true; NewGame(maprecord, /*userConfig.skill*/2); // todo: fix the skill. } } diff --git a/source/core/mapinfo.h b/source/core/mapinfo.h index fff7a9ec3..0263b58e3 100644 --- a/source/core/mapinfo.h +++ b/source/core/mapinfo.h @@ -53,9 +53,10 @@ struct CutsceneDef FString function; int sound = 0; int framespersec = 0; // only relevant for ANM. + bool transitiononly = false; // only play when transitioning between maps, but not when starting on a map or ending a game. void Create(DObject* runner); - bool Create(DObject* runner, MapRecord* map); + bool Create(DObject* runner, MapRecord* map, bool transition); }; struct GlobalCutscenes diff --git a/source/core/parsefuncs.h b/source/core/parsefuncs.h index 145abcbb9..175fabb10 100644 --- a/source/core/parsefuncs.h +++ b/source/core/parsefuncs.h @@ -64,6 +64,7 @@ static void parseCutscene(FScanner& sc, CutsceneDef& cdef) else if (sc.Compare("function")) { sc.GetString(cdef.function); cdef.video = ""; } else if (sc.Compare("sound")) sc.GetString(sound); else if (sc.Compare("fps")) sc.GetNumber(cdef.framespersec); + else if (sc.Compare("transitiononly")) cdef.transitiononly = true; else if (sc.Compare("clear")) { cdef.function = "none"; cdef.video = ""; } // this means 'play nothing', not 'not defined'. } if (sound.IsNotEmpty()) diff --git a/source/core/screenjob.cpp b/source/core/screenjob.cpp index 6405b3793..03e79b95a 100644 --- a/source/core/screenjob.cpp +++ b/source/core/screenjob.cpp @@ -212,8 +212,9 @@ void CutsceneDef::Create(DObject* runner) // //============================================================================= -bool CutsceneDef::Create(DObject* runner, MapRecord* map) +bool CutsceneDef::Create(DObject* runner, MapRecord* map, bool transition) { + if (!transition && transitiononly) return false; if (function.CompareNoCase("none") == 0) return true; // play nothing but return as being validated if (function.IsNotEmpty()) @@ -440,43 +441,6 @@ void ShowScoreboard(int numplayers, const CompletionFunc& completion_) gameaction = ga_intermission; } -//========================================================================== -// -// -// -//========================================================================== - -void NewGame(MapRecord* map, int skill, bool ns) -{ - completion = [=](bool) { gi->NewGame(map, skill, ns); }; - runner = CreateRunner(); - GC::WriteBarrier(runner); - - try - { - int volume = map->cluster - 1; - if (volume >= 0 && volume < MAXVOLUMES) - volumeList[volume].intro.Create(runner); - - globalCutscenes.LoadingScreen.Create(runner, map); - if (!ScreenJobValidate()) - { - runner->Destroy(); - runner = nullptr; - completion(false); - completion = nullptr; - return; - } - gameaction = ga_intermission; - } - catch (...) - { - if (runner) runner->Destroy(); - runner = nullptr; - throw; - } -} - //--------------------------------------------------------------------------- // // @@ -489,26 +453,42 @@ void ShowIntermission(MapRecord* fromMap, MapRecord* toMap, SummaryInfo* info, C runner = CreateRunner(); GC::WriteBarrier(runner); + // retrieve cluster relations for cluster-based cutscenes. + int fromcluster = -1, tocluster = -1; + if (fromMap) + { + fromcluster = fromMap->cluster - 1; + if (fromcluster < 0 || fromcluster >= MAXVOLUMES) fromcluster = -1; + } + if (toMap) + { + tocluster = toMap->cluster - 1; + if (tocluster < 0 || tocluster >= MAXVOLUMES) tocluster = -1; + } + if (fromcluster == tocluster) fromcluster = tocluster = -1; + + try { - // outro: first check the map's own outro. - // if that is empty, check the cluster's outro - // if that also fails, check the default outro - if (!fromMap->outro.Create(runner, fromMap)) + if (fromMap) { - auto& cluster = volumeList[fromMap->cluster - 1]; - if ((toMap == nullptr || toMap->cluster != fromMap->cluster) && !cluster.outro.Create(runner, fromMap)) - globalCutscenes.DefaultMapOutro.Create(runner, fromMap); - } + if (!fromMap->outro.Create(runner, fromMap, !!toMap)) + { + if (fromcluster != -1 && !volumeList[fromcluster].outro.Create(runner, fromMap, !!toMap)) + globalCutscenes.DefaultMapOutro.Create(runner, fromMap, !!toMap); + } - CallCreateSummaryFunction(globalCutscenes.SummaryScreen, runner, fromMap, info); + CallCreateSummaryFunction(globalCutscenes.SummaryScreen, runner, fromMap, info); + } if (toMap) { - if (!toMap->intro.Create(runner, toMap)) - globalCutscenes.DefaultMapIntro.Create(runner, toMap); - - globalCutscenes.LoadingScreen.Create(runner, toMap); + if (!toMap->intro.Create(runner, toMap, !!fromMap)) + { + if (tocluster != -1 && !volumeList[tocluster].intro.Create(runner, toMap, !!fromMap)) + globalCutscenes.DefaultMapIntro.Create(runner, toMap, !!fromMap); + } + globalCutscenes.LoadingScreen.Create(runner, toMap, true); } else if (isShareware()) { @@ -555,11 +535,6 @@ CCMD(testcutscene) /* -Duke: - if (!userConfig.nologo) fi.ShowLogo([](bool) { gameaction = ga_mainmenunostopsound; }); - else gameaction = ga_mainmenunostopsound; - - Blood: if (!userConfig.nologo && gGameOptions.nGameType == 0) playlogos(); else diff --git a/source/core/screenjob.h b/source/core/screenjob.h index 7b335f25e..a4f6eff5c 100644 --- a/source/core/screenjob.h +++ b/source/core/screenjob.h @@ -28,4 +28,3 @@ bool StartCutscene(const char* s, int flags, const CompletionFunc& completion); void PlayLogos(gameaction_t complete_ga, gameaction_t def_ga, bool stopmusic); void ShowScoreboard(int numplayers, const CompletionFunc& completion_); void ShowIntermission(MapRecord* fromMap, MapRecord* toMap, SummaryInfo* info, CompletionFunc completion_); -void NewGame(MapRecord* map, int skill, bool ns = false); diff --git a/source/games/blood/src/namelist.h b/source/games/blood/src/namelist.h index b81969d7b..b93e997e4 100644 --- a/source/games/blood/src/namelist.h +++ b/source/games/blood/src/namelist.h @@ -1,6 +1,8 @@ // names for everything that gets accessed by scripts. x(MENUBAR, 2038) x(BackTile, 253) +x(Monolithscreen, 2050) +x(GTIScreen, 2052) x(CrosshairTile, 2319) x(LoadScreen, 2049) diff --git a/wadsrc/static/filter/duke/engine/engine.def b/wadsrc/static/filter/duke/engine/engine.def index be2ca0a01..e9455553c 100644 --- a/wadsrc/static/filter/duke/engine/engine.def +++ b/wadsrc/static/filter/duke/engine/engine.def @@ -31,10 +31,6 @@ definecutscene episode 3 definecutscene episode 4 { - intro - { - function DukeCutscenes.BuildE4Intro - } outro { function DukeCutscenes.BuildE4End @@ -49,6 +45,14 @@ definecutscene episode 5 } } +definecutscene map e4l1 +{ + intro + { + function DukeCutscenes.BuildE4Intro + } +} + definecutscene sharewareend { function DukeCutscenes.BuildSharewareEnd diff --git a/wadsrc/static/filter/redneck/engine/engine.def b/wadsrc/static/filter/redneck/engine/engine.def index 2f93e916f..104188d77 100644 --- a/wadsrc/static/filter/redneck/engine/engine.def +++ b/wadsrc/static/filter/redneck/engine/engine.def @@ -25,6 +25,7 @@ definecutscene episode 2 definecutscene mapintro { function RRCutscenes.BuildMapIntro // this plays the 'travel' animation. + transitiononly } definecutscene loading diff --git a/wadsrc/static/zscript/games/duke/ui/cutscenes.zs b/wadsrc/static/zscript/games/duke/ui/cutscenes.zs index 49b5a3020..ad78289fa 100644 --- a/wadsrc/static/zscript/games/duke/ui/cutscenes.zs +++ b/wadsrc/static/zscript/games/duke/ui/cutscenes.zs @@ -352,11 +352,10 @@ class RRCutscenes if (!raze.isRRRA()) return; int ln = map.levelnumber; if (ln == 0) return; - if (ln > 1000) ln -= 1000-7; + if (ln >= 1000) ln -= 1000-7; let fn = String.Format("lvl%d.anm", ln); Array soundinfo; runner.Append(MoviePlayerJob.CreateWithSoundinfo(fn, soundinfo, 0, 20, 20, 7200)); // wait for one minute on the final frame so that the video doesn't stop before the user notices. } - } \ No newline at end of file