Screenjob WIP stuff

This commit is contained in:
Christoph Oelckers 2022-04-11 13:12:37 +02:00
parent 80200da947
commit 1bb750c061
13 changed files with 161 additions and 132 deletions

View file

@ -143,7 +143,6 @@ extern bool playedtitlemusic;
gameaction_t gameaction;
gamestate_t gamestate = GS_STARTUP;
FName SelectedSlideshow; // what to start when ga_slideshow
int paused;
bool pauseext;
@ -1169,9 +1168,6 @@ void G_Ticker ()
case ga_completed:
G_DoCompleted ();
break;
case ga_slideshow:
if (gamestate == GS_LEVEL) F_StartIntermission(SelectedSlideshow, FSTATE_InLevel);
break;
case ga_worlddone:
G_DoWorldDone ();
break;
@ -1192,6 +1188,11 @@ void G_Ticker ()
P_ResumeConversation ();
gameaction = ga_nothing;
break;
case ga_intermission:
gamestate = GS_CUTSCENE;
break;
default:
case ga_nothing:
break;
@ -3058,8 +3059,16 @@ bool G_CheckDemoStatus (void)
void G_StartSlideshow(FLevelLocals *Level, FName whichone)
{
gameaction = ga_slideshow;
SelectedSlideshow = whichone == NAME_None ? Level->info->slideshow : whichone;
auto SelectedSlideshow = whichone == NAME_None ? Level->info->slideshow : whichone;
auto slide = F_StartIntermission(SelectedSlideshow);
RunIntermission(slide, nullptr, [](bool)
{
primaryLevel->SetMusic();
gamestate = GS_LEVEL;
wipegamestate = GS_LEVEL;
gameaction = ga_resumeconversation;
});
}
DEFINE_ACTION_FUNCTION(FLevelLocals, StartSlideshow)

View file

@ -106,6 +106,8 @@ void G_AddViewAngle (int yaw, bool mouse = false);
class FBaseCVar;
FBaseCVar* G_GetUserCVar(int playernum, const char* cvarname);
void RunIntermission(DIntermissionController* intermissionScreen, DObject* statusScreen, std::function<void(bool)> completionf);
extern const AActor *SendItemUse, *SendItemDrop;
extern int SendItemDropAmount;

View file

@ -839,7 +839,8 @@ DIntermissionController* FLevelLocals::CreateIntermission()
thiscluster = FindClusterInfo (cluster);
if (strncmp (nextlevel, "enDSeQ", 6) == 0)
bool endgame = strncmp (nextlevel, "enDSeQ", 6) == 0;
if (endgame)
{
FName endsequence = ENamedName(strtoll(nextlevel.GetChars()+6, NULL, 16));
// Strife needs a special case here to choose between good and sad ending. Bad is handled elsewhere.
@ -902,6 +903,7 @@ DIntermissionController* FLevelLocals::CreateIntermission()
ext->mDefined & FExitText::DEF_LOOKUP,
false);
}
if (controller) controller->mEndGame = false;
return controller;
}
@ -933,9 +935,35 @@ DIntermissionController* FLevelLocals::CreateIntermission()
}
}
}
if (controller) controller->mEndGame = endgame;
return controller;
}
void RunIntermission(DIntermissionController* intermissionScreen, DObject* statusScreen, std::function<void(bool)> completionf)
{
runner = CreateRunner();
GC::WriteBarrier(runner);
completion = std::move(completionf);
auto func = LookupFunction("DoomCutscenes.BuildMapTransition");
if (func == nullptr)
{
I_Error("Script function 'DoomCutscenes.BuildMapTransition' not found");
}
VMValue val[3] = { runner, intermissionScreen, statusScreen };
VMCall(func, val, 3, nullptr, 0);
if (!ScreenJobValidate())
{
runner->Destroy();
runner = nullptr;
if (completion) completion(false);
completion = nullptr;
return;
}
gameaction = ga_intermission;
}
void G_DoCompleted (void)
{
gameaction = ga_nothing;
@ -972,17 +1000,16 @@ void G_DoCompleted (void)
DObject* statusScreen = nullptr, *intermissionScreen = nullptr;
if (playinter)
{
viewactive = false;
automapactive = false;
// [RH] If you ever get a statistics driver operational, adapt this.
// if (statcopy)
// memcpy (statcopy, &wminfo, sizeof(wminfo));
statusScreen = WI_Start (&staticWmInfo);
}
bool endgame = intermissionScreen && intermissionScreen->mEndGame;
intermissionScreen = primaryLevel->CreateIntermission();
// todo: create start of level screenjob.
RunIntermission(intermissionScreen, statusScreen, [=](bool) { if (!endgame) primaryLevel->WorldDone(); }
)
}
//==========================================================================

