This commit is contained in:
Christoph Oelckers 2016-02-10 00:49:35 +01:00
commit 012f10400c
20 changed files with 200 additions and 92 deletions

View file

@ -73,13 +73,14 @@ class PClassPlayerPawn : public PClassActor
{ {
DECLARE_CLASS(PClassPlayerPawn, PClassActor); DECLARE_CLASS(PClassPlayerPawn, PClassActor);
protected: protected:
virtual void Derive(PClass *newclass);
public: public:
PClassPlayerPawn(); PClassPlayerPawn();
virtual void DeriveData(PClass *newclass);
void EnumColorSets(TArray<int> *out); void EnumColorSets(TArray<int> *out);
FPlayerColorSet *GetColorSet(int setnum) { return ColorSets.CheckKey(setnum); } FPlayerColorSet *GetColorSet(int setnum) { return ColorSets.CheckKey(setnum); }
void SetPainFlash(FName type, PalEntry color); void SetPainFlash(FName type, PalEntry color);
bool GetPainFlash(FName type, PalEntry *color) const; bool GetPainFlash(FName type, PalEntry *color) const;
virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass);
FString DisplayName; // Display name (used in menus, etc.) FString DisplayName; // Display name (used in menus, etc.)
FString SoundClass; // Sound class FString SoundClass; // Sound class

View file

@ -98,6 +98,7 @@ enum
CLASSREG_PClassPlayerPawn, CLASSREG_PClassPlayerPawn,
CLASSREG_PClassType, CLASSREG_PClassType,
CLASSREG_PClassClass, CLASSREG_PClassClass,
CLASSREG_PClassWeaponPiece
}; };
struct ClassReg struct ClassReg

View file

