diff --git a/src/g_level.cpp b/src/g_level.cpp index 05b02744b..23fc0cca6 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1968,6 +1968,7 @@ void FLevelLocals::Tick () void FLevelLocals::Mark() { + GC::Mark(SpotState); GC::Mark(FraggleScriptThinker); canvasTextureInfo.Mark(); for (auto &s : sectorPortals) diff --git a/src/g_levellocals.h b/src/g_levellocals.h index 195da752a..f24d448e1 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -48,6 +48,7 @@ #include "r_data/r_canvastexture.h" class DFraggleThinker; +class DSpotState; struct FLevelData { @@ -202,7 +203,9 @@ struct FLevelLocals : public FLevelData FDynamicLight *lights; // links to global game objects - TObjPtr FraggleScriptThinker; + TArray> CorpseQueue; + TObjPtr FraggleScriptThinker = nullptr; + TObjPtr SpotState = nullptr; bool IsJumpingAllowed() const; bool IsCrouchingAllowed() const; diff --git a/src/g_shared/a_specialspot.cpp b/src/g_shared/a_specialspot.cpp index f677adc13..c8261208c 100644 --- a/src/g_shared/a_specialspot.cpp +++ b/src/g_shared/a_specialspot.cpp @@ -42,7 +42,6 @@ static FRandom pr_spot ("SpecialSpot"); IMPLEMENT_CLASS(DSpotState, false, false) -TObjPtr DSpotState::SpotState; //---------------------------------------------------------------------------- // @@ -198,16 +197,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FSpotList &list, FSpot //---------------------------------------------------------------------------- DSpotState::DSpotState () -: DThinker (STAT_INFO) { - if (SpotState) - { - I_Error ("Only one SpotState is allowed to exist at a time.\nCheck your code."); - } - else - { - SpotState = this; - } } //---------------------------------------------------------------------------- @@ -219,8 +209,6 @@ DSpotState::DSpotState () void DSpotState::OnDestroy () { SpotLists.Reset(); - - SpotState = NULL; Super::OnDestroy(); } @@ -240,18 +228,6 @@ void DSpotState::Tick () // //---------------------------------------------------------------------------- -DSpotState *DSpotState::GetSpotState(bool create) -{ - if (SpotState == NULL && create) SpotState = Create(); - return SpotState; -} - -//---------------------------------------------------------------------------- -// -// -// -//---------------------------------------------------------------------------- - FSpotList *DSpotState::FindSpotList(PClassActor *type) { if (type == nullptr) return nullptr; diff --git a/src/g_shared/a_specialspot.h b/src/g_shared/a_specialspot.h index fee1a804b..1599c3cf1 100644 --- a/src/g_shared/a_specialspot.h +++ b/src/g_shared/a_specialspot.h @@ -7,10 +7,9 @@ struct FSpotList; -class DSpotState : public DThinker +class DSpotState : public DObject { - DECLARE_CLASS(DSpotState, DThinker) - static TObjPtr SpotState; + DECLARE_CLASS(DSpotState, DObject) TArray SpotLists; public: diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 25b1d8fa2..0d205c0d4 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -2981,6 +2981,8 @@ enum T_Flags TF_SENSITIVEZ = 0x00000800, // Fail if the actor wouldn't fit in the position (for Z). }; +DSpotState *GetSpotState(FLevelLocals *self, int create); + DEFINE_ACTION_FUNCTION(AActor, A_Teleport) { PARAM_ACTION_PROLOGUE(AActor); @@ -3037,7 +3039,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Teleport) } } - DSpotState *state = DSpotState::GetSpotState(); + DSpotState *state = GetSpotState(&level, false); if (state == NULL) { return numret; diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 890f51715..d63c9f5e4 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -976,6 +976,7 @@ void G_SerializeLevel(FSerializer &arc, bool hubload) ("level.bodyqueslot", level.bodyqueslot) ("level.spawnindex", level.spawnindex) .Array("level.bodyque", level.bodyque, level.BODYQUESIZE) + ("level.spotstate", level.SpotState) ("level.fragglethinker", level.FraggleScriptThinker); // Hub transitions must keep the current total time diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 45fd3f8ca..6ffb35af8 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -69,6 +69,7 @@ #include "i_time.h" #include "scripting/vm/vm.h" #include "fragglescript/t_fs.h" +#include "a_specialspot.h" #include "maploader/maploader.h" void P_ClearUDMFKeys(); @@ -273,6 +274,7 @@ void FLevelLocals::ClearLevelData() } ClearPortals(); + SpotState = nullptr; canvasTextureInfo.EmptyList(); sections.Clear(); segs.Clear(); diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index 0f66fc266..10f10b992 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -1957,13 +1957,6 @@ DEFINE_ACTION_FUNCTION_NATIVE(FWeaponSlots, SetupWeaponSlots, FWeaponSlots::Setu //===================================================================================== -DEFINE_ACTION_FUNCTION_NATIVE(DSpotState, GetSpotState, DSpotState::GetSpotState) -{ - PARAM_PROLOGUE; - PARAM_BOOL(create); - ACTION_RETURN_OBJECT(DSpotState::GetSpotState(create)); -} - static void AddSpot(DSpotState *state, AActor *spot) { state->AddSpot(spot); @@ -2506,6 +2499,20 @@ DEFINE_ACTION_FUNCTION_NATIVE(DHUDFont, Create, CreateHudFont) // //===================================================================================== +DSpotState *GetSpotState(FLevelLocals *self, int create) +{ + if (create && self->SpotState == nullptr) self->SpotState = Create(); + GC::WriteBarrier(self->SpotState); + return self->SpotState; +} + +DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, GetSpotState, GetSpotState) +{ + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); + PARAM_INT(create); + ACTION_RETURN_POINTER(GetSpotState(self, create)); +} + static void FormatMapName(FLevelLocals *self, int cr, FString *result) { char mapnamecolor[3] = { '\34', char(cr + 'A'), 0 }; diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index fd4cb3d79..cfcf37e90 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -1,4 +1,4 @@ -version "3.7" +version "3.8" #include "zscript/base.txt" #include "zscript/sounddata.txt" #include "zscript/mapdata.txt" diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index ef4fa3bb0..e7d0436f7 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -687,6 +687,7 @@ struct LevelLocals native native bool IsCrouchingAllowed() const; native bool IsFreelookAllowed() const; native void StartIntermission(Name type, int state) const; + native SpotState GetSpotState(bool create = true); native static clearscope bool IsPointInMap(vector3 p); diff --git a/wadsrc/static/zscript/doom/bossbrain.txt b/wadsrc/static/zscript/doom/bossbrain.txt index 41954c3ca..a3b96d7fa 100644 --- a/wadsrc/static/zscript/doom/bossbrain.txt +++ b/wadsrc/static/zscript/doom/bossbrain.txt @@ -219,7 +219,7 @@ extend class Actor void A_BrainSpit(class spawntype = null) { - SpotState spstate = SpotState.GetSpotState(); + SpotState spstate = Level.GetSpotState(); Actor targ; Actor spit; bool isdefault = false; diff --git a/wadsrc/static/zscript/heretic/dsparil.txt b/wadsrc/static/zscript/heretic/dsparil.txt index c8c78bb8e..21e94ed1a 100644 --- a/wadsrc/static/zscript/heretic/dsparil.txt +++ b/wadsrc/static/zscript/heretic/dsparil.txt @@ -293,7 +293,7 @@ class Sorcerer2 : Actor void DSparilTeleport () { - SpotState state = SpotState.GetSpotState(); + SpotState state = Level.GetSpotState(); if (state == null) return; Actor spot = state.GetSpotWithMinMaxDistance("BossSpot", pos.x, pos.y, 128, 0); diff --git a/wadsrc/static/zscript/inventory/inventory.txt b/wadsrc/static/zscript/inventory/inventory.txt index f0eb1bf3a..7a6d4fd6b 100644 --- a/wadsrc/static/zscript/inventory/inventory.txt +++ b/wadsrc/static/zscript/inventory/inventory.txt @@ -265,7 +265,7 @@ class Inventory : Actor if (SpawnPointClass != NULL) { Actor spot = NULL; - let state = SpotState.GetSpotState(); + let state = Level.GetSpotState(); if (state != NULL) spot = state.GetRandomSpot(SpawnPointClass, false); if (spot != NULL) diff --git a/wadsrc/static/zscript/shared/specialspot.txt b/wadsrc/static/zscript/shared/specialspot.txt index e62e27e7a..fdf357b2a 100644 --- a/wadsrc/static/zscript/shared/specialspot.txt +++ b/wadsrc/static/zscript/shared/specialspot.txt @@ -1,6 +1,9 @@ class SpotState : Object native { - native static SpotState GetSpotState(bool create = true); + deprecated ("3.8") static SpotState GetSpotState(bool create = true) + { + return level.GetSpotState(create); + } native SpecialSpot GetNextInList(class type, int skipcounter); native SpecialSpot GetSpotWithMinMaxDistance(Class type, double x, double y, double mindist, double maxdist); native SpecialSpot GetRandomSpot(class type, bool onlyonce); @@ -13,7 +16,7 @@ class SpecialSpot : Actor { override void BeginPlay() { - let sstate = SpotState.GetSpotState(); + let sstate = Level.GetSpotState(); if (sstate != NULL) sstate.AddSpot(self); Super.BeginPlay(); } @@ -26,7 +29,7 @@ class SpecialSpot : Actor override void OnDestroy() { - let sstate = SpotState.GetSpotState(false); + let sstate = Level.GetSpotState(false); if (sstate != NULL) sstate.RemoveSpot(self); Super.OnDestroy(); } @@ -40,7 +43,7 @@ class SpecialSpot : Actor void A_SpawnSingleItem(class cls, int fail_sp = 0, int fail_co = 0, int fail_dm = 0) { Actor spot = NULL; - let state = SpotState.GetSpotState(); + let state = Level.GetSpotState(); if (state != NULL) spot = state.GetRandomSpot(GetClass(), true); if (spot == NULL) return;