From 1022564cab5591e1846cbdc2c386a9653eea8034 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 22 Apr 2021 18:52:39 +0200 Subject: [PATCH] - initial framework for scriptification of screen jobs. --- source/common/2d/v_draw.cpp | 8 ++ .../common/scripting/interface/vmnatives.cpp | 15 +++ source/core/screenjob.cpp | 96 +++++++++++++++++++ source/core/screenjob.h | 10 +- source/games/duke/src/sounds.cpp | 9 ++ wadsrc/static/zscript.txt | 3 + wadsrc/static/zscript/engine/base.zs | 2 + wadsrc/static/zscript/games/duke/dukegame.zs | 26 +++++ .../static/zscript/games/duke/ui/screens.zs | 35 +++++++ wadsrc/static/zscript/screenjob.zs | 87 +++++++++++++++++ 10 files changed, 289 insertions(+), 2 deletions(-) create mode 100644 wadsrc/static/zscript/games/duke/dukegame.zs create mode 100644 wadsrc/static/zscript/games/duke/ui/screens.zs create mode 100644 wadsrc/static/zscript/screenjob.zs diff --git a/source/common/2d/v_draw.cpp b/source/common/2d/v_draw.cpp index 70bf53042..7250a11c9 100644 --- a/source/common/2d/v_draw.cpp +++ b/source/common/2d/v_draw.cpp @@ -324,6 +324,14 @@ DEFINE_ACTION_FUNCTION(_Screen, ClearClipRect) return 0; } +DEFINE_ACTION_FUNCTION(_Screen, ClearScreen) +{ + PARAM_PROLOGUE; + twod->ClearScreen(); + return 0; +} + + void F2DDrawer::GetClipRect(int *x, int *y, int *w, int *h) { if (x) *x = clipleft; diff --git a/source/common/scripting/interface/vmnatives.cpp b/source/common/scripting/interface/vmnatives.cpp index 502d78de3..c196c7d93 100644 --- a/source/common/scripting/interface/vmnatives.cpp +++ b/source/common/scripting/interface/vmnatives.cpp @@ -49,6 +49,7 @@ #include "s_music.h" #include "i_interface.h" #include "base_sbar.h" +#include "image.h" //========================================================================== // @@ -477,6 +478,20 @@ DEFINE_ACTION_FUNCTION_NATIVE(_TexMan, OkForLocalization, OkForLocalization_) ACTION_RETURN_INT(OkForLocalization_(name, subst)); } +static int UseGamePalette(int index) +{ + auto tex = TexMan.GameByIndex(index, false); + if (!tex) return false; + auto image = tex->GetTexture()->GetImage(); + return image ? image->UseGamePalette() : false; +} + +DEFINE_ACTION_FUNCTION_NATIVE(_TexMan, UseGamePalette, UseGamePalette) +{ + PARAM_PROLOGUE; + PARAM_INT(texid); + ACTION_RETURN_INT(UseGamePalette(texid)); +} //===================================================================================== // diff --git a/source/core/screenjob.cpp b/source/core/screenjob.cpp index 8e8b83bd8..b80f22a39 100644 --- a/source/core/screenjob.cpp +++ b/source/core/screenjob.cpp @@ -51,11 +51,107 @@ #include #include #include "raze_music.h" +#include "vm.h" IMPLEMENT_CLASS(DScreenJob, true, false) +IMPLEMENT_CLASS(DSkippableScreenJob, true, false) +IMPLEMENT_CLASS(DBlackScreen, true, false) IMPLEMENT_CLASS(DImageScreen, true, false) +DEFINE_FIELD(DScreenJob, flags) +DEFINE_FIELD(DScreenJob, fadetime) +DEFINE_FIELD_NAMED(DScreenJob, state, jobstate) +DEFINE_FIELD(DScreenJob, fadestate) +DEFINE_FIELD(DScreenJob, ticks) +DEFINE_FIELD(DScreenJob, pausable) + +DEFINE_FIELD(DBlackScreen, wait) +DEFINE_FIELD(DBlackScreen, cleared) + +DEFINE_FIELD(DImageScreen, tilenum) +DEFINE_FIELD(DImageScreen, trans) +DEFINE_FIELD(DImageScreen, waittime) +DEFINE_FIELD(DImageScreen, cleared) +DEFINE_FIELD(DImageScreen, texid) + +DEFINE_ACTION_FUNCTION(DScreenJob, Init) +{ + // todo + return 0; +} + +DEFINE_ACTION_FUNCTION(DScreenJob, ProcessInput) +{ + PARAM_SELF_PROLOGUE(DScreenJob); + ACTION_RETURN_BOOL(self->ProcessInput()); +} + +DEFINE_ACTION_FUNCTION(DScreenJob, Start) +{ + PARAM_SELF_PROLOGUE(DScreenJob); + self->Start(); + return 0; +} + +DEFINE_ACTION_FUNCTION(DScreenJob, OnEvent) +{ + PARAM_SELF_PROLOGUE(DScreenJob); + PARAM_POINTER(evt, FInputEvent); + if (evt->Type != EV_KeyDown) + { + // not needed in the transition phase + ACTION_RETURN_BOOL(false); + } + event_t ev = {}; + ev.type = EV_KeyDown; + ev.data1 = evt->KeyScan; + ACTION_RETURN_BOOL(self->OnEvent(&ev)); +} + +DEFINE_ACTION_FUNCTION(DScreenJob, OnTick) +{ + PARAM_SELF_PROLOGUE(DScreenJob); + self->OnTick(); + return 0; +} + +DEFINE_ACTION_FUNCTION(DScreenJob, Draw) +{ + PARAM_SELF_PROLOGUE(DScreenJob); + PARAM_FLOAT(smooth); + self->Draw(smooth); + return 0; +} + +DEFINE_ACTION_FUNCTION(DSkippableScreenJob, Init) +{ + // todo + return 0; +} + +DEFINE_ACTION_FUNCTION(DSkippableScreenJob, Skipped) +{ + PARAM_SELF_PROLOGUE(DSkippableScreenJob); + self->Skipped(); + return 0; +} + +DEFINE_ACTION_FUNCTION(DBlackScreen, Init) +{ + // todo + return 0; +} + +DEFINE_ACTION_FUNCTION(DImageScreen, Init) +{ + // todo + return 0; +} + + + + void DScreenJob::OnDestroy() { if (flags & stopmusic) Mus_Stop(); diff --git a/source/core/screenjob.h b/source/core/screenjob.h index aa02c075e..3916a3373 100644 --- a/source/core/screenjob.h +++ b/source/core/screenjob.h @@ -12,12 +12,13 @@ class ScreenJobRunner; class DScreenJob : public DObject { DECLARE_CLASS(DScreenJob, DObject) +public: const int flags; const float fadetime; // in milliseconds int fadestate = fadein; friend class ScreenJobRunner; -protected: +//protected: int ticks = 0; int state = running; bool pausable = true; @@ -74,7 +75,8 @@ public: class DSkippableScreenJob : public DScreenJob { -protected: + DECLARE_CLASS(DSkippableScreenJob, DScreenJob) +public: DSkippableScreenJob(int fade = 0, float fadet = 250.f) : DScreenJob(fade, fadet) {} @@ -90,6 +92,8 @@ protected: class DBlackScreen : public DScreenJob { + DECLARE_CLASS(DBlackScreen, DScreenJob) +public: int wait; bool cleared = false; @@ -109,10 +113,12 @@ class DImageScreen : public DSkippableScreenJob { DECLARE_CLASS(DImageScreen, DScreenJob) +public: int tilenum = -1; int trans; int waittime; // in ms. bool cleared = false; + FTextureID texid; FGameTexture* tex = nullptr; public: diff --git a/source/games/duke/src/sounds.cpp b/source/games/duke/src/sounds.cpp index c9214b65b..8a4abf5ff 100644 --- a/source/games/duke/src/sounds.cpp +++ b/source/games/duke/src/sounds.cpp @@ -46,6 +46,7 @@ source as it is released. #include "gamestate.h" #include "names_d.h" #include "i_music.h" +#include "vm.h" CVAR(Bool, wt_forcemidi, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // quick hack to disable the oggs, which are of lower quality than playing the MIDIs with a good synth and sound font. CVAR(Bool, wt_forcevoc, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // The same for sound effects. The re-recordings are rather poor and disliked @@ -719,6 +720,14 @@ void S_PlaySpecialMusic(unsigned int m) } } +DEFINE_ACTION_FUNCTION_NATIVE(_Duke, PlaySpecialMusic, S_PlaySpecialMusic) +{ + PARAM_PROLOGUE; + PARAM_INT(song); + S_PlaySpecialMusic(song); + return 0; +} + //--------------------------------------------------------------------------- // // diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index da000f758..44b9bc8ee 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -28,6 +28,9 @@ version "4.3" #include "zscript/constants.zs" #include "zscript/razebase.zs" +#include "zscript/screenjob.zs" +#include "zscript/games/duke/dukegame.zs" +#include "zscript/games/duke/ui/screens.zs" #include "zscript/games/duke/ui/menu.zs" #include "zscript/games/blood/ui/menu.zs" #include "zscript/games/sw/ui/menu.zs" diff --git a/wadsrc/static/zscript/engine/base.zs b/wadsrc/static/zscript/engine/base.zs index a0b2a0c83..3a3a4fb3b 100644 --- a/wadsrc/static/zscript/engine/base.zs +++ b/wadsrc/static/zscript/engine/base.zs @@ -239,6 +239,7 @@ struct TexMan native static Vector2 GetScaledOffset(TextureID tex); native static int CheckRealHeight(TextureID tex); native static bool OkForLocalization(TextureID patch, String textSubstitute); + native static bool UseGamePalette(TextureID tex); } enum EScaleMode @@ -402,6 +403,7 @@ struct Screen native native static int, int, int, int GetViewWindow(); native static double, double, double, double GetFullscreenRect(double vwidth, double vheight, int fsmode); native static Vector2 SetOffset(double x, double y); + native static void ClearScreen(color col = 0); } struct Font native diff --git a/wadsrc/static/zscript/games/duke/dukegame.zs b/wadsrc/static/zscript/games/duke/dukegame.zs new file mode 100644 index 000000000..7b47cff15 --- /dev/null +++ b/wadsrc/static/zscript/games/duke/dukegame.zs @@ -0,0 +1,26 @@ +// contains all global Duke definitions +struct Duke native +{ + enum ESpecialMusic + { + MUS_INTRO = 0, + MUS_BRIEFING = 1, + MUS_LOADING = 2, + }; + + enum EPalette + { + BASEPAL = 0, + WATERPAL, + SLIMEPAL, + TITLEPAL, + DREALMSPAL, + ENDINGPAL, // 5 + ANIMPAL, // not used anymore. The anim code now generates true color textures. + DRUGPAL, + BASEPALCOUNT + }; + + + native static void PlaySpecialMusic(int which); +} diff --git a/wadsrc/static/zscript/games/duke/ui/screens.zs b/wadsrc/static/zscript/games/duke/ui/screens.zs new file mode 100644 index 000000000..324e0a03e --- /dev/null +++ b/wadsrc/static/zscript/games/duke/ui/screens.zs @@ -0,0 +1,35 @@ + + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +class DRealmsScreen : SkippableScreenJob +{ + void Init() + { + Super.Init(fadein | fadeout); + } + + override void Start() + { + Duke.PlaySpecialMusic(Duke.MUS_INTRO); + } + + override void OnTick() + { + if (ticks >= 7 * GameTicRate) jobstate = finished; + } + + override void Draw(double smoothratio) + { + let tex = TexMan.CheckForTexture("DREALMS"); + int translation = TexMan.UseGamePalette(tex)? Translation.MakeID(Translation_BasePalette, Duke.DREALMSPAL) : 0; + + screen.ClearScreen(); + screen.DrawTexture(tex, true, 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, DTA_TranslationIndex, translation, DTA_LegacyRenderStyle, STYLE_Normal); + } +} + diff --git a/wadsrc/static/zscript/screenjob.zs b/wadsrc/static/zscript/screenjob.zs new file mode 100644 index 000000000..5c8f7f25a --- /dev/null +++ b/wadsrc/static/zscript/screenjob.zs @@ -0,0 +1,87 @@ + +class ScreenJob native +{ + native int flags; + native float fadetime; // in milliseconds + native int fadestate; + + native int ticks; + native int jobstate; + native bool pausable; + + enum EJobState + { + running = 1, // normal operation + skipped = 2, // finished by user skipping + finished = 3, // finished by completing its sequence + stopping = 4, // running ending animations / fadeout, etc. Will not accept more input. + stopped = 5, // we're done here. + }; + enum EJobFlags + { + visible = 0, + fadein = 1, + fadeout = 2, + stopmusic = 4, + stopsound = 8, + }; + + native void Init(int flags = 0, float fadet = 250.f); + native virtual bool ProcessInput(); + native virtual void Start(); + native virtual bool OnEvent(InputEvent evt); + native virtual void OnTick(); + native virtual void Draw(double smoothratio); + + //native int DrawFrame(double smoothratio); + //native int GetFadeState(); + //native override void OnDestroy(); +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +class SkippableScreenJob : ScreenJob native +{ + native void Init(int flags = 0, float fadet = 250.f); + //native override bool OnEvent(InputEvent evt); + virtual void Skipped() {} +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +class BlackScreen : ScreenJob native +{ + native int wait; + native bool cleared; + + native void Init(int w, int flags = 0); + //override void OnTick(); + //override void Draw(double smooth); +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +class ImageScreen : SkippableScreenJob native +{ + native int tilenum; + native int trans; + native int waittime; // in ms. + native bool cleared; + native TextureID texid; + + native void Init(TextureID tex, int fade = fadein | fadeout, int wait = 3000, int translation = 0); + //override void OnTick(); + //override void Draw(double smooth); +}