@ -44,6 +44,7 @@
#include "autosegs.h" #include "autosegs.h"
#include "v_text.h" #include "v_text.h"
#include "a_pickups.h" #include "a_pickups.h"
#include "a_weaponpiece.h"
#include "d_player.h" #include "d_player.h"
#include "fragglescript/t_fs.h" #include "fragglescript/t_fs.h"
@ -2163,6 +2164,7 @@ PClass *ClassReg::RegisterClass()
&PClassPlayerPawn::RegistrationInfo, &PClassPlayerPawn::RegistrationInfo,
&PClassType::RegistrationInfo, &PClassType::RegistrationInfo,
&PClassClass::RegistrationInfo, &PClassClass::RegistrationInfo,
&PClassWeaponPiece::RegistrationInfo,
}; };
// Skip classes that have already been registered // Skip classes that have already been registered
@ -2318,42 +2320,50 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
assert (size >= Size); assert (size >= Size);
PClass *type; PClass *type;
bool notnew; bool notnew;
size_t bucket;
const PClass *existclass = FindClass(name); PClass *existclass = static_cast<PClass *>(TypeTable.FindType(RUNTIME_CLASS(PClass), /*FIXME:Outer*/0, name, &bucket));
// This is a placeholder so fill it in // 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<PClass*>(existclass); type = const_cast<PClass*>(existclass);
if (!IsDescendantOf(type->ParentClass)) 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()); 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());
}
}
DPrintf("Defining placeholder class %s\n", name.GetChars()); DPrintf("Defining placeholder class %s\n", name.GetChars());
notnew = true; notnew = true;
} }
else else
{ {
// Create a new type object of the same type as us. (We may be a derived class of PClass.)
type = static_cast<PClass *>(GetClass()->CreateNew());
notnew = false; notnew = false;
} }
// Create a new type object of the same type as us. (We may be a derived class of PClass.)
type = static_cast<PClass *>(GetClass()->CreateNew());
type->TypeName = name; type->TypeName = name;
type->Size = size; type->Size = size;
type->bRuntimeClass = true; type->bRuntimeClass = true;
Derive(type); Derive(type);
DeriveData(type);
if (!notnew) if (!notnew)
{ {
type->InsertIntoHash(); 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<PClassActor*>(type);
}
TypeTable.ReplaceType(type, existclass, bucket);
}
return type; return type;
} }
@ -2403,11 +2413,11 @@ PClass *PClass::FindClassTentative(FName name, bool fatal)
return static_cast<PClass *>(found); return static_cast<PClass *>(found);
} }
PClass *type = static_cast<PClass *>(GetClass()->CreateNew()); PClass *type = static_cast<PClass *>(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->TypeName = name;
type->ParentClass = this; type->ParentClass = this;
type->Size = fatal? TClass_Fatal : TClass_Nonfatal; type->Size = TentativeClass;
type->bRuntimeClass = true; type->bRuntimeClass = true;
TypeTable.AddType(type, RUNTIME_CLASS(PClass), (intptr_t)type->Outer, name, bucket); TypeTable.AddType(type, RUNTIME_CLASS(PClass), (intptr_t)type->Outer, name, bucket);
return type; return type;

View file

@ -601,8 +601,7 @@ public:
enum enum
{ {
TClass_Fatal = UINT_MAX, TentativeClass = UINT_MAX,
TClass_Nonfatal = UINT_MAX - 1
}; };
class PClassClass; class PClassClass;
@ -611,13 +610,14 @@ class PClass : public PStruct
DECLARE_CLASS(PClass, PStruct); DECLARE_CLASS(PClass, PStruct);
HAS_OBJECT_POINTERS; HAS_OBJECT_POINTERS;
protected: protected:
virtual void Derive(PClass *newclass);
// We unravel _WITH_META here just as we did for PType. // We unravel _WITH_META here just as we did for PType.
enum { MetaClassNum = CLASSREG_PClassClass }; enum { MetaClassNum = CLASSREG_PClassClass };
virtual void Derive(PClass *newclass);
public: public:
typedef PClassClass MetaClass; typedef PClassClass MetaClass;
MetaClass *GetClass() const; MetaClass *GetClass() const;
virtual void DeriveData(PClass *newclass) {}
static void StaticInit(); static void StaticInit();
static void StaticShutdown(); static void StaticShutdown();
static void StaticBootstrap(); static void StaticBootstrap();
@ -678,9 +678,9 @@ class PClassType : public PClass
{ {
DECLARE_CLASS(PClassType, PClass); DECLARE_CLASS(PClassType, PClass);
protected: protected:
virtual void Derive(PClass *newclass);
public: public:
PClassType(); PClassType();
virtual void Derive(PClass *newclass);
PClass *TypeTableType; // The type to use for hashing into the type table PClass *TypeTableType; // The type to use for hashing into the type table
}; };

View file

@ -30,15 +30,37 @@ PClassInventory::PClassInventory()
AltHUDIcon.SetNull(); AltHUDIcon.SetNull();
} }
void PClassInventory::Derive(PClass *newclass) void PClassInventory::DeriveData(PClass *newclass)
{ {
assert(newclass->IsKindOf(RUNTIME_CLASS(PClassInventory))); assert(newclass->IsKindOf(RUNTIME_CLASS(PClassInventory)));
Super::Derive(newclass); Super::DeriveData(newclass);
PClassInventory *newc = static_cast<PClassInventory *>(newclass); PClassInventory *newc = static_cast<PClassInventory *>(newclass);
newc->PickupMessage = PickupMessage; newc->PickupMessage = PickupMessage;
newc->GiveQuest = GiveQuest; newc->GiveQuest = GiveQuest;
newc->AltHUDIcon = AltHUDIcon; 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<PClassActor *>(newclass);
for (unsigned i = 0; i < ForbiddenToPlayerClass.Size(); i++)
{
if (ForbiddenToPlayerClass[i] == oldclass)
ForbiddenToPlayerClass[i] = static_cast<PClassPlayerPawn*>(newclass);
}
for (unsigned i = 0; i < RestrictedToPlayerClass.Size(); i++)
{
if (RestrictedToPlayerClass[i] == oldclass)
RestrictedToPlayerClass[i] = static_cast<PClassPlayerPawn*>(newclass);
}
}
} }
IMPLEMENT_CLASS(PClassAmmo) IMPLEMENT_CLASS(PClassAmmo)
@ -48,10 +70,10 @@ PClassAmmo::PClassAmmo()
DropAmount = 0; DropAmount = 0;
} }
void PClassAmmo::Derive(PClass *newclass) void PClassAmmo::DeriveData(PClass *newclass)
{ {
assert(newclass->IsKindOf(RUNTIME_CLASS(PClassAmmo))); assert(newclass->IsKindOf(RUNTIME_CLASS(PClassAmmo)));
Super::Derive(newclass); Super::DeriveData(newclass);
PClassAmmo *newc = static_cast<PClassAmmo *>(newclass); PClassAmmo *newc = static_cast<PClassAmmo *>(newclass);
newc->DropAmount = DropAmount; newc->DropAmount = DropAmount;
@ -1524,7 +1546,7 @@ bool AInventory::CanPickup (AActor *toucher)
if (!toucher) if (!toucher)
return false; return false;
PClassActor *ai = GetClass(); PClassInventory *ai = GetClass();
// Is the item restricted to certain player classes? // Is the item restricted to certain player classes?
if (ai->RestrictedToPlayerClass.Size() != 0) if (ai->RestrictedToPlayerClass.Size() != 0)
{ {
@ -1672,10 +1694,10 @@ PClassHealth::PClassHealth()
// //
//=========================================================================== //===========================================================================
void PClassHealth::Derive(PClass *newclass) void PClassHealth::DeriveData(PClass *newclass)
{ {
assert(newclass->IsKindOf(RUNTIME_CLASS(PClassHealth))); assert(newclass->IsKindOf(RUNTIME_CLASS(PClassHealth)));
Super::Derive(newclass); Super::DeriveData(newclass);
PClassHealth *newc = static_cast<PClassHealth *>(newclass); PClassHealth *newc = static_cast<PClassHealth *>(newclass);
newc->LowHealth = LowHealth; newc->LowHealth = LowHealth;

View file

@ -135,14 +135,16 @@ enum
class PClassInventory : public PClassActor class PClassInventory : public PClassActor
{ {
DECLARE_CLASS(PClassInventory, PClassActor) DECLARE_CLASS(PClassInventory, PClassActor)
protected:
virtual void Derive(PClass *newclass);
public: public:
PClassInventory(); PClassInventory();
virtual void DeriveData(PClass *newclass);
virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass);
FString PickupMessage; FString PickupMessage;
int GiveQuest; // Optionally give one of the quest items. int GiveQuest; // Optionally give one of the quest items.
FTextureID AltHUDIcon; FTextureID AltHUDIcon;
TArray<PClassPlayerPawn *> RestrictedToPlayerClass;
TArray<PClassPlayerPawn *> ForbiddenToPlayerClass;
}; };
class AInventory : public AActor class AInventory : public AActor
@ -241,7 +243,7 @@ class PClassAmmo : public PClassInventory
{ {
DECLARE_CLASS(PClassAmmo, PClassInventory) DECLARE_CLASS(PClassAmmo, PClassInventory)
protected: protected:
virtual void Derive(PClass *newclass); virtual void DeriveData(PClass *newclass);
public: public:
PClassAmmo(); PClassAmmo();
@ -266,9 +268,10 @@ class PClassWeapon : public PClassInventory
{ {
DECLARE_CLASS(PClassWeapon, PClassInventory); DECLARE_CLASS(PClassWeapon, PClassInventory);
protected: protected:
virtual void Derive(PClass *newclass); virtual void DeriveData(PClass *newclass);
public: public:
PClassWeapon(); PClassWeapon();
virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass);
int SlotNumber; int SlotNumber;
fixed_t SlotPriority; fixed_t SlotPriority;
@ -401,9 +404,9 @@ class PClassHealth : public PClassInventory
{ {
DECLARE_CLASS(PClassHealth, PClassInventory) DECLARE_CLASS(PClassHealth, PClassInventory)
protected: protected:
virtual void Derive(PClass *newclass);
public: public:
PClassHealth(); PClassHealth();
virtual void DeriveData(PClass *newclass);
FString LowHealthMessage; FString LowHealthMessage;
int LowHealth; int LowHealth;
@ -518,8 +521,8 @@ class PClassPuzzleItem : public PClassInventory
{ {
DECLARE_CLASS(PClassPuzzleItem, PClassInventory); DECLARE_CLASS(PClassPuzzleItem, PClassInventory);
protected: protected:
virtual void Derive(PClass *newclass);
public: public:
virtual void DeriveData(PClass *newclass);
FString PuzzFailMessage; FString PuzzFailMessage;
}; };

View file

@ -11,9 +11,9 @@
IMPLEMENT_CLASS(PClassPuzzleItem) IMPLEMENT_CLASS(PClassPuzzleItem)
void PClassPuzzleItem::Derive(PClass *newclass) void PClassPuzzleItem::DeriveData(PClass *newclass)
{ {
Super::Derive(newclass); Super::DeriveData(newclass);
assert(newclass->IsKindOf(RUNTIME_CLASS(PClassPuzzleItem))); assert(newclass->IsKindOf(RUNTIME_CLASS(PClassPuzzleItem)));
static_cast<PClassPuzzleItem *>(newclass)->PuzzFailMessage = PuzzFailMessage; static_cast<PClassPuzzleItem *>(newclass)->PuzzFailMessage = PuzzFailMessage;
} }

View file

@ -3,8 +3,20 @@
#include "doomstat.h" #include "doomstat.h"
#include "farchive.h" #include "farchive.h"
IMPLEMENT_CLASS(PClassWeaponPiece)
IMPLEMENT_CLASS (AWeaponHolder) 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<PClassWeapon *>(newclass);
}
}
void AWeaponHolder::Serialize (FArchive &arc) void AWeaponHolder::Serialize (FArchive &arc)
{ {
Super::Serialize(arc); Super::Serialize(arc);

View file

@ -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 class AWeaponPiece : public AInventory
{ {
DECLARE_CLASS (AWeaponPiece, AInventory) DECLARE_CLASS_WITH_META(AWeaponPiece, AInventory, PClassWeaponPiece)
HAS_OBJECT_POINTERS HAS_OBJECT_POINTERS
protected: protected:
bool PrivateShouldStay (); bool PrivateShouldStay ();

View file

@ -44,16 +44,29 @@ PClassWeapon::PClassWeapon()
SlotPriority = FIXED_MAX; SlotPriority = FIXED_MAX;
} }
void PClassWeapon::Derive(PClass *newclass) void PClassWeapon::DeriveData(PClass *newclass)
{ {
assert(newclass->IsKindOf(RUNTIME_CLASS(PClassWeapon))); assert(newclass->IsKindOf(RUNTIME_CLASS(PClassWeapon)));
Super::Derive(newclass); Super::DeriveData(newclass);
PClassWeapon *newc = static_cast<PClassWeapon *>(newclass); PClassWeapon *newc = static_cast<PClassWeapon *>(newclass);
newc->SlotNumber = SlotNumber; newc->SlotNumber = SlotNumber;
newc->SlotPriority = SlotPriority; 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<PClassAmmo *>(newclass);
if (def->AmmoType2 == oldclass) def->AmmoType2 = static_cast<PClassAmmo *>(newclass);
if (def->SisterWeaponType == oldclass) def->SisterWeaponType = static_cast<PClassWeapon *>(newclass);
}
}
//=========================================================================== //===========================================================================
// //
// AWeapon :: Serialize // AWeapon :: Serialize

View file

@ -201,16 +201,11 @@ PClassActor::PClassActor()
FastSpeed = FIXED_MIN; FastSpeed = FIXED_MIN;
RDFactor = FRACUNIT; RDFactor = FRACUNIT;
CameraHeight = FIXED_MIN; CameraHeight = FIXED_MIN;
BloodType = NAME_Blood;
BloodType2 = NAME_BloodSplatter;
BloodType3 = NAME_AxeBlood;
DropItems = NULL; DropItems = NULL;
DontHurtShooter = false; DontHurtShooter = false;
ExplosionDamage = 128;
ExplosionRadius = -1; ExplosionRadius = -1;
MissileHeight = 32*FRACUNIT;
MeleeDamage = 0; MeleeDamage = 0;
// Record this in the master list. // Record this in the master list.
@ -250,10 +245,9 @@ PClassActor::~PClassActor()
// //
//========================================================================== //==========================================================================
void PClassActor::Derive(PClass *newclass) void PClassActor::DeriveData(PClass *newclass)
{ {
assert(newclass->IsKindOf(RUNTIME_CLASS(PClassActor))); assert(newclass->IsKindOf(RUNTIME_CLASS(PClassActor)));
Super::Derive(newclass);
PClassActor *newa = static_cast<PClassActor *>(newclass); PClassActor *newa = static_cast<PClassActor *>(newclass);
newa->Obituary = Obituary; newa->Obituary = Obituary;
@ -281,6 +275,22 @@ void PClassActor::Derive(PClass *newclass)
newa->MeleeSound = MeleeSound; newa->MeleeSound = MeleeSound;
newa->MissileName = MissileName; newa->MissileName = MissileName;
newa->MissileHeight = MissileHeight; newa->MissileHeight = MissileHeight;
newa->VisibleToPlayerClass = VisibleToPlayerClass;
if (DamageFactors != NULL)
{
// copy damage factors from parent
newa->DamageFactors = new DmgFactors;
*newa->DamageFactors = *DamageFactors;
}
if (PainChances != NULL)
{
// copy pain chances from parent
newa->PainChances = new PainChanceList;
*newa->PainChances = *PainChances;
}
} }
//========================================================================== //==========================================================================
@ -522,6 +532,27 @@ 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<PClassPlayerPawn*>(newclass);
}
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);
}
}
//========================================================================== //==========================================================================
// //
// DmgFactors :: CheckFactor // DmgFactors :: CheckFactor

View file

@ -192,14 +192,15 @@ class PClassActor : public PClass
DECLARE_CLASS(PClassActor, PClass); DECLARE_CLASS(PClassActor, PClass);
HAS_OBJECT_POINTERS; HAS_OBJECT_POINTERS;
protected: protected:
virtual void Derive(PClass *newclass);
public: public:
static void StaticInit (); static void StaticInit ();
static void StaticSetActorNums (); static void StaticSetActorNums ();
virtual void DeriveData(PClass *newclass);
PClassActor(); PClassActor();
~PClassActor(); ~PClassActor();
virtual void ReplaceClassRef(PClass *oldclass, PClass *newclass);
void BuildDefaults(); void BuildDefaults();
void ApplyDefaults(BYTE *defaults); void ApplyDefaults(BYTE *defaults);
void RegisterIDs(); void RegisterIDs();
@ -236,8 +237,6 @@ public:
PainChanceList *PainChances; PainChanceList *PainChances;
TArray<PClassPlayerPawn *> VisibleToPlayerClass; TArray<PClassPlayerPawn *> VisibleToPlayerClass;
TArray<PClassPlayerPawn *> RestrictedToPlayerClass;
TArray<PClassPlayerPawn *> ForbiddenToPlayerClass;
FString Obituary; // Player was killed by this actor FString Obituary; // Player was killed by this actor
FString HitObituary; // Player was killed by this actor in melee FString HitObituary; // Player was killed by this actor in melee

View file

@ -515,10 +515,10 @@ PClassPlayerPawn::PClassPlayerPawn()
ColorRangeEnd = 0; ColorRangeEnd = 0;
} }
void PClassPlayerPawn::Derive(PClass *newclass) void PClassPlayerPawn::DeriveData(PClass *newclass)
{ {
assert(newclass->IsKindOf(RUNTIME_CLASS(PClassPlayerPawn))); assert(newclass->IsKindOf(RUNTIME_CLASS(PClassPlayerPawn)));
Super::Derive(newclass); Super::DeriveData(newclass);
PClassPlayerPawn *newp = static_cast<PClassPlayerPawn *>(newclass); PClassPlayerPawn *newp = static_cast<PClassPlayerPawn *>(newclass);
size_t i; size_t i;
@ -581,6 +581,16 @@ bool PClassPlayerPawn::GetPainFlash(FName type, PalEntry *color) const
return false; 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 // player_t :: SendPitchLimits

View file

@ -137,6 +137,7 @@ PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName par
goto create; goto create;
} }
ti->InitializeNativeDefaults(); ti->InitializeNativeDefaults();
ti->ParentClass->DeriveData(ti);
} }
else else
{ {
@ -144,23 +145,6 @@ PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName par
ti = static_cast<PClassActor *>(parent->CreateDerivedClass (typeName, parent->Size)); ti = static_cast<PClassActor *>(parent->CreateDerivedClass (typeName, parent->Size));
} }
// Copy class lists from parent
ti->ForbiddenToPlayerClass = parent->ForbiddenToPlayerClass;
ti->RestrictedToPlayerClass = parent->RestrictedToPlayerClass;
ti->VisibleToPlayerClass = parent->VisibleToPlayerClass;
if (parent->DamageFactors != NULL)
{
// copy damage factors from parent
ti->DamageFactors = new DmgFactors;
*ti->DamageFactors = *parent->DamageFactors;
}
if (parent->PainChances != NULL)
{
// copy pain chances from parent
ti->PainChances = new PainChanceList;
*ti->PainChances = *parent->PainChances;
}
ti->Replacee = ti->Replacement = NULL; ti->Replacee = ti->Replacement = NULL;
ti->DoomEdNum = -1; ti->DoomEdNum = -1;
return ti; return ti;
@ -340,15 +324,10 @@ static void FinishThingdef()
{ {
PClassActor *ti = PClassActor::AllActorClasses[i]; 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()); Printf(TEXTCOLOR_RED "Class %s referenced but not defined\n", ti->TypeName.GetChars());
if (ti->Size == TClass_Fatal) errorcount++; 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);
}
continue; continue;
} }

