- properly handle all meta properties for inventory items.

This commit is contained in:
Christoph Oelckers 2017-02-28 00:45:16 +01:00
parent f343d36ea9
commit 78a66e001a
17 changed files with 60 additions and 46 deletions

View file

@ -486,6 +486,7 @@ public:
PalEntry &ColorVar(FName field); PalEntry &ColorVar(FName field);
FName &NameVar(FName field); FName &NameVar(FName field);
double &FloatVar(FName field); double &FloatVar(FName field);
FString &StringVar(FName field);
template<class T> T*& PointerVar(FName field); template<class T> T*& PointerVar(FName field);
// If you need to replace one object with another and want to // If you need to replace one object with another and want to

View file

@ -2892,6 +2892,7 @@ PClass::PClass()
bExported = false; bExported = false;
bDecorateClass = false; bDecorateClass = false;
ConstructNative = nullptr; ConstructNative = nullptr;
Meta = nullptr;
mDescriptiveName = "Class"; mDescriptiveName = "Class";
PClass::AllClasses.Push(this); PClass::AllClasses.Push(this);
@ -3085,11 +3086,10 @@ void PClass::InitializeSpecials(void *addr, void *defaults, TArray<FTypeAndOffse
{ {
// Once we reach a native class, we can stop going up the family tree, // Once we reach a native class, we can stop going up the family tree,
// since native classes handle initialization natively. // since native classes handle initialization natively.
if (!bRuntimeClass) if ((!bRuntimeClass && Inits == &PClass::SpecialInits) || ParentClass == nullptr)
{ {
return; return;
} }
assert(ParentClass != nullptr);
ParentClass->InitializeSpecials(addr, defaults, Inits); ParentClass->InitializeSpecials(addr, defaults, Inits);
for (auto tao : (this->*Inits)) for (auto tao : (this->*Inits))
{ {
@ -3179,11 +3179,27 @@ void PClass::InitializeDefaults()
memset(Defaults + sizeof(DObject), 0, Size - sizeof(DObject)); memset(Defaults + sizeof(DObject), 0, Size - sizeof(DObject));
} }
assert(MetaSize >= ParentClass->MetaSize);
if (MetaSize != 0) if (MetaSize != 0)
{ {
Meta = (BYTE*)M_Malloc(MetaSize); Meta = (BYTE*)M_Malloc(MetaSize);
memset(Meta, 0, MetaSize);
if (ParentClass->MetaSize > 0) memcpy(Meta, ParentClass->Meta, ParentClass->MetaSize); // Copy the defaults from the parent but leave the DObject part alone because it contains important data.
if (ParentClass->Meta != nullptr)
{
memcpy(Meta, ParentClass->Meta, ParentClass->MetaSize);
if (MetaSize > ParentClass->MetaSize)
{
memset(Meta + ParentClass->MetaSize, 0, MetaSize - ParentClass->MetaSize);
}
}
else
{
memset(Meta, 0, MetaSize);
}
if (MetaSize > 0) memcpy(Meta, ParentClass->Meta, ParentClass->MetaSize);
else memset(Meta, 0, MetaSize);
} }
} }
@ -3199,10 +3215,14 @@ void PClass::InitializeDefaults()
{ {
field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits); field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits);
} }
if (!(field->Flags & VARF_Native) && (field->Flags & VARF_Meta)) }
{ }
field->Type->SetDefaultValue(Meta, unsigned(field->Offset), &MetaInits); if (Meta != nullptr) ParentClass->InitializeSpecials(Meta, ParentClass->Meta, &PClass::MetaInits);
} for (const PField *field : Fields)
{
if (!(field->Flags & VARF_Native) && (field->Flags & VARF_Meta))
{
field->Type->SetDefaultValue(Meta, unsigned(field->Offset), &MetaInits);
} }
} }
} }
@ -3264,6 +3284,7 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
type->bRuntimeClass = true; type->bRuntimeClass = true;
Derive(type, name); Derive(type, name);
type->Size = size; type->Size = size;
type->MetaSize = MetaSize;
if (size != TentativeClass) if (size != TentativeClass)
{ {
type->InitializeDefaults(); type->InitializeDefaults();
@ -3344,7 +3365,7 @@ PField *PClass::AddField(FName name, PType *type, DWORD flags)
// Only initialize the defaults if they have already been created. // Only initialize the defaults if they have already been created.
// For ZScript this is not the case, it will first define all fields before // For ZScript this is not the case, it will first define all fields before
// setting up any defaults for any class. // setting up any defaults for any class.
if (field != nullptr && !(flags & VARF_Native) && Meta != nullptr) if (field != nullptr && !(flags & VARF_Native))
{ {
Meta = (BYTE *)M_Realloc(Meta, MetaSize); Meta = (BYTE *)M_Realloc(Meta, MetaSize);
memset(Meta + oldsize, 0, MetaSize - oldsize); memset(Meta + oldsize, 0, MetaSize - oldsize);
@ -3380,6 +3401,7 @@ PClass *PClass::FindClassTentative(FName name)
PClass *type = static_cast<PClass *>(GetClass()->CreateNew()); PClass *type = static_cast<PClass *>(GetClass()->CreateNew());
DPrintf(DMSG_SPAMMY, "Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars()); DPrintf(DMSG_SPAMMY, "Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars());
assert(MetaSize == 0);
Derive(type, name); Derive(type, name);
type->Size = TentativeClass; type->Size = TentativeClass;
TypeTable.AddType(type, RUNTIME_CLASS(PClass), 0, name, bucket); TypeTable.AddType(type, RUNTIME_CLASS(PClass), 0, name, bucket);

View file

@ -603,6 +603,7 @@ public:
void InitializeActorInfo(); void InitializeActorInfo();
void BuildFlatPointers(); void BuildFlatPointers();
void BuildArrayPointers(); void BuildArrayPointers();
void InitMeta();
void DestroySpecials(void *addr); void DestroySpecials(void *addr);
const PClass *NativeClass() const; const PClass *NativeClass() const;
@ -742,6 +743,11 @@ inline double &DObject::FloatVar(FName field)
return *(double*)ScriptVar(field, TypeFloat64); return *(double*)ScriptVar(field, TypeFloat64);
} }
inline FString &DObject::StringVar(FName field)
{
return *(FString*)ScriptVar(field, TypeString);
}
template<class T> template<class T>
inline T *&DObject::PointerVar(FName field) inline T *&DObject::PointerVar(FName field)
{ {

View file

@ -50,8 +50,6 @@ DEFINE_FIELD(AInventory, DropTime)
DEFINE_FIELD(AInventory, SpawnPointClass) DEFINE_FIELD(AInventory, SpawnPointClass)
DEFINE_FIELD(AInventory, PickupFlash) DEFINE_FIELD(AInventory, PickupFlash)
DEFINE_FIELD(AInventory, PickupSound) DEFINE_FIELD(AInventory, PickupSound)
DEFINE_FIELD(AInventory, GiveQuest)
DEFINE_FIELD(PClassActor, PickupMsg)
//=========================================================================== //===========================================================================
// //
@ -115,8 +113,7 @@ void AInventory::Serialize(FSerializer &arc)
("icon", Icon, def->Icon) ("icon", Icon, def->Icon)
("pickupsound", PickupSound, def->PickupSound) ("pickupsound", PickupSound, def->PickupSound)
("spawnpointclass", SpawnPointClass, def->SpawnPointClass) ("spawnpointclass", SpawnPointClass, def->SpawnPointClass)
("droptime", DropTime, def->DropTime) ("droptime", DropTime, def->DropTime);
("givequest", GiveQuest, def->GiveQuest);
} }
//=========================================================================== //===========================================================================

View file

@ -87,7 +87,6 @@ public:
FTextureID Icon; // Icon to show on status bar or HUD FTextureID Icon; // Icon to show on status bar or HUD
int DropTime; // Countdown after dropping int DropTime; // Countdown after dropping
PClassActor *SpawnPointClass; // For respawning like Heretic's mace PClassActor *SpawnPointClass; // For respawning like Heretic's mace
int GiveQuest; // Optionally give one of the quest items.
FTextureID AltHUDIcon; FTextureID AltHUDIcon;
DWORD ItemFlags; DWORD ItemFlags;

View file

@ -354,7 +354,6 @@ void PClassActor::DeriveData(PClass *newclass)
} }
// Inventory stuff // Inventory stuff
newa->PickupMsg = PickupMsg;
newa->ForbiddenToPlayerClass = ForbiddenToPlayerClass; newa->ForbiddenToPlayerClass = ForbiddenToPlayerClass;
newa->RestrictedToPlayerClass = RestrictedToPlayerClass; newa->RestrictedToPlayerClass = RestrictedToPlayerClass;

View file

@ -321,7 +321,6 @@ public:
double MissileHeight; double MissileHeight;
// These are only valid for inventory items. // These are only valid for inventory items.
FString PickupMsg;
TArray<PClassActor *> RestrictedToPlayerClass; TArray<PClassActor *> RestrictedToPlayerClass;
TArray<PClassActor *> ForbiddenToPlayerClass; TArray<PClassActor *> ForbiddenToPlayerClass;

View file

@ -398,6 +398,8 @@ xx(VisibleStartPitch)
xx(VisibleEndAngle) xx(VisibleEndAngle)
xx(VisibleEndPitch) xx(VisibleEndPitch)
xx(Format) xx(Format)
xx(PickupMsg)
xx(Respawnable)
// Various actor names which are used internally // Various actor names which are used internally
xx(MapSpot) xx(MapSpot)

View file

@ -541,11 +541,11 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
else if (def == DEF_Pickup && sc.Compare ("PickupMessage")) else if (def == DEF_Pickup && sc.Compare ("PickupMessage"))
{ {
sc.MustGetString (); sc.MustGetString ();
bag.Info->PickupMsg = sc.String; inv->StringVar(NAME_PickupMsg) = sc.String;
} }
else if (def == DEF_Pickup && sc.Compare ("Respawns")) else if (def == DEF_Pickup && sc.Compare ("Respawns"))
{ {
inv->BoolVar("Respawnable") = true; inv->BoolVar(NAME_Respawnable) = true;
} }
else if (def == DEF_BreakableDecoration && sc.Compare ("SolidOnDeath")) else if (def == DEF_BreakableDecoration && sc.Compare ("SolidOnDeath"))
{ {

View file

@ -874,7 +874,7 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul
else if (f->Type->IsKindOf(RUNTIME_CLASS(PString))) else if (f->Type->IsKindOf(RUNTIME_CLASS(PString)))
{ {
sc.MustGetString(); sc.MustGetString();
*(FString*)addr = sc.String; *(FString*)addr = strbin1(sc.String);
} }
else if (f->Type->IsKindOf(RUNTIME_CLASS(PClassPointer))) else if (f->Type->IsKindOf(RUNTIME_CLASS(PClassPointer)))
{ {

View file

@ -1831,16 +1831,6 @@ DEFINE_CLASS_PROPERTY(pickupflash, S, Inventory)
defaults->PickupFlash = FindClassTentative(str, RUNTIME_CLASS(AActor)); defaults->PickupFlash = FindClassTentative(str, RUNTIME_CLASS(AActor));
} }
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY(pickupmessage, T, Inventory)
{
PROP_STRING_PARM(str, 0);
assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
static_cast<PClassActor *>(info)->PickupMsg = str;
}
//========================================================================== //==========================================================================
// //
//========================================================================== //==========================================================================
@ -1875,15 +1865,6 @@ DEFINE_CLASS_PROPERTY(usesound, S, Inventory)
defaults->UseSound = str; defaults->UseSound = str;
} }
//==========================================================================
//
//==========================================================================
DEFINE_CLASS_PROPERTY(givequest, I, Inventory)
{
PROP_INT_PARM(i, 0);
defaults->GiveQuest = i;
}
//========================================================================== //==========================================================================
// //
//========================================================================== //==========================================================================

