- 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);
FName &NameVar(FName field);
double &FloatVar(FName field);
FString &StringVar(FName field);
template<class T> T*& PointerVar(FName field);
// If you need to replace one object with another and want to

View file

@ -2892,6 +2892,7 @@ PClass::PClass()
bExported = false;
bDecorateClass = false;
ConstructNative = nullptr;
Meta = nullptr;
mDescriptiveName = "Class";
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,
// since native classes handle initialization natively.
if (!bRuntimeClass)
if ((!bRuntimeClass && Inits == &PClass::SpecialInits) || ParentClass == nullptr)
{
return;
}
assert(ParentClass != nullptr);
ParentClass->InitializeSpecials(addr, defaults, Inits);
for (auto tao : (this->*Inits))
{
@ -3179,11 +3179,27 @@ void PClass::InitializeDefaults()
memset(Defaults + sizeof(DObject), 0, Size - sizeof(DObject));
}
assert(MetaSize >= ParentClass->MetaSize);
if (MetaSize != 0)
{
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);
}
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;
Derive(type, name);
type->Size = size;
type->MetaSize = MetaSize;
if (size != TentativeClass)
{
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.
// For ZScript this is not the case, it will first define all fields before
// 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);
memset(Meta + oldsize, 0, MetaSize - oldsize);
@ -3380,6 +3401,7 @@ PClass *PClass::FindClassTentative(FName name)
PClass *type = static_cast<PClass *>(GetClass()->CreateNew());
DPrintf(DMSG_SPAMMY, "Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars());
assert(MetaSize == 0);
Derive(type, name);
type->Size = TentativeClass;
TypeTable.AddType(type, RUNTIME_CLASS(PClass), 0, name, bucket);

View file

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

View file

@ -50,8 +50,6 @@ DEFINE_FIELD(AInventory, DropTime)
DEFINE_FIELD(AInventory, SpawnPointClass)
DEFINE_FIELD(AInventory, PickupFlash)
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)
("pickupsound", PickupSound, def->PickupSound)
("spawnpointclass", SpawnPointClass, def->SpawnPointClass)
("droptime", DropTime, def->DropTime)
("givequest", GiveQuest, def->GiveQuest);
("droptime", DropTime, def->DropTime);
}
//===========================================================================

View file

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

View file

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

View file

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

View file

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

View file

@ -541,11 +541,11 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
else if (def == DEF_Pickup && sc.Compare ("PickupMessage"))
{
sc.MustGetString ();
bag.Info->PickupMsg = sc.String;
inv->StringVar(NAME_PickupMsg) = sc.String;
}
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"))
{

View file

@ -874,7 +874,7 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul
else if (f->Type->IsKindOf(RUNTIME_CLASS(PString)))
{
sc.MustGetString();
*(FString*)addr = sc.String;
*(FString*)addr = strbin1(sc.String);
}
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));
}
//==========================================================================
//
//==========================================================================
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;
}
//==========================================================================
//
//==========================================================================
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;
}
}
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)))
{
// Remove from the list if all fields got compiled.

View file

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

View file

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

View file

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

View file

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

View file

@ -33,7 +33,7 @@ class Weapon : StateProvider native
native float FOVScale;
native int Crosshair; // 0 to use player's crosshair
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;
Default