- removed an assert from APowerMorph::EndEffect. With some recent changes to DestroyAllInventory it appears that the asserted condition no longer is true at this point when ending a game.

- fixed: When replacing a tentative class, the pointers in the morph objects were not replaced. Instead of adding more ReplaceClassRef methods I chose to integrate this part into the PointerSubstitution mechanism and delete ReplaceClassRef entirely. The code had some oversights anyway that would have caused problems, now that non-actors can be created.
This commit is contained in:
Christoph Oelckers 2016-12-01 00:05:23 +01:00
parent 0233c21e33
commit 87484950cf
20 changed files with 72 additions and 132 deletions

View File

@ -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

View File

@ -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)
{

View File

@ -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
{

View File

@ -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<PClassActor*>(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<PClassActor*>(existclass));
if (index < PClassActor::AllActorClasses.Size()) PClassActor::AllActorClasses.Delete(index);
TypeTable.ReplaceType(type, existclass, bucket);
}
return type;

View File

@ -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<PClassWeapon *>(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)

View File

@ -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;

View File

@ -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<PClassPlayerPawn*>(newclass);
changed++;
}
}
for (unsigned i = 0; i < RestrictedToPlayerClass.Size(); i++)
{
if (RestrictedToPlayerClass[i] == oldclass)
{
RestrictedToPlayerClass[i] = static_cast<PClassPlayerPawn*>(newclass);
changed++;
}
}
}
return changed;
}
void PClassInventory::Finalize(FStateDefinitions &statedef)

View File

@ -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;

View File

@ -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<PClassWeapon *>(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
//===========================================================================

View File

@ -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 ();

View File

@ -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<PClassAmmo *>(newclass);
if (def->AmmoType2 == oldclass) def->AmmoType2 = static_cast<PClassAmmo *>(newclass);
if (def->SisterWeaponType == oldclass) def->SisterWeaponType = static_cast<PClassWeapon *>(newclass);
}
}
//===========================================================================
//
//

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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<PClassPlayerPawn*>(newclass);
changed++;
}
}
AActor *def = (AActor*)Defaults;
if (def != NULL)
{
if (def->TeleFogSourceType == oldclass) def->TeleFogSourceType = static_cast<PClassActor *>(newclass);
if (def->TeleFogDestType == oldclass) def->TeleFogDestType = static_cast<PClassActor *>(newclass);
}
return changed;
}
//==========================================================================

View File

@ -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();

View File

@ -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 ()

View File

@ -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<PClassInventory *>(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)

View File

@ -68,7 +68,6 @@
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
void InitThingdef();
TArray<PClassActor **> 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();
}

View File

@ -74,8 +74,6 @@
#include "a_health.h"
#include "a_keys.h"
extern TArray<PClassActor **> 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);
}