mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-02-02 13:51:52 +00:00
- added cutscene creation code
This commit is contained in:
parent
ea007f56f2
commit
99d98cf79d
6 changed files with 106 additions and 7 deletions
|
@ -98,6 +98,7 @@ enum gameaction_t : int
|
||||||
ga_resumeconversation,
|
ga_resumeconversation,
|
||||||
ga_intro,
|
ga_intro,
|
||||||
ga_intermission,
|
ga_intermission,
|
||||||
|
ga_titleloop,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern gameaction_t gameaction;
|
extern gameaction_t gameaction;
|
||||||
|
|
|
@ -136,7 +136,7 @@ void DrawHUD();
|
||||||
void D_DoAnonStats();
|
void D_DoAnonStats();
|
||||||
void I_DetectOS();
|
void I_DetectOS();
|
||||||
void UpdateGenericUI(bool cvar);
|
void UpdateGenericUI(bool cvar);
|
||||||
|
void Local_Job_Init();
|
||||||
|
|
||||||
// MACROS ------------------------------------------------------------------
|
// MACROS ------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -306,6 +306,7 @@ CUSTOM_CVAR(Int, I_FriendlyWindowTitle, 1, CVAR_GLOBALCONFIG|CVAR_ARCHIVE|CVAR_N
|
||||||
{
|
{
|
||||||
I_UpdateWindowTitle();
|
I_UpdateWindowTitle();
|
||||||
}
|
}
|
||||||
|
CVAR(Bool, cl_nointros, false, CVAR_ARCHIVE)
|
||||||
|
|
||||||
|
|
||||||
bool hud_toggled = false;
|
bool hud_toggled = false;
|
||||||
|
@ -3371,6 +3372,7 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray<FString>& allwads, TArr
|
||||||
twod->End();
|
twod->End();
|
||||||
UpdateJoystickMenu(NULL);
|
UpdateJoystickMenu(NULL);
|
||||||
UpdateVRModes();
|
UpdateVRModes();
|
||||||
|
Local_Job_Init();
|
||||||
|
|
||||||
v = Args->CheckValue ("-loadgame");
|
v = Args->CheckValue ("-loadgame");
|
||||||
if (v)
|
if (v)
|
||||||
|
@ -3417,7 +3419,16 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray<FString>& allwads, TArr
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
D_StartTitle(); // start up intro loop
|
if (multiplayer || cl_nointros || Args->CheckParm("-nointro"))
|
||||||
|
{
|
||||||
|
D_StartTitle();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!StartCutscene(gameinfo.IntroScene, SJ_BLOCKUI, [=](bool) {
|
||||||
|
gameaction = ga_titleloop;
|
||||||
|
})) D_StartTitle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (demorecording)
|
else if (demorecording)
|
||||||
|
|
|
@ -1198,6 +1198,9 @@ void G_Ticker ()
|
||||||
gamestate = GS_CUTSCENE;
|
gamestate = GS_CUTSCENE;
|
||||||
gameaction = ga_nothing;
|
gameaction = ga_nothing;
|
||||||
break;
|
break;
|
||||||
|
case ga_titleloop:
|
||||||
|
D_StartTitle();
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -3077,7 +3080,7 @@ void G_StartSlideshow(FLevelLocals *Level, FName whichone)
|
||||||
{
|
{
|
||||||
auto SelectedSlideshow = whichone == NAME_None ? Level->info->slideshow : whichone;
|
auto SelectedSlideshow = whichone == NAME_None ? Level->info->slideshow : whichone;
|
||||||
auto slide = F_StartIntermission(SelectedSlideshow);
|
auto slide = F_StartIntermission(SelectedSlideshow);
|
||||||
RunIntermission(slide, nullptr, [](bool)
|
RunIntermission(nullptr, nullptr, slide, nullptr, [](bool)
|
||||||
{
|
{
|
||||||
primaryLevel->SetMusic();
|
primaryLevel->SetMusic();
|
||||||
gamestate = GS_LEVEL;
|
gamestate = GS_LEVEL;
|
||||||
|
|
|
@ -107,7 +107,8 @@ class FBaseCVar;
|
||||||
FBaseCVar* G_GetUserCVar(int playernum, const char* cvarname);
|
FBaseCVar* G_GetUserCVar(int playernum, const char* cvarname);
|
||||||
|
|
||||||
class DIntermissionController;
|
class DIntermissionController;
|
||||||
void RunIntermission(DIntermissionController* intermissionScreen, DObject* statusScreen, std::function<void(bool)> completionf);
|
struct level_info_t;
|
||||||
|
void RunIntermission(level_info_t* oldlevel, level_info_t* newlevel, DIntermissionController* intermissionScreen, DObject* statusScreen, std::function<void(bool)> completionf);
|
||||||
|
|
||||||
extern const AActor *SendItemUse, *SendItemDrop;
|
extern const AActor *SendItemUse, *SendItemDrop;
|
||||||
extern int SendItemDropAmount;
|
extern int SendItemDropAmount;
|
||||||
|
|
|
@ -83,9 +83,11 @@
|
||||||
#include "stringtable.h"
|
#include "stringtable.h"
|
||||||
#include "c_buttons.h"
|
#include "c_buttons.h"
|
||||||
#include "screenjob.h"
|
#include "screenjob.h"
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
#include "gi.h"
|
#include "gi.h"
|
||||||
|
|
||||||
|
|
||||||
#include "g_hub.h"
|
#include "g_hub.h"
|
||||||
#include "g_levellocals.h"
|
#include "g_levellocals.h"
|
||||||
#include "actorinlines.h"
|
#include "actorinlines.h"
|
||||||
|
@ -178,6 +180,7 @@ void *statcopy; // for statistics driver
|
||||||
FLevelLocals level; // info about current level
|
FLevelLocals level; // info about current level
|
||||||
FLevelLocals *primaryLevel = &level; // level for which to display the user interface.
|
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.
|
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;
|
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)
|
if (!intermissionScreen && !statusScreen)
|
||||||
{
|
{
|
||||||
|
@ -949,6 +1009,20 @@ void RunIntermission(DIntermissionController* intermissionScreen, DObject* statu
|
||||||
GC::WriteBarrier(runner);
|
GC::WriteBarrier(runner);
|
||||||
completion = std::move(completionf);
|
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");
|
auto func = LookupFunction("DoomCutscenes.BuildMapTransition");
|
||||||
if (func == nullptr)
|
if (func == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -957,6 +1031,14 @@ void RunIntermission(DIntermissionController* intermissionScreen, DObject* statu
|
||||||
VMValue val[3] = { runner, intermissionScreen, statusScreen };
|
VMValue val[3] = { runner, intermissionScreen, statusScreen };
|
||||||
VMCall(func, val, 3, nullptr, 0);
|
VMCall(func, val, 3, nullptr, 0);
|
||||||
|
|
||||||
|
if (toMap)
|
||||||
|
{
|
||||||
|
if (!CreateCutscene(&toMap->intro, runner, toMap))
|
||||||
|
{
|
||||||
|
if (tocluster != nullptr) CreateCutscene(&tocluster->intro, runner, toMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!ScreenJobValidate())
|
if (!ScreenJobValidate())
|
||||||
{
|
{
|
||||||
DeleteScreenJob();
|
DeleteScreenJob();
|
||||||
|
@ -1012,7 +1094,8 @@ void G_DoCompleted (void)
|
||||||
}
|
}
|
||||||
bool endgame = strncmp(nextlevel, "enDSeQ", 6) == 0;
|
bool endgame = strncmp(nextlevel, "enDSeQ", 6) == 0;
|
||||||
intermissionScreen = primaryLevel->CreateIntermission();
|
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();
|
if (!endgame) primaryLevel->WorldDone();
|
||||||
else D_StartTitle();
|
else D_StartTitle();
|
||||||
|
|
|
@ -955,6 +955,6 @@ CCMD(testfinale)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto controller = F_StartFinale(gameinfo.finaleMusic, gameinfo.finaleOrder, -1, 0, gameinfo.FinaleFlat, text, false, false, true, true);
|
auto controller = F_StartFinale(gameinfo.finaleMusic, gameinfo.finaleOrder, -1, 0, gameinfo.FinaleFlat, text, false, false, true, true);
|
||||||
RunIntermission(controller, nullptr, [=](bool) { gameaction = ga_nothing; });
|
RunIntermission(nullptr, nullptr, controller, nullptr, [=](bool) { gameaction = ga_nothing; });
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue