- added cutscene creation code

This commit is contained in:
Christoph Oelckers 2022-06-03 00:03:57 +02:00
commit 99d98cf79d
6 changed files with 106 additions and 7 deletions

View file

@ -83,9 +83,11 @@
#include "stringtable.h"
#include "c_buttons.h"
#include "screenjob.h"
#include "types.h"
#include "gi.h"
#include "g_hub.h"
#include "g_levellocals.h"
#include "actorinlines.h"
@ -178,6 +180,7 @@ void *statcopy; // for statistics driver
FLevelLocals level; // info about current level
FLevelLocals *primaryLevel = &level; // level for which to display the user interface.
FLevelLocals *currentVMLevel = &level; // level which currently ticks. Used as global input to the VM and some functions called by it.
static PType* maprecordtype;
//==========================================================================
@ -938,7 +941,64 @@ DIntermissionController* FLevelLocals::CreateIntermission()
return controller;
}
void RunIntermission(DIntermissionController* intermissionScreen, DObject* statusScreen, std::function<void(bool)> completionf)
//=============================================================================
//
//
//
//=============================================================================
void Local_Job_Init()
{
maprecordtype = NewPointer(NewStruct("MapRecord", nullptr, true));
}
//=============================================================================
//
//
//
//=============================================================================
static void CallCreateMapFunction(const char* qname, DObject* runner, level_info_t* map)
{
auto func = LookupFunction(qname);
if (func->Proto->ArgumentTypes.Size() == 1) return CallCreateFunction(qname, runner); // accept functions without map parameter as well here.
if (func->Proto->ArgumentTypes.Size() != 2) I_Error("Bad map-cutscene function %s. Must receive precisely two arguments.", qname);
if (func->Proto->ArgumentTypes[0] != runnerclasstype && func->Proto->ArgumentTypes[1] != maprecordtype)
I_Error("Bad cutscene function %s. Must receive ScreenJobRunner and LevelInfo reference.", qname);
VMValue val[2] = { runner, map };
VMCall(func, val, 2, nullptr, 0);
}
//=============================================================================
//
//
//
//=============================================================================
bool CreateCutscene(CutsceneDef* cs, DObject* runner, level_info_t* map)
{
if (cs->function.CompareNoCase("none") == 0)
return true; // play nothing but return as being validated
if (cs->function.IsNotEmpty())
{
CallCreateMapFunction(cs->function, runner, map);
return true;
}
else if (cs->video.IsNotEmpty())
{
AddGenericVideo(runner, cs->video, cs->GetSound(), cs->framespersec);
return true;
}
return false;
}
//=============================================================================
//
//
//
//=============================================================================
void RunIntermission(level_info_t* fromMap, level_info_t* toMap, DIntermissionController* intermissionScreen, DObject* statusScreen, std::function<void(bool)> completionf)
{
if (!intermissionScreen && !statusScreen)
{
@ -948,6 +1008,20 @@ void RunIntermission(DIntermissionController* intermissionScreen, DObject* statu
runner = CreateRunner(false);
GC::WriteBarrier(runner);
completion = std::move(completionf);
// retrieve cluster relations for cluster-based cutscenes.
cluster_info_t* fromcluster = nullptr, *tocluster = nullptr;
if (fromMap) fromcluster = FindClusterInfo(fromMap->cluster);
if (toMap) tocluster = FindClusterInfo(toMap->cluster);
if (fromcluster == tocluster) fromcluster = tocluster = nullptr;
if (fromMap)
{
if (!CreateCutscene(&fromMap->outro, runner, fromMap))
{
if (fromcluster != nullptr) CreateCutscene(&fromcluster->outro, runner, fromMap);
}
}
auto func = LookupFunction("DoomCutscenes.BuildMapTransition");
if (func == nullptr)
@ -957,6 +1031,14 @@ void RunIntermission(DIntermissionController* intermissionScreen, DObject* statu
VMValue val[3] = { runner, intermissionScreen, statusScreen };
VMCall(func, val, 3, nullptr, 0);
if (toMap)
{
if (!CreateCutscene(&toMap->intro, runner, toMap))
{
if (tocluster != nullptr) CreateCutscene(&tocluster->intro, runner, toMap);
}
}
if (!ScreenJobValidate())
{
DeleteScreenJob();
@ -1012,7 +1094,8 @@ void G_DoCompleted (void)
}
bool endgame = strncmp(nextlevel, "enDSeQ", 6) == 0;
intermissionScreen = primaryLevel->CreateIntermission();
RunIntermission(intermissionScreen, statusScreen, [=](bool)
auto nextinfo = endgame? nullptr : FindLevelInfo(nextlevel, false);
RunIntermission(primaryLevel->info, nextinfo, intermissionScreen, statusScreen, [=](bool)
{
if (!endgame) primaryLevel->WorldDone();
else D_StartTitle();