View file

@ -72,12 +72,15 @@ static FxExpression *ParseExpressionB (FScanner &sc, PClassActor *cls);
static FxExpression *ParseExpressionA (FScanner &sc, PClassActor *cls); static FxExpression *ParseExpressionA (FScanner &sc, PClassActor *cls);
static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls); static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls);
FxExpression *ParseExpression (FScanner &sc, PClassActor *cls) FxExpression *ParseExpression (FScanner &sc, PClassActor *cls, bool mustresolve)
{ {
FxExpression *data = ParseExpressionM (sc, cls); FxExpression *data = ParseExpressionM (sc, cls);
if (mustresolve)
{
FCompileContext ctx(cls); FCompileContext ctx(cls);
data = data->Resolve(ctx); data = data->Resolve(ctx);
}
return data; return data;
} }

View file

@ -984,7 +984,7 @@ public:
}; };
FxExpression *ParseExpression (FScanner &sc, PClassActor *cls); FxExpression *ParseExpression (FScanner &sc, PClassActor *cls, bool mustresolve = false);
#endif #endif

View file

@ -52,6 +52,7 @@
#include "thingdef_exp.h" #include "thingdef_exp.h"
#include "m_fixed.h" #include "m_fixed.h"
#include "vmbuilder.h" #include "vmbuilder.h"
#include "v_text.h"
ExpEmit::ExpEmit(VMFunctionBuilder *build, int type) ExpEmit::ExpEmit(VMFunctionBuilder *build, int type)
: RegNum(build->Registers[type].Get(1)), RegType(type), Konst(false), Fixed(false) : RegNum(build->Registers[type].Get(1)), RegType(type), Konst(false), Fixed(false)
@ -3546,15 +3547,25 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx)
if (clsname != NAME_None) if (clsname != NAME_None)
{ {
// for backwards compatibility with old times it cannot be made a fatal error, if the class is not defined. :( cls = PClass::FindClass(clsname);
cls = desttype->FindClassTentative(clsname, false); if (cls == NULL)
{
/* lax */
// Since this happens in released WADs it must pass without a terminal error... :(
ScriptPosition.Message(MSG_WARNING,
"Unknown class name '%s'",
clsname.GetChars(), desttype->TypeName.GetChars());
}
else
{
if (!cls->IsDescendantOf(desttype)) if (!cls->IsDescendantOf(desttype))
{ {
ScriptPosition.Message(MSG_ERROR,"class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars()); ScriptPosition.Message(MSG_ERROR, "class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars());
delete this; delete this;
return NULL; return NULL;
} }
ScriptPosition.Message(MSG_DEBUG,"resolving '%s' as class name", clsname.GetChars()); ScriptPosition.Message(MSG_DEBUG, "resolving '%s' as class name", clsname.GetChars());
}
} }
FxExpression *x = new FxConstant(cls, ScriptPosition); FxExpression *x = new FxConstant(cls, ScriptPosition);
delete this; delete this;

