diff --git a/src/g_level.h b/src/g_level.h index 71ae6f276..ffc708427 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -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, diff --git a/src/gamedata/g_mapinfo.cpp b/src/gamedata/g_mapinfo.cpp index 9f6d94f2e..ea6192080 100644 --- a/src/gamedata/g_mapinfo.cpp +++ b/src/gamedata/g_mapinfo.cpp @@ -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; } diff --git a/src/gamedata/g_mapinfo.h b/src/gamedata/g_mapinfo.h index 5f4a5cc18..25a5ed1ca 100644 --- a/src/gamedata/g_mapinfo.h +++ b/src/gamedata/g_mapinfo.h @@ -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); diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index c32812ce2..a28e4c948 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -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(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); diff --git a/src/intermission/intermission.h b/src/intermission/intermission.h index 45c2efd8b..21548edc9 100644 --- a/src/intermission/intermission.h +++ b/src/intermission/intermission.h @@ -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) diff --git a/src/intermission/intermission_parse.cpp b/src/intermission/intermission_parse.cpp index d1089526b..77ce981ab 100644 --- a/src/intermission/intermission_parse.cpp +++ b/src/intermission/intermission_parse.cpp @@ -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); } //==========================================================================