diff --git a/src/d_player.h b/src/d_player.h index 168327f8a..9a4e60d0f 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -80,6 +80,7 @@ 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.h b/src/dobject.h index 4b6f1ec49..f478cfc08 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -98,6 +98,7 @@ enum CLASSREG_PClassPlayerPawn, CLASSREG_PClassType, CLASSREG_PClassClass, + CLASSREG_PClassWeaponPiece }; struct ClassReg diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 7e80eca0c..f16bd588d 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -44,6 +44,7 @@ #include "autosegs.h" #include "v_text.h" #include "a_pickups.h" +#include "a_weaponpiece.h" #include "d_player.h" #include "fragglescript/t_fs.h" @@ -2163,6 +2164,7 @@ PClass *ClassReg::RegisterClass() &PClassPlayerPawn::RegistrationInfo, &PClassType::RegistrationInfo, &PClassClass::RegistrationInfo, + &PClassWeaponPiece::RegistrationInfo, }; // Skip classes that have already been registered @@ -2318,34 +2320,29 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size) assert (size >= Size); PClass *type; bool notnew; + size_t bucket; - const PClass *existclass = FindClass(name); + PClass *existclass = static_cast(TypeTable.FindType(RUNTIME_CLASS(PClass), /*FIXME:Outer*/0, name, &bucket)); // This is a placeholder so fill it in - if (existclass != NULL && (existclass->Size == TClass_Fatal || existclass->Size == TClass_Nonfatal)) + if (existclass != NULL && (existclass->Size == TentativeClass)) { type = const_cast(existclass); if (!IsDescendantOf(type->ParentClass)) { - if (existclass->Size == TClass_Fatal) - { - I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars()); - } - else - { - Printf(TEXTCOLOR_RED "%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars()); - } + I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars()); } DPrintf("Defining placeholder class %s\n", name.GetChars()); notnew = true; } else { - // Create a new type object of the same type as us. (We may be a derived class of PClass.) - type = static_cast(GetClass()->CreateNew()); notnew = false; } + // Create a new type object of the same type as us. (We may be a derived class of PClass.) + type = static_cast(GetClass()->CreateNew()); + type->TypeName = name; type->Size = size; type->bRuntimeClass = true; @@ -2354,6 +2351,18 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size) { type->InsertIntoHash(); } + 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); + } + TypeTable.ReplaceType(type, existclass, bucket); + } return type; } @@ -2403,11 +2412,11 @@ PClass *PClass::FindClassTentative(FName name, bool fatal) return static_cast(found); } PClass *type = static_cast(GetClass()->CreateNew()); - DPrintf("Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars()); + Printf("Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars()); type->TypeName = name; type->ParentClass = this; - type->Size = fatal? TClass_Fatal : TClass_Nonfatal; + type->Size = TentativeClass; type->bRuntimeClass = true; TypeTable.AddType(type, RUNTIME_CLASS(PClass), (intptr_t)type->Outer, name, bucket); return type; diff --git a/src/dobjtype.h b/src/dobjtype.h index 900059cab..8e0331f2f 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -601,8 +601,7 @@ public: enum { - TClass_Fatal = UINT_MAX, - TClass_Nonfatal = UINT_MAX - 1 + TentativeClass = UINT_MAX, }; class PClassClass; diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index f6bca1294..f192f650f 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -39,6 +39,18 @@ void PClassInventory::Derive(PClass *newclass) newc->PickupMessage = PickupMessage; newc->GiveQuest = GiveQuest; newc->AltHUDIcon = AltHUDIcon; + newc->ForbiddenToPlayerClass = ForbiddenToPlayerClass; + newc->RestrictedToPlayerClass = RestrictedToPlayerClass; +} + +void PClassInventory::ReplaceClassRef(PClass *oldclass, PClass *newclass) +{ + Super::ReplaceClassRef(oldclass, newclass); + AInventory *def = (AInventory*)Defaults; + if (def != NULL) + { + if (def->PickupFlash == oldclass) def->PickupFlash = static_cast(newclass); + } } IMPLEMENT_CLASS(PClassAmmo) diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index ef693394a..9c9c1e48c 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -139,6 +139,7 @@ protected: virtual void Derive(PClass *newclass); public: PClassInventory(); + virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); FString PickupMessage; int GiveQuest; // Optionally give one of the quest items. @@ -269,6 +270,7 @@ protected: virtual void Derive(PClass *newclass); public: PClassWeapon(); + virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); int SlotNumber; fixed_t SlotPriority; diff --git a/src/g_shared/a_weaponpiece.cpp b/src/g_shared/a_weaponpiece.cpp index 6862c1911..1a4c27882 100644 --- a/src/g_shared/a_weaponpiece.cpp +++ b/src/g_shared/a_weaponpiece.cpp @@ -3,8 +3,20 @@ #include "doomstat.h" #include "farchive.h" +IMPLEMENT_CLASS(PClassWeaponPiece) IMPLEMENT_CLASS (AWeaponHolder) +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 (FArchive &arc) { Super::Serialize(arc); diff --git a/src/g_shared/a_weaponpiece.h b/src/g_shared/a_weaponpiece.h index 9f495a06e..dfa30f5d7 100644 --- a/src/g_shared/a_weaponpiece.h +++ b/src/g_shared/a_weaponpiece.h @@ -1,7 +1,16 @@ +// Ammo: Something a weapon needs to operate +class PClassWeaponPiece : public PClassInventory +{ + DECLARE_CLASS(PClassWeaponPiece, PClassInventory) +protected: +public: + virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); +}; + class AWeaponPiece : public AInventory { - DECLARE_CLASS (AWeaponPiece, AInventory) + DECLARE_CLASS_WITH_META(AWeaponPiece, AInventory, PClassWeaponPiece) HAS_OBJECT_POINTERS protected: bool PrivateShouldStay (); diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index c972c7120..e7242ad3f 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -54,6 +54,19 @@ void PClassWeapon::Derive(PClass *newclass) newc->SlotPriority = SlotPriority; } + +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); + } +} + //=========================================================================== // // AWeapon :: Serialize diff --git a/src/info.cpp b/src/info.cpp index 8c2ae06a6..1ca53470c 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -522,6 +522,37 @@ void PClassActor::SetPainChance(FName type, int chance) } } +//========================================================================== +// +// PClassActor :: ReplaceClassRef +// +//========================================================================== + +void PClassActor::ReplaceClassRef(PClass *oldclass, PClass *newclass) +{ + for (unsigned i = 0; i < VisibleToPlayerClass.Size(); i++) + { + if (VisibleToPlayerClass[i] == oldclass) + VisibleToPlayerClass[i] = static_cast(newclass); + } + for (unsigned i = 0; i < ForbiddenToPlayerClass.Size(); i++) + { + if (ForbiddenToPlayerClass[i] == oldclass) + ForbiddenToPlayerClass[i] = static_cast(newclass); + } + for (unsigned i = 0; i < RestrictedToPlayerClass.Size(); i++) + { + if (RestrictedToPlayerClass[i] == oldclass) + RestrictedToPlayerClass[i] = static_cast(newclass); + } + 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); + } +} + //========================================================================== // // DmgFactors :: CheckFactor diff --git a/src/info.h b/src/info.h index 2d0c627ec..52ccca305 100644 --- a/src/info.h +++ b/src/info.h @@ -200,6 +200,7 @@ public: PClassActor(); ~PClassActor(); + virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass); void BuildDefaults(); void ApplyDefaults(BYTE *defaults); void RegisterIDs(); diff --git a/src/p_user.cpp b/src/p_user.cpp index 0427bd64f..e23ccff7b 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -581,6 +581,16 @@ 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 diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp index b12f45abe..30d94c6a3 100644 --- a/src/thingdef/thingdef.cpp +++ b/src/thingdef/thingdef.cpp @@ -340,15 +340,10 @@ static void FinishThingdef() { PClassActor *ti = PClassActor::AllActorClasses[i]; - if (ti->Size == TClass_Fatal || ti->Size == TClass_Nonfatal) + if (ti->Size == TentativeClass) { Printf(TEXTCOLOR_RED "Class %s referenced but not defined\n", ti->TypeName.GetChars()); - if (ti->Size == TClass_Fatal) errorcount++; - else - { - // In order to prevent a crash, this class needs to be completed, even though it defines nothing. - ti->ParentClass->CreateDerivedClass(ti->TypeName, ti->ParentClass->Size); - } + errorcount++; continue; }