From ca98f33f42c4c15c3c88202a41e5ea71ecdb0779 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Tue, 8 Jul 2025 14:19:29 -0400 Subject: [PATCH] Added support for client-side VisualThinkers --- src/d_net.cpp | 2 +- src/playsim/p_effect.cpp | 11 ++++++----- src/playsim/p_visualthinker.h | 2 +- wadsrc/static/zscript/doombase.zs | 2 +- wadsrc/static/zscript/visualthinker.zs | 4 ++-- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/d_net.cpp b/src/d_net.cpp index 084943e19..5565b1871 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -2714,7 +2714,7 @@ void Net_DoCommand(int cmd, uint8_t **stream, int player) if (typeinfo && typeinfo->IsDescendantOf("VisualThinker")) { DVector3 spawnpos = source->Vec3Angle(source->radius * 4, source->Angles.Yaw, 8.); - auto vt = DVisualThinker::NewVisualThinker(source->Level, typeinfo); + auto vt = DVisualThinker::NewVisualThinker(source->Level, typeinfo, false); if (vt) { vt->PT.Pos = spawnpos; diff --git a/src/playsim/p_effect.cpp b/src/playsim/p_effect.cpp index 62db58742..5ad982159 100644 --- a/src/playsim/p_effect.cpp +++ b/src/playsim/p_effect.cpp @@ -1033,7 +1033,7 @@ DVisualThinker* DVisualThinker::GetNext() const return _next; } -DVisualThinker* DVisualThinker::NewVisualThinker(FLevelLocals* Level, PClass* type) +DVisualThinker* DVisualThinker::NewVisualThinker(FLevelLocals* Level, PClass* type, bool clientSide) { if (type == nullptr) { @@ -1050,7 +1050,7 @@ DVisualThinker* DVisualThinker::NewVisualThinker(FLevelLocals* Level, PClass* ty return nullptr; } - auto zs = static_cast(Level->CreateThinker(type, DVisualThinker::DEFAULT_STAT)); + auto zs = static_cast(clientSide ? Level->CreateClientsideThinker(type, DVisualThinker::DEFAULT_STAT) : Level->CreateThinker(type, DVisualThinker::DEFAULT_STAT)); zs->Construct(); IFOVERRIDENVIRTUALPTRNAME(zs, NAME_VisualThinker, BeginPlay) @@ -1065,9 +1065,9 @@ DVisualThinker* DVisualThinker::NewVisualThinker(FLevelLocals* Level, PClass* ty return zs; } -static DVisualThinker* SpawnVisualThinker(FLevelLocals* Level, PClass* type) +static DVisualThinker* SpawnVisualThinker(FLevelLocals* Level, PClass* type, bool clientSide) { - return DVisualThinker::NewVisualThinker(Level, type); + return DVisualThinker::NewVisualThinker(Level, type, clientSide); } void DVisualThinker::UpdateSector(subsector_t * newSubsector) @@ -1101,7 +1101,8 @@ DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, SpawnVisualThinker, SpawnVisualThink { PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); PARAM_CLASS_NOT_NULL(type, DVisualThinker); - DVisualThinker* zs = SpawnVisualThinker(self, type); + PARAM_BOOL(clientSide); + DVisualThinker* zs = SpawnVisualThinker(self, type, clientSide); ACTION_RETURN_OBJECT(zs); } diff --git a/src/playsim/p_visualthinker.h b/src/playsim/p_visualthinker.h index 69faada9f..d6317e92d 100644 --- a/src/playsim/p_visualthinker.h +++ b/src/playsim/p_visualthinker.h @@ -55,7 +55,7 @@ public: void OnDestroy() override; DVisualThinker* GetNext() const; - static DVisualThinker* NewVisualThinker(FLevelLocals* Level, PClass* type); + static DVisualThinker* NewVisualThinker(FLevelLocals* Level, PClass* type, bool clientSide); void SetTranslation(FName trname); int GetRenderStyle() const; bool isFrozen(); diff --git a/wadsrc/static/zscript/doombase.zs b/wadsrc/static/zscript/doombase.zs index 79a96c30d..ca4361d7c 100644 --- a/wadsrc/static/zscript/doombase.zs +++ b/wadsrc/static/zscript/doombase.zs @@ -624,7 +624,7 @@ struct LevelLocals native native String GetEpisodeName(); native void SpawnParticle(FSpawnParticleParams p); - native VisualThinker SpawnVisualThinker(Class type); + native VisualThinker SpawnVisualThinker(Class type, bool clientSide = false); clearscope native static bool WorldPaused(); } diff --git a/wadsrc/static/zscript/visualthinker.zs b/wadsrc/static/zscript/visualthinker.zs index 34c4643f5..a926243b6 100644 --- a/wadsrc/static/zscript/visualthinker.zs +++ b/wadsrc/static/zscript/visualthinker.zs @@ -37,11 +37,11 @@ Class VisualThinker : Thinker native native protected void UpdateSpriteInfo(); // needs to be called every time the texture is updated if the thinker uses SPF_LOCAL_ANIM and is set to a non-ticking statnum (or if Tick is overriden and doesn't call Super.Tick()) static VisualThinker Spawn(Class type, TextureID tex, Vector3 pos, Vector3 vel = (0,0,0), double alpha = 1.0, int flags = 0, - double roll = 0.0, Vector2 scale = (1,1), Vector2 offset = (0,0), int style = STYLE_Normal, TranslationID trans = 0, int VisualThinkerFlags = 0) + double roll = 0.0, Vector2 scale = (1,1), Vector2 offset = (0,0), int style = STYLE_Normal, TranslationID trans = 0, int VisualThinkerFlags = 0, bool clientSide = false) { if (!Level) return null; - let p = level.SpawnVisualThinker(type); + let p = level.SpawnVisualThinker(type, clientSide); if (p) { p.Texture = tex;