View file

@ -79,7 +79,7 @@ FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool c
} }
else if (type == TypeSInt32 || type == TypeFloat64) else if (type == TypeSInt32 || type == TypeFloat64)
{ {
x = ParseExpression (sc, cls); x = ParseExpression (sc, cls, constant);
if (constant && !x->isConstant()) if (constant && !x->isConstant())
{ {
sc.ScriptMessage("Default parameter must be constant."); sc.ScriptMessage("Default parameter must be constant.");
@ -190,7 +190,7 @@ static void ParseConstant (FScanner &sc, PSymbolTable *symt, PClassActor *cls)
sc.MustGetToken(TK_Identifier); sc.MustGetToken(TK_Identifier);
FName symname = sc.String; FName symname = sc.String;
sc.MustGetToken('='); sc.MustGetToken('=');
FxExpression *expr = ParseExpression (sc, cls); FxExpression *expr = ParseExpression (sc, cls, true);
sc.MustGetToken(';'); sc.MustGetToken(';');
if (!expr->isConstant()) if (!expr->isConstant())
@ -248,7 +248,7 @@ static void ParseEnum (FScanner &sc, PSymbolTable *symt, PClassActor *cls)
FName symname = sc.String; FName symname = sc.String;
if (sc.CheckToken('=')) if (sc.CheckToken('='))
{ {
FxExpression *expr = ParseExpression (sc, cls); FxExpression *expr = ParseExpression (sc, cls, true);
if (!expr->isConstant()) if (!expr->isConstant())
{ {
sc.ScriptMessage("'%s' must be constant", symname.GetChars()); sc.ScriptMessage("'%s' must be constant", symname.GetChars());
@ -536,7 +536,7 @@ static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClassActor *cl
if (sc.CheckToken('[')) if (sc.CheckToken('['))
{ {
FxExpression *expr = ParseExpression(sc, cls); FxExpression *expr = ParseExpression(sc, cls, true);
if (!expr->isConstant()) if (!expr->isConstant())
{ {
sc.ScriptMessage("Array size must be a constant"); sc.ScriptMessage("Array size must be a constant");

View file

@ -1534,12 +1534,12 @@ DEFINE_PROPERTY(riplevelmax, I, Actor)
//========================================================================== //==========================================================================
DEFINE_CLASS_PROPERTY(restrictedto, Ssssssssssssssssssss, Inventory) DEFINE_CLASS_PROPERTY(restrictedto, Ssssssssssssssssssss, Inventory)
{ {
info->RestrictedToPlayerClass.Clear(); static_cast<PClassInventory*>(info)->RestrictedToPlayerClass.Clear();
for(int i = 0;i < PROP_PARM_COUNT;++i) for(int i = 0;i < PROP_PARM_COUNT;++i)
{ {
PROP_STRING_PARM(n, i); PROP_STRING_PARM(n, i);
if (*n != 0) if (*n != 0)
info->RestrictedToPlayerClass.Push(FindClassTentativePlayerPawn(n)); static_cast<PClassInventory*>(info)->RestrictedToPlayerClass.Push(FindClassTentativePlayerPawn(n));
} }
} }
@ -1548,12 +1548,12 @@ DEFINE_CLASS_PROPERTY(restrictedto, Ssssssssssssssssssss, Inventory)
//========================================================================== //==========================================================================
DEFINE_CLASS_PROPERTY(forbiddento, Ssssssssssssssssssss, Inventory) DEFINE_CLASS_PROPERTY(forbiddento, Ssssssssssssssssssss, Inventory)
{ {
info->ForbiddenToPlayerClass.Clear(); static_cast<PClassInventory*>(info)->ForbiddenToPlayerClass.Clear();
for(int i = 0;i < PROP_PARM_COUNT;++i) for(int i = 0;i < PROP_PARM_COUNT;++i)
{ {
PROP_STRING_PARM(n, i); PROP_STRING_PARM(n, i);
if (*n != 0) if (*n != 0)
info->ForbiddenToPlayerClass.Push(FindClassTentativePlayerPawn(n)); static_cast<PClassInventory*>(info)->ForbiddenToPlayerClass.Push(FindClassTentativePlayerPawn(n));
} }
} }

View file

@ -32,6 +32,10 @@ ACTOR Actor native //: Thinker
RipLevelMin 0 RipLevelMin 0
RipLevelMax 0 RipLevelMax 0
DefThreshold 100 DefThreshold 100
BloodType "Blood", "BloodSplatter", "AxeBlood"
ExplosionDamage 128
MissileHeight 32
// Functions // Functions
native bool CheckClass(class<Actor> checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); native bool CheckClass(class<Actor> checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false);