allow cutscenes in intermissions

This commit is contained in:
Ricardo Luís Vaz Silva 2025-01-25 19:44:54 -03:00
parent 74a04474e1
commit 206c2291d9
6 changed files with 143 additions and 16 deletions

View file

@ -18,6 +18,8 @@ void G_DeferedInitNew (const char *mapname, int skill = -1);
struct FNewGameStartup;
void G_DeferedInitNew (FNewGameStartup *gs);
bool CreateCutscene(struct CutsceneDef* cs, DObject* runner, level_info_t* map);
enum
{
CHANGELEVEL_KEEPFACING = 1,

View file

@ -793,7 +793,7 @@ void FMapInfoParser::ParseMusic(FString &name, int &order)
//
//==========================================================================
void FMapInfoParser::ParseCutscene(CutsceneDef& cdef)
void FMapInfoParser::ParseCutscene(CutsceneDef& cdef, bool allow_function)
{
FString sound;
sc.MustGetStringName("{");
@ -801,7 +801,7 @@ void FMapInfoParser::ParseCutscene(CutsceneDef& cdef)
{
sc.MustGetString();
if (sc.Compare("video")) { ParseAssign(); sc.MustGetString(); cdef.video = sc.String; cdef.function = ""; }
else if (sc.Compare("function")) { ParseAssign(); sc.SetCMode(false); sc.MustGetString(); sc.SetCMode(true); cdef.function = sc.String; cdef.video = ""; }
else if (sc.Compare("function") && allow_function) { ParseAssign(); sc.SetCMode(false); sc.MustGetString(); sc.SetCMode(true); cdef.function = sc.String; cdef.video = ""; }
else if (sc.Compare("sound")) { ParseAssign(); sc.MustGetString(); cdef.soundName = sc.String; }
else if (sc.Compare("soundid")) { ParseAssign(); sc.MustGetNumber(); cdef.soundID = sc.Number; }
else if (sc.Compare("fps")) { ParseAssign(); sc.MustGetNumber(); cdef.framespersec = sc.Number; }

View file

@ -102,7 +102,7 @@ struct FMapInfoParser
bool ParseLookupName(FString &dest);
void ParseMusic(FString &name, int &order);
void ParseCutscene(CutsceneDef& cdef);
void ParseCutscene(CutsceneDef& cdef, bool allow_function = true);
//void ParseLumpOrTextureName(char *name);
void ParseLumpOrTextureName(FString &name);

View file

@ -58,6 +58,7 @@
#include "sbar.h"
#include "screenjob.h"
#include "vm.h"
#include "i_time.h"
FIntermissionDescriptorList IntermissionDescriptors;
@ -66,12 +67,17 @@ IMPLEMENT_CLASS(DIntermissionScreenFader, false, false)
IMPLEMENT_CLASS(DIntermissionScreenText, false, false)
IMPLEMENT_CLASS(DIntermissionScreenCast, false, false)
IMPLEMENT_CLASS(DIntermissionScreenScroller, false, false)
IMPLEMENT_CLASS(DIntermissionScreenCutscene, false, true)
IMPLEMENT_CLASS(DIntermissionController, false, true)
IMPLEMENT_POINTERS_START(DIntermissionController)
IMPLEMENT_POINTER(mScreen)
IMPLEMENT_POINTERS_END
IMPLEMENT_POINTERS_START(DIntermissionScreenCutscene)
IMPLEMENT_POINTER(mScreenJobRunner)
IMPLEMENT_POINTERS_END
extern int NoWipe;
CVAR(Bool, nointerscrollabort, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
@ -276,6 +282,66 @@ void DIntermissionScreen::OnDestroy()
//
//==========================================================================
void DIntermissionScreenCutscene::Init(FIntermissionAction *desc, bool first)
{
Super::Init(desc, first);
mScreenJobRunner = CreateRunner(false);
if(first) NoWipe++;
CreateCutscene(&static_cast<FIntermissionActionCutscene*>(desc)->scn, mScreenJobRunner, nullptr);
}
int DIntermissionScreenCutscene::Responder (FInputEvent *ev)
{
ScaleOverrider ovr(twod);
IFVIRTUALPTRNAME(mScreenJobRunner, NAME_ScreenJobRunner, OnEvent)
{
FInputEvent evt = *ev;
int result = 0;
VMValue parm[] = { mScreenJobRunner, &evt };
VMReturn ret(&result);
VMCall(func, parm, 2, &ret, 1);
return result ? -1 : 0;
}
return Super::Responder(ev);
}
int DIntermissionScreenCutscene::Ticker()
{
++mTicker;
ScaleOverrider ovr(twod);
IFVIRTUALPTRNAME(mScreenJobRunner, NAME_ScreenJobRunner, OnTick)
{
int result = 0;
VMValue parm[] = { mScreenJobRunner };
VMReturn ret(&result);
VMCall(func, parm, 1, &ret, 1);
return result ? -1 : 0;
}
return -1;
}
void DIntermissionScreenCutscene::Drawer ()
{
ScaleOverrider ovr(twod);
IFVIRTUALPTRNAME(mScreenJobRunner, NAME_ScreenJobRunner, RunFrame)
{
VMValue parm[] = { mScreenJobRunner, I_GetTimeFrac() };
VMCall(func, parm, 2, nullptr, 0);
}
}
void DIntermissionScreenCutscene::OnDestroy()
{
mScreenJobRunner->Destroy();
Super::OnDestroy();
}
//==========================================================================
//
//
//
//==========================================================================
void DIntermissionScreenFader::Init(FIntermissionAction *desc, bool first)
{
Super::Init(desc, first);

View file

@ -9,6 +9,7 @@
#include "v_font.h"
#include "g_game.h"
#include "v_text.h"
#include "screenjob.h"
struct FInputEvent;
struct FState;
@ -85,6 +86,14 @@ struct FIntermissionAction
FIntermissionAction();
virtual ~FIntermissionAction() {}
virtual bool ParseKey(FScanner &sc);
virtual bool Parse(struct FMapInfoParser &m, FScanner &sc);
};
struct FIntermissionActionCutscene : public FIntermissionAction
{
CutsceneDef scn;
FIntermissionActionCutscene();
virtual bool Parse(FMapInfoParser &m, FScanner &sc);
};
struct FIntermissionActionFader : public FIntermissionAction
@ -197,6 +206,20 @@ public:
}
};
class DIntermissionScreenCutscene : public DIntermissionScreen
{
DECLARE_CLASS (DIntermissionScreenCutscene, DIntermissionScreen)
HAS_OBJECT_POINTERS
public:
DObject* mScreenJobRunner;
DIntermissionScreenCutscene() {}
virtual void Init(FIntermissionAction *desc, bool first);
virtual int Responder (FInputEvent *ev);
virtual int Ticker ();
virtual void Drawer ();
virtual void OnDestroy ();
};
class DIntermissionScreenFader : public DIntermissionScreen
{
DECLARE_CLASS (DIntermissionScreenFader, DIntermissionScreen)

View file

@ -194,6 +194,46 @@ bool FIntermissionAction::ParseKey(FScanner &sc)
else return false;
}
bool FIntermissionAction::Parse(FMapInfoParser &m, FScanner &sc)
{
sc.MustGetToken('{');
while (!sc.CheckToken('}'))
{
bool success = false;
if (!sc.CheckToken(TK_Sound))
{
sc.MustGetToken(TK_Identifier);
}
success = ParseKey(sc);
if (!success)
{
sc.ScriptMessage("Unknown key name '%s'\n", sc.String);
return false;
}
}
return true;
}
//==========================================================================
//
// FIntermissionActionCutscene
//
//==========================================================================
FIntermissionActionCutscene::FIntermissionActionCutscene()
{
scn = {};
mSize = sizeof(FIntermissionActionCutscene);
mClass = RUNTIME_CLASS(DIntermissionScreenCutscene);
}
bool FIntermissionActionCutscene::Parse(FMapInfoParser &m, FScanner &sc)
{
m.ParseCutscene(scn, false);
return true;
}
//==========================================================================
//
// FIntermissionActionFader
@ -527,6 +567,10 @@ void FMapInfoParser::ParseIntermissionAction(FIntermissionDescriptor *desc)
{
ac = new FIntermissionActionCast;
}
else if (sc.Compare("cutscene"))
{
ac = new FIntermissionActionCutscene;
}
else if (sc.Compare("Fader"))
{
ac = new FIntermissionActionFader;
@ -556,25 +600,17 @@ void FMapInfoParser::ParseIntermissionAction(FIntermissionDescriptor *desc)
sc.ScriptMessage("Unknown intermission type '%s'", sc.String);
}
sc.MustGetToken('{');
while (!sc.CheckToken('}'))
if(ac)
{
bool success = false;
if (!sc.CheckToken(TK_Sound))
if(!ac->Parse(*this, sc))
{
sc.MustGetToken(TK_Identifier);
SkipToNext();
}
if (ac != NULL)
else
{
success = ac->ParseKey(sc);
if (!success)
{
sc.ScriptMessage("Unknown key name '%s'\n", sc.String);
}
desc->mActions.Push(ac);
}
if (!success) SkipToNext();
}
if (ac != NULL) desc->mActions.Push(ac);
}
//==========================================================================