diff --git a/src/d_player.h b/src/d_player.h index 4cdfb8b79..81a1c43a6 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -81,7 +81,6 @@ public: FPlayerColorSet *GetColorSet(int setnum) { return ColorSets.CheckKey(setnum); } void SetPainFlash(FName type, PalEntry color); bool GetPainFlash(FName type, PalEntry *color) const; - virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); FString DisplayName; // Display name (used in menus, etc.) FString SoundClass; // Sound class diff --git a/src/dobject.cpp b/src/dobject.cpp index b05ae69ac..6b973de33 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -423,7 +423,7 @@ size_t DObject::PointerSubstitution (DObject *old, DObject *notOld) // //========================================================================== -size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld) +size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld, bool scandefaults) { DObject *probe; size_t changed = 0; @@ -438,6 +438,20 @@ size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld) last = probe; } + if (scandefaults) + { + for (auto p : PClassActor::AllActorClasses) + { + auto def = GetDefaultByType(p); + if (def != nullptr) + { + def->Class = p; + def->DObject::PointerSubstitution(old, notOld); + def->Class = nullptr; // reset pointer. Defaults should not have a valid class pointer. + } + } + } + // Go through the bodyque. for (i = 0; i < BODYQUESIZE; ++i) { diff --git a/src/dobject.h b/src/dobject.h index 7d27133dc..ed9c0fffa 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -482,7 +482,7 @@ public: // change any pointers from the old object to the new object, // use this method. virtual size_t PointerSubstitution (DObject *old, DObject *notOld); - static size_t StaticPointerSubstitution (DObject *old, DObject *notOld); + static size_t StaticPointerSubstitution (DObject *old, DObject *notOld, bool scandefaults = false); PClass *GetClass() const { diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index dba554498..c33caf12f 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -3008,8 +3008,6 @@ PClass *ClassReg::RegisterClass() &PClassPlayerPawn::RegistrationInfo, &PClassType::RegistrationInfo, &PClassClass::RegistrationInfo, - &PClassWeaponPiece::RegistrationInfo, - &PClassPowerupGiver::RegistrationInfo, }; // Skip classes that have already been registered @@ -3332,14 +3330,10 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size) } else { - PClassActor::AllActorClasses.Pop(); // remove the newly added class from the list - // todo: replace all affected fields - for (unsigned i = 0; i < PClassActor::AllActorClasses.Size(); i++) - { - PClassActor::AllActorClasses[i]->ReplaceClassRef(existclass, type); - if (PClassActor::AllActorClasses[i] == existclass) - PClassActor::AllActorClasses[i] = static_cast(type); - } + StaticPointerSubstitution(existclass, type, true); // replace the old one, also in the actor defaults. + // Delete the old class from the actor classes list, if it is in there. + auto index = PClassActor::AllActorClasses.Find(static_cast(existclass)); + if (index < PClassActor::AllActorClasses.Size()) PClassActor::AllActorClasses.Delete(index); TypeTable.ReplaceType(type, existclass, bucket); } return type; diff --git a/src/g_inventory/a_artifacts.cpp b/src/g_inventory/a_artifacts.cpp index a75b9ecd4..4afe74f1f 100644 --- a/src/g_inventory/a_artifacts.cpp +++ b/src/g_inventory/a_artifacts.cpp @@ -45,19 +45,12 @@ IMPLEMENT_CLASS(APowerup, false, false) // Powerup-Giver ------------------------------------------------------------- -IMPLEMENT_CLASS(PClassPowerupGiver, false, false) -void PClassPowerupGiver::ReplaceClassRef(PClass *oldclass, PClass *newclass) -{ - Super::ReplaceClassRef(oldclass, newclass); - APowerupGiver *def = (APowerupGiver*)Defaults; - if (def != NULL) - { - if (def->PowerupType == oldclass) def->PowerupType = static_cast(newclass); - } -} +IMPLEMENT_CLASS(APowerupGiver, false, true) -IMPLEMENT_CLASS(APowerupGiver, false, false) +IMPLEMENT_POINTERS_START(APowerupGiver) +IMPLEMENT_POINTER(PowerupType) +IMPLEMENT_POINTERS_END DEFINE_FIELD(APowerupGiver, PowerupType) DEFINE_FIELD(APowerupGiver, EffectTics) @@ -1855,7 +1848,14 @@ void APowerDoubleFiringSpeed::EndEffect( ) // Morph powerup ------------------------------------------------------ -IMPLEMENT_CLASS(APowerMorph, false, false) +IMPLEMENT_CLASS(APowerMorph, false, true) + +IMPLEMENT_POINTERS_START(APowerMorph) + IMPLEMENT_POINTER(PlayerClass) + IMPLEMENT_POINTER(MorphFlash) + IMPLEMENT_POINTER(UnMorphFlash) +IMPLEMENT_POINTERS_END + DEFINE_FIELD(APowerMorph, PlayerClass) DEFINE_FIELD(APowerMorph, MorphFlash) @@ -1916,19 +1916,12 @@ void APowerMorph::EndEffect( ) { Super::EndEffect(); - // Abort if owner already destroyed - if (Owner == NULL) + // Abort if owner already destroyed or unmorphed + if (Owner == nullptr || MorphedPlayer == nullptr) { - assert(MorphedPlayer == NULL); return; } - // Abort if owner already unmorphed - if (MorphedPlayer == NULL) - { - return; - } - // Abort if owner is dead; their Die() method will // take care of any required unmorphing on death. if (MorphedPlayer->health <= 0) diff --git a/src/g_inventory/a_artifacts.h b/src/g_inventory/a_artifacts.h index 7e9956d73..bb821b5d6 100644 --- a/src/g_inventory/a_artifacts.h +++ b/src/g_inventory/a_artifacts.h @@ -35,19 +35,11 @@ protected: friend void InitAllPowerupEffects(AInventory *item); }; -class PClassPowerupGiver: public PClassInventory -{ - DECLARE_CLASS(PClassPowerupGiver, PClassInventory) -protected: -public: - virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); -}; - - // An artifact is an item that gives the player a powerup when activated. class APowerupGiver : public AInventory { - DECLARE_CLASS_WITH_META (APowerupGiver, AInventory, PClassPowerupGiver) + DECLARE_CLASS (APowerupGiver, AInventory) + HAS_OBJECT_POINTERS public: virtual bool Use (bool pickup) override; virtual void Serialize(FSerializer &arc) override; @@ -272,6 +264,7 @@ protected: class APowerMorph : public APowerup { DECLARE_CLASS( APowerMorph, APowerup ) + HAS_OBJECT_POINTERS public: virtual void Serialize(FSerializer &arc) override; diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index 91b88a053..51072023b 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -45,9 +45,9 @@ void PClassInventory::DeriveData(PClass *newclass) newc->RestrictedToPlayerClass = RestrictedToPlayerClass; } -void PClassInventory::ReplaceClassRef(PClass *oldclass, PClass *newclass) +size_t PClassInventory::PointerSubstitution(DObject *oldclass, DObject *newclass) { - Super::ReplaceClassRef(oldclass, newclass); + size_t changed = Super::PointerSubstitution(oldclass, newclass); AInventory *def = (AInventory*)Defaults; if (def != NULL) { @@ -55,14 +55,21 @@ void PClassInventory::ReplaceClassRef(PClass *oldclass, PClass *newclass) for (unsigned i = 0; i < ForbiddenToPlayerClass.Size(); i++) { if (ForbiddenToPlayerClass[i] == oldclass) + { ForbiddenToPlayerClass[i] = static_cast(newclass); + changed++; + } } for (unsigned i = 0; i < RestrictedToPlayerClass.Size(); i++) { if (RestrictedToPlayerClass[i] == oldclass) + { RestrictedToPlayerClass[i] = static_cast(newclass); + changed++; + } } } + return changed; } void PClassInventory::Finalize(FStateDefinitions &statedef) diff --git a/src/g_inventory/a_pickups.h b/src/g_inventory/a_pickups.h index 99dad8713..32914e3e5 100644 --- a/src/g_inventory/a_pickups.h +++ b/src/g_inventory/a_pickups.h @@ -55,7 +55,7 @@ class PClassInventory : public PClassActor public: PClassInventory(); virtual void DeriveData(PClass *newclass); - virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); + virtual size_t PointerSubstitution(DObject *oldclass, DObject *newclass); void Finalize(FStateDefinitions &statedef); FString PickupMessage; diff --git a/src/g_inventory/a_weaponpiece.cpp b/src/g_inventory/a_weaponpiece.cpp index e1a7fe33b..2fe14ae91 100644 --- a/src/g_inventory/a_weaponpiece.cpp +++ b/src/g_inventory/a_weaponpiece.cpp @@ -38,7 +38,6 @@ #include "doomstat.h" #include "serializer.h" -IMPLEMENT_CLASS(PClassWeaponPiece, false, false) IMPLEMENT_CLASS(AWeaponHolder, false, false) DEFINE_FIELD(AWeaponHolder, PieceMask); @@ -50,22 +49,6 @@ DEFINE_FIELD(AWeaponHolder, PieceWeapon); // //=========================================================================== -void PClassWeaponPiece::ReplaceClassRef(PClass *oldclass, PClass *newclass) -{ - Super::ReplaceClassRef(oldclass, newclass); - AWeaponPiece *def = (AWeaponPiece*)Defaults; - if (def != NULL) - { - if (def->WeaponClass == oldclass) def->WeaponClass = static_cast(newclass); - } -} - -//=========================================================================== -// -// -// -//=========================================================================== - void AWeaponHolder::Serialize(FSerializer &arc) { Super::Serialize(arc); @@ -77,6 +60,7 @@ IMPLEMENT_CLASS(AWeaponPiece, false, true) IMPLEMENT_POINTERS_START(AWeaponPiece) IMPLEMENT_POINTER(FullWeapon) + IMPLEMENT_POINTER(WeaponClass) IMPLEMENT_POINTERS_END //=========================================================================== diff --git a/src/g_inventory/a_weaponpiece.h b/src/g_inventory/a_weaponpiece.h index e0db15007..a8c6a2e76 100644 --- a/src/g_inventory/a_weaponpiece.h +++ b/src/g_inventory/a_weaponpiece.h @@ -2,18 +2,9 @@ #include "a_pickups.h" #include "a_weapons.h" -// -class PClassWeaponPiece : public PClassInventory -{ - DECLARE_CLASS(PClassWeaponPiece, PClassInventory) -protected: -public: - virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); -}; - class AWeaponPiece : public AInventory { - DECLARE_CLASS_WITH_META(AWeaponPiece, AInventory, PClassWeaponPiece) + DECLARE_CLASS(AWeaponPiece, AInventory) HAS_OBJECT_POINTERS protected: bool PrivateShouldStay (); diff --git a/src/g_inventory/a_weapons.cpp b/src/g_inventory/a_weapons.cpp index 19a30dcd8..c312f15b3 100644 --- a/src/g_inventory/a_weapons.cpp +++ b/src/g_inventory/a_weapons.cpp @@ -148,24 +148,6 @@ void PClassWeapon::DeriveData(PClass *newclass) } -//=========================================================================== -// -// -// -//=========================================================================== - -void PClassWeapon::ReplaceClassRef(PClass *oldclass, PClass *newclass) -{ - Super::ReplaceClassRef(oldclass, newclass); - AWeapon *def = (AWeapon*)Defaults; - if (def != NULL) - { - if (def->AmmoType1 == oldclass) def->AmmoType1 = static_cast(newclass); - if (def->AmmoType2 == oldclass) def->AmmoType2 = static_cast(newclass); - if (def->SisterWeaponType == oldclass) def->SisterWeaponType = static_cast(newclass); - } -} - //=========================================================================== // // diff --git a/src/g_inventory/a_weapons.h b/src/g_inventory/a_weapons.h index c6424075d..1b1258401 100644 --- a/src/g_inventory/a_weapons.h +++ b/src/g_inventory/a_weapons.h @@ -95,7 +95,6 @@ protected: virtual void DeriveData(PClass *newclass); public: PClassWeapon(); - virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); void Finalize(FStateDefinitions &statedef); int SlotNumber; diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index f22318839..03f76c0c0 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -613,7 +613,14 @@ void InitAllPowerupEffects(AInventory *item) // Base class for morphing projectiles -------------------------------------- -IMPLEMENT_CLASS(AMorphProjectile, false, false) +IMPLEMENT_CLASS(AMorphProjectile, false, true) + +IMPLEMENT_POINTERS_START(AMorphProjectile) + IMPLEMENT_POINTER(PlayerClass) + IMPLEMENT_POINTER(MonsterClass) + IMPLEMENT_POINTER(MorphFlash) + IMPLEMENT_POINTER(UnMorphFlash) +IMPLEMENT_POINTERS_END DEFINE_FIELD(AMorphProjectile, PlayerClass) DEFINE_FIELD(AMorphProjectile, MonsterClass) diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index 0087690f7..001df5488 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -187,6 +187,7 @@ private: class AMorphProjectile : public AActor { DECLARE_CLASS (AMorphProjectile, AActor) + HAS_OBJECT_POINTERS; public: int DoSpecialDamage (AActor *target, int damage, FName damagetype); diff --git a/src/info.cpp b/src/info.cpp index b8bf3acde..a0117a71f 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -619,19 +619,18 @@ void PClassActor::SetPainChance(FName type, int chance) // //========================================================================== -void PClassActor::ReplaceClassRef(PClass *oldclass, PClass *newclass) +size_t PClassActor::PointerSubstitution(DObject *oldclass, DObject *newclass) { + auto changed = Super::PointerSubstitution(oldclass, newclass); for (unsigned i = 0; i < VisibleToPlayerClass.Size(); i++) { if (VisibleToPlayerClass[i] == oldclass) + { VisibleToPlayerClass[i] = static_cast(newclass); + changed++; + } } - AActor *def = (AActor*)Defaults; - if (def != NULL) - { - if (def->TeleFogSourceType == oldclass) def->TeleFogSourceType = static_cast(newclass); - if (def->TeleFogDestType == oldclass) def->TeleFogDestType = static_cast(newclass); - } + return changed; } //========================================================================== diff --git a/src/info.h b/src/info.h index bb21524a5..54aac3e3c 100644 --- a/src/info.h +++ b/src/info.h @@ -248,7 +248,7 @@ public: PClassActor(); ~PClassActor(); - virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); + virtual size_t PointerSubstitution(DObject *oldclass, DObject *newclass); void BuildDefaults(); void ApplyDefaults(BYTE *defaults); void RegisterIDs(); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index f1f33425a..5a37561c9 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -145,6 +145,8 @@ IMPLEMENT_POINTERS_START(AActor) IMPLEMENT_POINTER(Poisoner) IMPLEMENT_POINTER(DamageFunc) IMPLEMENT_POINTER(alternative) + IMPLEMENT_POINTER(TeleFogSourceType) + IMPLEMENT_POINTER(TeleFogDestType) IMPLEMENT_POINTERS_END AActor::~AActor () diff --git a/src/p_user.cpp b/src/p_user.cpp index 74b07e0ca..b808dd9c3 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -607,16 +607,6 @@ bool PClassPlayerPawn::GetPainFlash(FName type, PalEntry *color) const return false; } -void PClassPlayerPawn::ReplaceClassRef(PClass *oldclass, PClass *newclass) -{ - Super::ReplaceClassRef(oldclass, newclass); - APlayerPawn *def = (APlayerPawn*)Defaults; - if (def != NULL) - { - if (def->FlechetteType == oldclass) def->FlechetteType = static_cast(newclass); - } -} - //=========================================================================== // // player_t :: SendPitchLimits @@ -648,6 +638,7 @@ IMPLEMENT_CLASS(APlayerPawn, false, true) IMPLEMENT_POINTERS_START(APlayerPawn) IMPLEMENT_POINTER(InvFirst) IMPLEMENT_POINTER(InvSel) + IMPLEMENT_POINTER(FlechetteType) IMPLEMENT_POINTERS_END IMPLEMENT_CLASS(APlayerChunk, false, false) diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index cdf35283a..e1d5f9b27 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -68,7 +68,6 @@ // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- void InitThingdef(); -TArray OptionalClassPtrs; // STATIC FUNCTION PROTOTYPES -------------------------------------------- PClassActor *QuestItemClasses[31]; @@ -365,7 +364,7 @@ static void CheckStates(PClassActor *obj) void ParseScripts(); void ParseAllDecorate(); -void LoadActors () +void LoadActors() { cycle_t timer; @@ -387,7 +386,7 @@ void LoadActors () } FScriptPosition::ResetErrorCounter(); - for (int i = PClassActor::AllActorClasses.Size()-1; i>=0;i--) + for (int i = PClassActor::AllActorClasses.Size() - 1; i >= 0; i--) { auto ti = PClassActor::AllActorClasses[i]; if (ti->Size == TentativeClass) @@ -397,10 +396,6 @@ void LoadActors () Printf(TEXTCOLOR_ORANGE "Class %s referenced but not defined\n", ti->TypeName.GetChars()); FScriptPosition::WarnCounter++; DObject::StaticPointerSubstitution(ti, nullptr); - for (auto op : OptionalClassPtrs) - { - if (*op == ti) *op = nullptr; - } PClassActor::AllActorClasses.Delete(i); } else @@ -420,7 +415,7 @@ void LoadActors () CheckStates(ti); - + if (ti->bDecorateClass && ti->IsDescendantOf(RUNTIME_CLASS(AStateProvider))) { // either a DECORATE based weapon or CustomInventory. @@ -429,7 +424,7 @@ void LoadActors () // hits an unsafe state. If we can find something here it can be handled wuth a compile error rather than a runtime error. CheckForUnsafeStates(ti); } - + } if (FScriptPosition::ErrorCounter > 0) { @@ -447,6 +442,4 @@ void LoadActors () QuestItemClasses[i] = PClass::FindActor(fmt); } StateSourceLines.Clear(); - OptionalClassPtrs.Clear(); - OptionalClassPtrs.ShrinkToFit(); } diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 9bff91a80..2eb5f6781 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -74,8 +74,6 @@ #include "a_health.h" #include "a_keys.h" -extern TArray OptionalClassPtrs; - //========================================================================== // // Gets a class pointer and performs an error check for correct type @@ -2998,7 +2996,6 @@ DEFINE_CLASS_PROPERTY(playerclass, S, MorphProjectile) { PROP_STRING_PARM(str, 0); defaults->PlayerClass = FindClassTentativePlayerPawn(str, bag.fromDecorate); - if (bag.fromDecorate) OptionalClassPtrs.Push((PClassActor**)&defaults->PlayerClass); } //========================================================================== @@ -3008,7 +3005,6 @@ DEFINE_CLASS_PROPERTY(monsterclass, S, MorphProjectile) { PROP_STRING_PARM(str, 0); defaults->MonsterClass = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate); - if (bag.fromDecorate) OptionalClassPtrs.Push(&defaults->MonsterClass); } //========================================================================== @@ -3036,7 +3032,6 @@ DEFINE_CLASS_PROPERTY(morphflash, S, MorphProjectile) { PROP_STRING_PARM(str, 0); defaults->MorphFlash = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate); - if (bag.fromDecorate) OptionalClassPtrs.Push(&defaults->MorphFlash); } //========================================================================== @@ -3046,7 +3041,6 @@ DEFINE_CLASS_PROPERTY(unmorphflash, S, MorphProjectile) { PROP_STRING_PARM(str, 0); defaults->UnMorphFlash = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate); - if (bag.fromDecorate) OptionalClassPtrs.Push(&defaults->UnMorphFlash); } //========================================================================== @@ -3056,7 +3050,6 @@ DEFINE_CLASS_PROPERTY(playerclass, S, PowerMorph) { PROP_STRING_PARM(str, 0); defaults->PlayerClass = FindClassTentativePlayerPawn(str, bag.fromDecorate); - if (bag.fromDecorate) OptionalClassPtrs.Push((PClassActor**)&defaults->PlayerClass); } //========================================================================== @@ -3075,7 +3068,6 @@ DEFINE_CLASS_PROPERTY(morphflash, S, PowerMorph) { PROP_STRING_PARM(str, 0); defaults->MorphFlash = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate); - if (bag.fromDecorate) OptionalClassPtrs.Push(&defaults->MorphFlash); } //========================================================================== @@ -3085,7 +3077,6 @@ DEFINE_CLASS_PROPERTY(unmorphflash, S, PowerMorph) { PROP_STRING_PARM(str, 0); defaults->UnMorphFlash = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate); - if (bag.fromDecorate) OptionalClassPtrs.Push(&defaults->UnMorphFlash); }