View file

@ -196,9 +196,9 @@ void DIntermissionScreen::Init(FIntermissionAction *desc, bool first)
}
int DIntermissionScreen::Responder (event_t *ev)
int DIntermissionScreen::Responder (FInputEvent *ev)
{
if (ev->type == EV_KeyDown)
if (ev->Type == EV_KeyDown)
{
return -1;
}
@ -275,9 +275,9 @@ void DIntermissionScreenFader::Init(FIntermissionAction *desc, bool first)
//
//===========================================================================
int DIntermissionScreenFader::Responder (event_t *ev)
int DIntermissionScreenFader::Responder (FInputEvent *ev)
{
if (ev->type == EV_KeyDown)
if (ev->Type == EV_KeyDown)
{
return -1;
}
@ -367,9 +367,9 @@ void DIntermissionScreenText::Init(FIntermissionAction *desc, bool first)
if (mDuration > 0) mDuration += mTextDelay + mTextSpeed * mTextLen;
}
int DIntermissionScreenText::Responder (event_t *ev)
int DIntermissionScreenText::Responder (FInputEvent *ev)
{
if (ev->type == EV_KeyDown)
if (ev->Type == EV_KeyDown)
{
if (mTicker < mTextDelay + (mTextLen * mTextSpeed))
{
@ -517,9 +517,9 @@ void DIntermissionScreenCast::Init(FIntermissionAction *desc, bool first)
}
}
int DIntermissionScreenCast::Responder (event_t *ev)
int DIntermissionScreenCast::Responder (FInputEvent *ev)
{
if (ev->type != EV_KeyDown) return 0;
if (ev->Type != EV_KeyDown) return 0;
if (castdeath)
return 1; // already in dying frames
@ -715,7 +715,7 @@ void DIntermissionScreenScroller::Init(FIntermissionAction *desc, bool first)
mScrollDir = static_cast<FIntermissionActionScroller*>(desc)->mScrollDir;
}
int DIntermissionScreenScroller::Responder (event_t *ev)
int DIntermissionScreenScroller::Responder (FInputEvent *ev)
{
int res = Super::Responder(ev);
if (res == -1 && !nointerscrollabort)
@ -835,7 +835,7 @@ void DIntermissionScreenScroller::Drawer ()
//
//==========================================================================
DIntermissionController::DIntermissionController(FIntermissionDescriptor *Desc, bool DeleteDesc, uint8_t state)
DIntermissionController::DIntermissionController(FIntermissionDescriptor *Desc, bool DeleteDesc)
{
mDesc = Desc;
mDeleteDesc = DeleteDesc;
@ -844,7 +844,6 @@ DIntermissionController::DIntermissionController(FIntermissionDescriptor *Desc,
mSentAdvance = false;
mScreen = nullptr;
mFirst = true;
mGameState = state;
}
bool DIntermissionController::NextPage ()
@ -903,13 +902,13 @@ again:
return false;
}
bool DIntermissionController::Responder (event_t *ev)
bool DIntermissionController::Responder (FInputEvent *ev)
{
if (mScreen != NULL)
{
if (ev->type == EV_KeyDown)
if (ev->Type == EV_KeyDown)
{
const char *cmd = Bindings.GetBind (ev->data1);
const char *cmd = Bindings.GetBind (ev->KeyScan);
if (cmd != nullptr)
{
@ -954,25 +953,6 @@ void DIntermissionController::Ticker ()
mAdvance = false;
if (!NextPage())
{
switch (mGameState)
{
case FSTATE_InLevel:
primaryLevel->SetMusic();
gamestate = GS_LEVEL;
wipegamestate = GS_LEVEL;
gameaction = ga_resumeconversation;
viewactive = true;
Destroy();
break;
case FSTATE_ChangingLevel:
gameaction = ga_worlddone;
Destroy();
break;
default:
break;
}
}
}
}
@ -1001,16 +981,14 @@ void DIntermissionController::OnDestroy ()
//
//==========================================================================
DIntermissionController* F_StartIntermission(FIntermissionDescriptor *desc, bool deleteme, uint8_t state)
DIntermissionController* F_StartIntermission(FIntermissionDescriptor *desc, bool deleteme)
{
ScaleOverrider s(twod);
S_StopAllChannels ();
gameaction = ga_nothing;
gamestate = GS_FINALE;
if (state == FSTATE_InLevel) wipegamestate = GS_FINALE; // don't wipe when within a level.
viewactive = false;
automapactive = false;
auto CurrentIntermission = Create<DIntermissionController>(desc, deleteme, state);
//if (state == FSTATE_InLevel) wipegamestate = GS_FINALE; // don't wipe when within a level.
auto CurrentIntermission = Create<DIntermissionController>(desc, deleteme);
// If the intermission finishes straight away then cancel the wipe.
if (!CurrentIntermission->NextPage())
@ -1029,7 +1007,7 @@ DIntermissionController* F_StartIntermission(FIntermissionDescriptor *desc, bool
//
//==========================================================================
DIntermissionController* F_StartIntermission(FName seq, uint8_t state)
DIntermissionController* F_StartIntermission(FName seq)
{
FIntermissionDescriptor **pdesc = IntermissionDescriptors.CheckKey(seq);
if (pdesc == nullptr)
@ -1038,10 +1016,38 @@ DIntermissionController* F_StartIntermission(FName seq, uint8_t state)
}
else
{
F_StartIntermission(*pdesc, false, state);
return F_StartIntermission(*pdesc, false);
}
}
DEFINE_ACTION_FUNCTION(DIntermissionController, Responder)
{
PARAM_SELF_PROLOGUE(DIntermissionController);
PARAM_POINTER(evt, FInputEvent);
ACTION_RETURN_BOOL(self->Responder(evt));
}
DEFINE_ACTION_FUNCTION(DIntermissionController, Ticker)
{
PARAM_SELF_PROLOGUE(DIntermissionController);
self->Ticker();
ACTION_RETURN_BOOL(true);
}
DEFINE_ACTION_FUNCTION(DIntermissionController, Drawer)
{
PARAM_SELF_PROLOGUE(DIntermissionController);
self->Ticker();
return 0;
}
DEFINE_ACTION_FUNCTION(DIntermissionController, NextPage)
{
PARAM_SELF_PROLOGUE(DIntermissionController);
ACTION_RETURN_BOOL(self->NextPage());
}
#include "c_dispatch.h"
CCMD(measureintermissions)

View file

@ -10,7 +10,7 @@
#include "g_game.h"
#include "v_text.h"
struct event_t;
struct FInputEvent;
struct FState;
#define DECLARE_SUPER_CLASS(cls,parent) \
@ -176,7 +176,7 @@ public:
DIntermissionScreen() {}
virtual void Init(FIntermissionAction *desc, bool first);
virtual int Responder (event_t *ev);
virtual int Responder (FInputEvent *ev);
virtual int Ticker ();
virtual void Drawer ();
void OnDestroy() override;
@ -202,7 +202,7 @@ public:
DIntermissionScreenFader() {}
virtual void Init(FIntermissionAction *desc, bool first);
virtual int Responder (event_t *ev);
virtual int Responder (FInputEvent *ev);
virtual int Ticker ();
virtual void Drawer ();
};
@ -227,7 +227,7 @@ public:
DIntermissionScreenText() {}
virtual void Init(FIntermissionAction *desc, bool first);
virtual int Responder (event_t *ev);
virtual int Responder (FInputEvent *ev);
virtual void Drawer ();
};
@ -256,7 +256,7 @@ public:
DIntermissionScreenCast() {}
virtual void Init(FIntermissionAction *desc, bool first);
virtual int Responder (event_t *ev);
virtual int Responder (FInputEvent *ev);
virtual int Ticker ();
virtual void Drawer ();
};
@ -275,7 +275,7 @@ public:
DIntermissionScreenScroller() {}
virtual void Init(FIntermissionAction *desc, bool first);
virtual int Responder (event_t *ev);
virtual int Responder (FInputEvent *ev);
virtual void Drawer ();
};
@ -296,14 +296,13 @@ class DIntermissionController : public DObject
bool mDeleteDesc;
bool mFirst;
bool mAdvance, mSentAdvance;
uint8_t mGameState;
int mIndex;
public:
static DIntermissionController *CurrentIntermission;
bool mEndGame;
DIntermissionController(FIntermissionDescriptor *mDesc = NULL, bool mDeleteDesc = false, uint8_t state = FSTATE_ChangingLevel);
bool Responder (event_t *ev);
DIntermissionController(FIntermissionDescriptor *mDesc = NULL, bool mDeleteDesc = false);
bool Responder (FInputEvent *ev);
void Ticker ();
void Drawer ();
void OnDestroy() override;
@ -314,8 +313,8 @@ public:
// Interface for main loop
DIntermissionController* F_StartIntermission(FIntermissionDescriptor *desc, bool deleteme, uint8_t state);
DIntermissionController* F_StartIntermission(FName desc, uint8_t state);
DIntermissionController* F_StartIntermission(FIntermissionDescriptor *desc, bool deleteme);
DIntermissionController* F_StartIntermission(FName desc);
// Create an intermission from old cluster data
DIntermissionController* F_StartFinale (const char *music, int musicorder, int cdtrack, unsigned int cdid, const char *flat,

View file

@ -41,6 +41,7 @@
#include "c_dispatch.h"
#include "gstrings.h"
#include "gi.h"
#include "screenjob.h"
static void ReplaceIntermission(FName intname,FIntermissionDescriptor *desc)
@ -922,7 +923,6 @@ DIntermissionController* F_StartFinale (const char *music, int musicorder, int c
return nullptr;
}
CCMD(testfinale)
{
if (argv.argc() < 2)
@ -954,5 +954,6 @@ CCMD(testfinale)
}
auto controller = F_StartFinale(gameinfo.finaleMusic, gameinfo.finaleOrder, -1, 0, gameinfo.FinaleFlat, text, false, false, true, true);
// todo: play it
RunIntermission(controller, nullptr, [=](bool) { gameaction = ga_nothing; });
}

View file

@ -33,6 +33,7 @@
*/
#include <assert.h>
#include <stdint.h>
#include "actor.h"
#include "p_conversation.h"
@ -489,7 +490,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply
if (!(npc->flags8 & MF8_DONTFACETALKER))
npc->Angles.Yaw = player->ConversationNPCAngle;
npc->flags5 &= ~MF5_INCONVERSATION;
if (gameaction != ga_slideshow) ClearConversationStuff(player);
if (gameaction != ga_intermission) ClearConversationStuff(player);
return;
}
@ -507,7 +508,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply
if (!(npc->flags8 & MF8_DONTFACETALKER))
npc->Angles.Yaw = player->ConversationNPCAngle;
npc->flags5 &= ~MF5_INCONVERSATION;
if (gameaction != ga_slideshow) ClearConversationStuff(player);
if (gameaction != ga_intermission) ClearConversationStuff(player);
return;
}
}
@ -548,7 +549,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply
}
if (reply->GiveType->IsDescendantOf("SlideshowStarter"))
gameaction = ga_slideshow;
G_StartSlideshow(primaryLevel, NAME_None);
}
else
{
@ -617,7 +618,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply
if (!(reply->CloseDialog))
{
if (gameaction != ga_slideshow)
if (gameaction != ga_intermission)
{
P_StartConversation (npc, player->mo, player->ConversationFaceTalker, false);
return;
@ -643,7 +644,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply
// [CW] Set these to NULL because we're not using to them
// anymore. However, this can interfere with slideshows
// so we don't set them to NULL in that case.
if (gameaction != ga_slideshow)
if (gameaction != ga_intermission)
{
npc->flags5 &= ~MF5_INCONVERSATION;
ClearConversationStuff(player);

View file

@ -291,6 +291,8 @@ version "4.6"
#include "zscript/ui/statusbar/statusbar.zs"
#include "zscript/ui/statusbar/strife_sbar.zs"
#include "zscript/ui/intermission.zs"
#include "zscript/compatibility.zs"
#include "zscript/scriptutil/scriptutil.zs"
#include "zscript/actors/mbf21.zs"

View file

@ -1,5 +1,5 @@
class ScreenJob : Object
class ScreenJob : Object UI
{
int flags;
float fadetime; // in milliseconds
@ -299,7 +299,7 @@ class MoviePlayerJob : SkippableScreenJob
//
//---------------------------------------------------------------------------
class ScreenJobRunner : Object
class ScreenJobRunner : Object UI
{
enum ERunState
{

View file

@ -1,11 +1,13 @@
class IntermissionController native
class IntermissionController native ui
{
// This is mostly a black box to the native intermission code.
// May be scriptified later, but right now we do not need it.
static native IntermissionController Creeate(String music, int musicorder, String flat, String text, int textInLump, int finalePic, int lookupText, bool ending, Name endsequence);
/*
static native IntermissionController Create(String music, int musicorder, String flat, String text, int textInLump, int finalePic, int lookupText, bool ending, Name endsequence);
static native IntermissionController CreateNamed(Name nm);
*/
native bool Responder(InputEvent ev);
native bool Ticker();
native void Drawer();
@ -16,21 +18,12 @@ class IntermissionController native
class IntermissionScreenJob : ScreenJob
{
IntermissionController controller;
void Init(String music, int musicorder, String flat, String text, int textInLump, int finalePic, int lookupText, bool ending, Name endsequence)
{
controller = IntermissionController.Create(music, musicorder, flat, text, textInLump, finalePic, lookupText, ending, endsequence);
}
void InitNamed(Name nm)
{
controller = IntermissionController.CreateNamed(nm);
}
void Init(IntermissionController ctrl) { controller = ctrl; }
override bool OnEvent(InputEvent evt) { return controller.Responder(evt); }
virtual void OnTick() { if (!controller.Ticker()) jobstate = finished; }
virtual void Draw(double smoothratio) { controller.Drawer(); }
virtual void OnSkip() { if (!controller.NextPage()) jobstate = finished; }
override void OnTick() { if (!controller.Ticker()) jobstate = finished; }
override void Draw(double smoothratio) { controller.Drawer(); }
override void OnDestroy()
{
@ -40,7 +33,7 @@ class IntermissionScreenJob : ScreenJob
}
class StatusScreenJob : ScreenJob
class StatusScreenJob : SkippableScreenJob
{
StatusScreen controller;
@ -49,14 +42,35 @@ class StatusScreenJob : ScreenJob
controller = scr;
}
override bool OnEvent(InputEvent evt) { return controller.Responder(evt); }
virtual void OnTick() { controller.Ticker(); if (controller.CurState == StatusScreen.LeavingIntermission) jobstate = finished; }
virtual void Draw(double smoothratio) { controller.Drawer(); }
virtual void OnSkip() { if (!controller.NextStage()) jobstate = finished; }
override void OnTick() { controller.Ticker(); if (controller.CurState == StatusScreen.LeavingIntermission) jobstate = finished; }
override void Draw(double smoothratio) { controller.Drawer(); }
override void OnSkip() { controller.NextStage(); } // skipping status screens is asynchronous, so yields no result
override void OnDestroy()
{
controller.Destroy();
Super.OnDestroy();
}
}
}
class DoomCutscenes
{
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void BuildMapTransition(ScreenJobRunner runner, IntermissionController inter, StatusScreen status)
{
if (status)
{
runner.Append(new("StatusScreenJob").Init(status));
}
if (inter)
{
runner.Append(new("IntermissionScreenJob").Init(inter));
}
}
}

View file

@ -796,25 +796,9 @@ class StatusScreen abstract play version("2.5")
//
// ====================================================================
protected void checkForAccelerate(void)
void nextStage(void)
{
int i;
// check for button presses to skip delays
for (i = 0; i < MAXPLAYERS; i++)
{
PlayerInfo player = players[i];
if (playeringame[i])
{
if ((player.cmd.buttons ^ player.oldbuttons) &&
((player.cmd.buttons & player.oldbuttons) == player.oldbuttons) && player.Bot == NULL)
{
acceleratestage = 1;
playerready[i] = true;
}
player.oldbuttons = player.buttons;
}
}
accelerateStage = 1;
}
// ====================================================================

View file

@ -216,16 +216,8 @@ class CoopStatusScreen : StatusScreen
}
else if (ng_state == 12)
{
int i;
for (i = 0; i < MAXPLAYERS; i++)
{
// If the player is in the game and not ready, stop checking
if (playeringame[i] && players[i].Bot == NULL && !playerready[i])
break;
}
// All players are ready; proceed.
if ((i == MAXPLAYERS && acceleratestage) || autoskip)
if ((acceleratestage) || autoskip)
{
PlaySound("intermission/pastcoopstats");
initShowNextLoc();
@ -311,7 +303,7 @@ class CoopStatusScreen : StatusScreen
screen.Dim(player.GetDisplayColor(), 0.8f, x, y - ypadding, (secret_x - x) + (8 * CleanXfac), lineheight);
if (playerready[i] || player.Bot != NULL) // Bots are automatically assumed ready, to prevent confusion
//if (playerready[i] || player.Bot != NULL) // Bots are automatically assumed ready, to prevent confusion
screen.DrawTexture(readyico, true, x - (readysize.Y * CleanXfac), y, DTA_CleanNoMove, true);
Color thiscolor = GetRowColor(player, i == consoleplayer);

View file

@ -124,16 +124,8 @@ class DeathmatchStatusScreen : StatusScreen
}
else if (ng_state == 6)
{
int i;
for (i = 0; i < MAXPLAYERS; i++)
{
// If the player is in the game and not ready, stop checking
if (playeringame[i] && players[i].Bot == NULL && !playerready[i])
break;
}
// All players are ready; proceed.
if ((i == MAXPLAYERS && acceleratestage) || doautoskip)
if ((acceleratestage) || doautoskip)
{
PlaySound("intermission/pastdmstats");
initShowNextLoc();
@ -207,7 +199,7 @@ class DeathmatchStatusScreen : StatusScreen
screen.Dim(player.GetDisplayColor(), 0.8, x, y - ypadding, (deaths_x - x) + (8 * CleanXfac), lineheight);
if (playerready[pnum] || player.Bot != NULL) // Bots are automatically assumed ready, to prevent confusion
//if (playerready[pnum] || player.Bot != NULL) // Bots are automatically assumed ready, to prevent confusion
screen.DrawTexture(readyico, true, x - (readysize.X * CleanXfac), y, DTA_CleanNoMove, true);
let thiscolor = GetRowColor(player, pnum == consoleplayer);
@ -247,4 +239,4 @@ class DeathmatchStatusScreen : StatusScreen
String leveltime = Stringtable.Localize("$SCORE_LVLTIME") .. ": " .. String.Format("%02i:%02i:%02i", hours, minutes, seconds);
drawTextScaled(displayFont, x, y, leveltime, FontScale, textcolor);
}
}
}