View file

@ -1007,6 +1007,11 @@ void ZCCCompiler::CompileAllFields()
type->Size = Classes[i]->Type()->ParentClass->Size; type->Size = Classes[i]->Type()->ParentClass->Size;
} }
} }
if (Classes[i]->Type()->ParentClass)
type->MetaSize = Classes[i]->Type()->ParentClass->MetaSize;
else
type->MetaSize = 0;
if (CompileFields(type, Classes[i]->Fields, nullptr, &Classes[i]->TreeNodes, false, !!HasNativeChildren.CheckKey(type))) if (CompileFields(type, Classes[i]->Fields, nullptr, &Classes[i]->TreeNodes, false, !!HasNativeChildren.CheckKey(type)))
{ {
// Remove from the list if all fields got compiled. // Remove from the list if all fields got compiled.

View file

@ -37,7 +37,7 @@ class Ammo : Inventory
{ {
int BackpackAmount; int BackpackAmount;
int BackpackMaxAmount; int BackpackMaxAmount;
/*meta*/ int DropAmount; meta int DropAmount;
property BackpackAmount: BackpackAmount; property BackpackAmount: BackpackAmount;
property BackpackMaxAmount: BackpackMaxAmount; property BackpackMaxAmount: BackpackMaxAmount;

View file

@ -36,8 +36,8 @@
class Health : Inventory class Health : Inventory
{ {
transient int PrevHealth; transient int PrevHealth;
/*meta*/ int LowHealth; meta int LowHealth;
/*meta*/ String LowHealthMessage; meta String LowHealthMessage;
property LowMessage: LowHealth, LowHealthMessage; property LowMessage: LowHealth, LowHealthMessage;

View file

@ -87,8 +87,8 @@ class MapRevealer : Inventory
class PuzzleItem : Inventory class PuzzleItem : Inventory
{ {
/*meta*/ int PuzzleItemNumber; meta int PuzzleItemNumber;
/*meta*/ String PuzzFailMessage; meta String PuzzFailMessage;
property Number: PuzzleItemNumber; property Number: PuzzleItemNumber;
property FailMessage: PuzzFailMessage; property FailMessage: PuzzFailMessage;

View file

@ -23,8 +23,11 @@ class Inventory : Actor native
native bool bPickupGood; native bool bPickupGood;
native bool bCreateCopyMoved; native bool bCreateCopyMoved;
native bool bInitEffectFailed; native bool bInitEffectFailed;
native meta String PickupMsg; meta String PickupMsg;
native /*meta*/ int GiveQuest; meta int GiveQuest;
Property PickupMessage: PickupMsg;
Property GiveQuest: GiveQuest;
Default Default
{ {

View file

@ -33,7 +33,7 @@ class Weapon : StateProvider native
native float FOVScale; native float FOVScale;
native int Crosshair; // 0 to use player's crosshair native int Crosshair; // 0 to use player's crosshair
native bool GivenAsMorphWeapon; native bool GivenAsMorphWeapon;
native bool bAltFire; // Set when self weapon's alternate fire is used. native bool bAltFire; // Set when this weapon's alternate fire is used.
native readonly bool bDehAmmo; native readonly bool bDehAmmo;
Default Default