- 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.
This commit is contained in:
Christoph Oelckers 2021-04-28 01:15:15 +02:00
parent cdccdec3e7
commit 869dbd70e5
9 changed files with 58 additions and 67 deletions

View file

@ -133,6 +133,18 @@ void G_BuildTiccmd(ticcmd_t* cmd)
//========================================================================== //==========================================================================
bool newGameStarted; 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() static void GameTicker()
{ {
int i; int i;
@ -159,7 +171,6 @@ static void GameTicker()
FX_SetReverb(0); FX_SetReverb(0);
gi->FreeLevelData(); gi->FreeLevelData();
gameaction = ga_level; gameaction = ga_level;
newGameStarted = true;
NewGame(g_nextmap, -1); NewGame(g_nextmap, -1);
BackupSaveGame = ""; BackupSaveGame = "";
} }
@ -197,7 +208,6 @@ static void GameTicker()
C_FlushDisplay(); C_FlushDisplay();
gameaction = ga_level; gameaction = ga_level;
BackupSaveGame = ""; BackupSaveGame = "";
newGameStarted = true;
NewGame(g_nextmap, g_nextskill, ga == ga_newgamenostopsound); NewGame(g_nextmap, g_nextskill, ga == ga_newgamenostopsound);
break; break;
@ -648,7 +658,6 @@ void MainLoop ()
userConfig.CommandMap = ""; userConfig.CommandMap = "";
if (maprecord) if (maprecord)
{ {
newGameStarted = true;
NewGame(maprecord, /*userConfig.skill*/2); // todo: fix the skill. NewGame(maprecord, /*userConfig.skill*/2); // todo: fix the skill.
} }
} }

View file

@ -53,9 +53,10 @@ struct CutsceneDef
FString function; FString function;
int sound = 0; int sound = 0;
int framespersec = 0; // only relevant for ANM. 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); void Create(DObject* runner);
bool Create(DObject* runner, MapRecord* map); bool Create(DObject* runner, MapRecord* map, bool transition);
}; };
struct GlobalCutscenes struct GlobalCutscenes

View file

@ -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("function")) { sc.GetString(cdef.function); cdef.video = ""; }
else if (sc.Compare("sound")) sc.GetString(sound); else if (sc.Compare("sound")) sc.GetString(sound);
else if (sc.Compare("fps")) sc.GetNumber(cdef.framespersec); 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'. else if (sc.Compare("clear")) { cdef.function = "none"; cdef.video = ""; } // this means 'play nothing', not 'not defined'.
} }
if (sound.IsNotEmpty()) if (sound.IsNotEmpty())

View file

@ -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) if (function.CompareNoCase("none") == 0)
return true; // play nothing but return as being validated return true; // play nothing but return as being validated
if (function.IsNotEmpty()) if (function.IsNotEmpty())
@ -440,43 +441,6 @@ void ShowScoreboard(int numplayers, const CompletionFunc& completion_)
gameaction = ga_intermission; 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(); runner = CreateRunner();
GC::WriteBarrier(runner); 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 try
{ {
// outro: first check the map's own outro. if (fromMap)
// if that is empty, check the cluster's outro
// if that also fails, check the default outro
if (!fromMap->outro.Create(runner, fromMap))
{ {
auto& cluster = volumeList[fromMap->cluster - 1]; if (!fromMap->outro.Create(runner, fromMap, !!toMap))
if ((toMap == nullptr || toMap->cluster != fromMap->cluster) && !cluster.outro.Create(runner, fromMap)) {
globalCutscenes.DefaultMapOutro.Create(runner, fromMap); 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)
{ {
if (!toMap->intro.Create(runner, toMap)) if (!toMap->intro.Create(runner, toMap, !!fromMap))
globalCutscenes.DefaultMapIntro.Create(runner, toMap); {
if (tocluster != -1 && !volumeList[tocluster].intro.Create(runner, toMap, !!fromMap))
globalCutscenes.LoadingScreen.Create(runner, toMap); globalCutscenes.DefaultMapIntro.Create(runner, toMap, !!fromMap);
}
globalCutscenes.LoadingScreen.Create(runner, toMap, true);
} }
else if (isShareware()) else if (isShareware())
{ {
@ -555,11 +535,6 @@ CCMD(testcutscene)
/* /*
Duke:
if (!userConfig.nologo) fi.ShowLogo([](bool) { gameaction = ga_mainmenunostopsound; });
else gameaction = ga_mainmenunostopsound;
Blood: Blood:
if (!userConfig.nologo && gGameOptions.nGameType == 0) playlogos(); if (!userConfig.nologo && gGameOptions.nGameType == 0) playlogos();
else else

View file

@ -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 PlayLogos(gameaction_t complete_ga, gameaction_t def_ga, bool stopmusic);
void ShowScoreboard(int numplayers, const CompletionFunc& completion_); void ShowScoreboard(int numplayers, const CompletionFunc& completion_);
void ShowIntermission(MapRecord* fromMap, MapRecord* toMap, SummaryInfo* info, CompletionFunc completion_); void ShowIntermission(MapRecord* fromMap, MapRecord* toMap, SummaryInfo* info, CompletionFunc completion_);
void NewGame(MapRecord* map, int skill, bool ns = false);

View file

@ -1,6 +1,8 @@
// names for everything that gets accessed by scripts. // names for everything that gets accessed by scripts.
x(MENUBAR, 2038) x(MENUBAR, 2038)
x(BackTile, 253) x(BackTile, 253)
x(Monolithscreen, 2050)
x(GTIScreen, 2052)
x(CrosshairTile, 2319) x(CrosshairTile, 2319)
x(LoadScreen, 2049) x(LoadScreen, 2049)

View file

@ -31,10 +31,6 @@ definecutscene episode 3
definecutscene episode 4 definecutscene episode 4
{ {
intro
{
function DukeCutscenes.BuildE4Intro
}
outro outro
{ {
function DukeCutscenes.BuildE4End function DukeCutscenes.BuildE4End
@ -49,6 +45,14 @@ definecutscene episode 5
} }
} }
definecutscene map e4l1
{
intro
{
function DukeCutscenes.BuildE4Intro
}
}
definecutscene sharewareend definecutscene sharewareend
{ {
function DukeCutscenes.BuildSharewareEnd function DukeCutscenes.BuildSharewareEnd

View file

@ -25,6 +25,7 @@ definecutscene episode 2
definecutscene mapintro definecutscene mapintro
{ {
function RRCutscenes.BuildMapIntro // this plays the 'travel' animation. function RRCutscenes.BuildMapIntro // this plays the 'travel' animation.
transitiononly
} }
definecutscene loading definecutscene loading

View file

@ -352,11 +352,10 @@ class RRCutscenes
if (!raze.isRRRA()) return; if (!raze.isRRRA()) return;
int ln = map.levelnumber; int ln = map.levelnumber;
if (ln == 0) return; if (ln == 0) return;
if (ln > 1000) ln -= 1000-7; if (ln >= 1000) ln -= 1000-7;
let fn = String.Format("lvl%d.anm", ln); let fn = String.Format("lvl%d.anm", ln);
Array<int> soundinfo; Array<int> 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. 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.
} }
} }