diff --git a/src/gamedata/decallib.cpp b/src/gamedata/decallib.cpp index 609a87687..eb2192e6a 100644 --- a/src/gamedata/decallib.cpp +++ b/src/gamedata/decallib.cpp @@ -871,6 +871,13 @@ void FDecalLib::AddDecal (FDecalBase *decal) } } +FDecalBase* FDecalLib::GetDecalBaseByName(const char* name) const +{ + if (name == nullptr) + return nullptr; + return ScanTreeForName(name, Root); +} + const FDecalTemplate *FDecalLib::GetDecalByNum (uint16_t num) const { if (num == 0) diff --git a/src/gamedata/decallib.h b/src/gamedata/decallib.h index 9bb3b9ce5..b466bda06 100644 --- a/src/gamedata/decallib.h +++ b/src/gamedata/decallib.h @@ -99,6 +99,7 @@ public: void ReadDecals (FScanner &sc); void ReadAllDecals (); + FDecalBase* GetDecalBaseByName(const char* name) const; const FDecalTemplate *GetDecalByNum (uint16_t num) const; const FDecalTemplate *GetDecalByName (const char *name) const; diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 260ecf623..4e034ebff 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -434,7 +434,8 @@ void AActor::Serialize(FSerializer &arc) ("premorphproperties", PremorphProperties) ("morphexitflash", MorphExitFlash) ("damagesource", damagesource) - ("behaviors", Behaviors); + ("behaviors", Behaviors) + A("decalgenerator", DecalGenerator); SerializeTerrain(arc, "floorterrain", floorterrain, &def->floorterrain); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index db69e09b9..d3c9b35b6 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -58,6 +58,7 @@ #include "types.h" #include "dictionary.h" #include "events.h" +#include "decallib.h" static TArray properties; static TArray AFTable; @@ -779,6 +780,21 @@ void InitThingdef() skillstruct->Size = sizeof(FSkillInfo); skillstruct->Align = alignof(FSkillInfo); + auto decalbasestruct = NewStruct("DecalBase", nullptr, true); + decalbasestruct->Size = sizeof(FDecalBase); + decalbasestruct->Align = alignof(FDecalBase); + NewPointer(decalbasestruct, false)->InstallHandlers( + [](FSerializer& ar, const char* key, const void* addr) + { + ar(key, *(FDecalBase**)addr); + }, + [](FSerializer& ar, const char* key, void* addr) + { + Serialize(ar, key, *(FDecalBase**)addr, nullptr); + return true; + } + ); + PStruct *pstruct = NewStruct("PlayerInfo", nullptr, true); pstruct->Size = sizeof(player_t); pstruct->Align = alignof(player_t); diff --git a/src/serializer_doom.cpp b/src/serializer_doom.cpp index a950a5d8e..59a371ec0 100644 --- a/src/serializer_doom.cpp +++ b/src/serializer_doom.cpp @@ -52,6 +52,7 @@ #include "g_levellocals.h" #include "p_conversation.h" #include "p_terrain.h" +#include "decallib.h" #include "serializer_internal.h" @@ -449,6 +450,34 @@ FSerializer &Serialize(FSerializer &arc, const char *key, FState *&state, FState } +template<> FSerializer& Serialize(FSerializer& arc, const char* key, FDecalBase*& decal, FDecalBase** def) +{ + if (arc.isWriting()) + { + if (!arc.w->inObject() || def == nullptr || decal != *def) + { + arc.WriteKey(key); + if (decal == nullptr) + arc.w->Null(); + else + arc.w->String(decal->GetDecalName().GetChars()); + } + } + else + { + auto d = arc.r->FindKey(key); + if (d != nullptr) + { + if (!d->IsString()) + decal = nullptr; + else + decal = DecalLibrary.GetDecalBaseByName(d->GetString()); + } + } + + return arc; +} + //========================================================================== // // diff --git a/src/serializer_doom.h b/src/serializer_doom.h index bc87df74a..ae653437e 100644 --- a/src/serializer_doom.h +++ b/src/serializer_doom.h @@ -16,6 +16,7 @@ struct FDoorAnimation; struct FPolyObj; struct FInterpolator; struct FLevelLocals; +class FDecalBase; class FDoomSerializer : public FSerializer { @@ -59,6 +60,7 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, FDoorAnimat template<> FSerializer &Serialize(FSerializer &arc, const char *key, char *&pstr, char **def); template<> FSerializer &Serialize(FSerializer &arc, const char *key, FLevelLocals *&font, FLevelLocals **def); FSerializer &Serialize(FSerializer &arc, const char *key, FState *&state, FState **def, bool *retcode); +template<> FSerializer &Serialize(FSerializer &arc, const char *key, FDecalBase *&decal, FDecalBase **def); template<> inline FSerializer &Serialize(FSerializer &arc, const char *key, FState *&state, FState **def) { return Serialize(arc, key, state, def, nullptr); diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index c3b70460d..d49e6acc0 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -265,7 +265,7 @@ class Actor : Thinker native native readonly State SeeState; native State MeleeState; native State MissileState; - native readonly internal voidptr /*DecalBase*/ DecalGenerator; + native DecalBase DecalGenerator; native uint8 fountaincolor; native double CameraHeight; // Height of camera when used as such native double CameraFOV; diff --git a/wadsrc/static/zscript/doombase.zs b/wadsrc/static/zscript/doombase.zs index 39410cbce..fbfcb0247 100644 --- a/wadsrc/static/zscript/doombase.zs +++ b/wadsrc/static/zscript/doombase.zs @@ -1027,3 +1027,6 @@ struct FRailParams native int SpiralOffset; native int limit; }; // [RH] Shoot a railgun + +// This is just here to prevent mods that used setting this directly from breaking. +struct DecalBase native {}