From f343d36ea941829b68c239eb91d0f68c4e7a3b38 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Feb 2017 23:28:19 +0100 Subject: [PATCH 01/12] - implemented the basics of a working metadata system. This will store class meta properties in a separate memory block so that it won't have to muck around with PClass - which made the implementation from the scripting branch relatively useless because extending the data wasn't particularly easy and also not well implemented. This can now be handled just like the defaults. --- src/dobjtype.cpp | 105 ++++++++++++++++++---- src/dobjtype.h | 14 +-- src/intermission/intermission.h | 6 +- src/menu/menu.cpp | 2 +- src/scripting/backend/codegen.cpp | 8 +- src/scripting/decorate/thingdef_parse.cpp | 9 +- src/scripting/vm/vmexec.h | 8 +- src/scripting/vm/vmops.h | 3 +- src/scripting/zscript/zcc_compile.cpp | 14 +-- 9 files changed, 128 insertions(+), 41 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 75193b868..dcb93599d 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2910,6 +2910,11 @@ PClass::~PClass() M_Free(Defaults); Defaults = nullptr; } + if (Meta != nullptr) + { + M_Free(Meta); + Meta = nullptr; + } } //========================================================================== @@ -3047,7 +3052,7 @@ PClass *PClass::FindClass (FName zaname) // //========================================================================== -DObject *PClass::CreateNew() const +DObject *PClass::CreateNew() { BYTE *mem = (BYTE *)M_Malloc (Size); assert (mem != nullptr); @@ -3064,7 +3069,7 @@ DObject *PClass::CreateNew() const } ConstructNative (mem); ((DObject *)mem)->SetClass (const_cast(this)); - InitializeSpecials(mem, Defaults); + InitializeSpecials(mem, Defaults, &PClass::SpecialInits); return (DObject *)mem; } @@ -3076,7 +3081,7 @@ DObject *PClass::CreateNew() const // //========================================================================== -void PClass::InitializeSpecials(void *addr, void *defaults) const +void PClass::InitializeSpecials(void *addr, void *defaults, TArray PClass::*Inits) { // Once we reach a native class, we can stop going up the family tree, // since native classes handle initialization natively. @@ -3085,8 +3090,8 @@ void PClass::InitializeSpecials(void *addr, void *defaults) const return; } assert(ParentClass != nullptr); - ParentClass->InitializeSpecials(addr, defaults); - for (auto tao : SpecialInits) + ParentClass->InitializeSpecials(addr, defaults, Inits); + for (auto tao : (this->*Inits)) { tao.first->InitializeValue((char*)addr + tao.second, defaults == nullptr? nullptr : ((char*)defaults) + tao.second); } @@ -3101,7 +3106,7 @@ void PClass::InitializeSpecials(void *addr, void *defaults) const // //========================================================================== -void PClass::DestroySpecials(void *addr) const +void PClass::DestroySpecials(void *addr) { // Once we reach a native class, we can stop going up the family tree, // since native classes handle deinitialization natively. @@ -3160,7 +3165,6 @@ void PClass::InitializeDefaults() optr->ObjNext = nullptr; optr->SetClass(this); - // Copy the defaults from the parent but leave the DObject part alone because it contains important data. if (ParentClass->Defaults != nullptr) { @@ -3174,19 +3178,31 @@ void PClass::InitializeDefaults() { memset(Defaults + sizeof(DObject), 0, Size - sizeof(DObject)); } + + if (MetaSize != 0) + { + Meta = (BYTE*)M_Malloc(MetaSize); + memset(Meta, 0, MetaSize); + if (ParentClass->MetaSize > 0) memcpy(Meta, ParentClass->Meta, ParentClass->MetaSize); + } } if (bRuntimeClass) { // Copy parent values from the parent defaults. assert(ParentClass != nullptr); - if (Defaults != nullptr) ParentClass->InitializeSpecials(Defaults, ParentClass->Defaults); + if (Defaults != nullptr) ParentClass->InitializeSpecials(Defaults, ParentClass->Defaults, &PClass::SpecialInits); + if (Meta != nullptr) ParentClass->InitializeSpecials(Meta, ParentClass->Meta, &PClass::MetaInits); for (const PField *field : Fields) { - if (!(field->Flags & VARF_Native)) + if (!(field->Flags & VARF_Native) && !(field->Flags & VARF_Meta)) { 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); + } } } } @@ -3264,6 +3280,39 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size) return type; } +//========================================================================== +// +// PStruct :: AddField +// +// Appends a new metadata field to the end of a struct. Returns either the new field +// or nullptr if a symbol by that name already exists. +// +//========================================================================== + +PField *PClass::AddMetaField(FName name, PType *type, DWORD flags) +{ + PField *field = new PField(name, type, flags); + + // The new field is added to the end of this struct, alignment permitting. + field->Offset = (MetaSize + (type->Align - 1)) & ~(type->Align - 1); + + // Enlarge this struct to enclose the new field. + MetaSize = unsigned(field->Offset + type->Size); + + // This struct's alignment is the same as the largest alignment of any of + // its fields. + Align = MAX(Align, type->Align); + + if (Symbols.AddSymbol(field) == nullptr) + { // name is already in use + field->Destroy(); + return nullptr; + } + Fields.Push(field); + + return field; +} + //========================================================================== // // PClass :: AddField @@ -3272,18 +3321,36 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size) PField *PClass::AddField(FName name, PType *type, DWORD flags) { - unsigned oldsize = Size; - PField *field = Super::AddField(name, type, 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) && Defaults != nullptr) + if (!(flags & VARF_Meta)) { - Defaults = (BYTE *)M_Realloc(Defaults, Size); - memset(Defaults + oldsize, 0, Size - oldsize); + unsigned oldsize = Size; + PField *field = Super::AddField(name, type, 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) && Defaults != nullptr) + { + Defaults = (BYTE *)M_Realloc(Defaults, Size); + memset(Defaults + oldsize, 0, Size - oldsize); + } + return field; + } + else + { + unsigned oldsize = MetaSize; + PField *field = AddMetaField(name, type, 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) + { + Meta = (BYTE *)M_Realloc(Meta, MetaSize); + memset(Meta + oldsize, 0, MetaSize - oldsize); + } + return field; } - return field; } //========================================================================== diff --git a/src/dobjtype.h b/src/dobjtype.h index 0151e6c11..c88b00930 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -557,12 +557,13 @@ enum class PClass : public PNativeStruct { DECLARE_CLASS(PClass, PNativeStruct); -protected: // We unravel _WITH_META here just as we did for PType. - TArray SpecialInits; +protected: + TArray MetaInits; void Derive(PClass *newclass, FName name); - void InitializeSpecials(void *addr, void *defaults) const; + void InitializeSpecials(void *addr, void *defaults, TArray PClass::*Inits); void SetSuper(); + PField *AddMetaField(FName name, PType *type, DWORD flags); public: void WriteValue(FSerializer &ar, const char *key,const void *addr) const override; void WriteAllFields(FSerializer &ar, const void *addr) const; @@ -577,11 +578,14 @@ public: static void StaticBootstrap(); // Per-class information ------------------------------------- + TArray SpecialInits; PClass *ParentClass; // the class this class derives from const size_t *Pointers; // object pointers defined by this class *only* const size_t *FlatPointers; // object pointers defined by this class and all its superclasses; not initialized by default const size_t *ArrayPointers; // dynamic arrays containing object pointers. BYTE *Defaults; + BYTE *Meta; // Per-class static script data + unsigned MetaSize; bool bRuntimeClass; // class was defined at run-time, not compile-time bool bExported; // This type has been declared in a script bool bDecorateClass; // may be subject to some idiosyncracies due to DECORATE backwards compatibility @@ -593,13 +597,13 @@ public: PClass(); ~PClass(); void InsertIntoHash(); - DObject *CreateNew() const; + DObject *CreateNew(); PClass *CreateDerivedClass(FName name, unsigned int size); PField *AddField(FName name, PType *type, DWORD flags=0) override; void InitializeActorInfo(); void BuildFlatPointers(); void BuildArrayPointers(); - void DestroySpecials(void *addr) const; + void DestroySpecials(void *addr); const PClass *NativeClass() const; // Returns true if this type is an ancestor of (or same as) the passed type. diff --git a/src/intermission/intermission.h b/src/intermission/intermission.h index cdc100d88..f0b423150 100644 --- a/src/intermission/intermission.h +++ b/src/intermission/intermission.h @@ -58,15 +58,15 @@ enum EScrollDir }; // actions that don't create objects -#define WIPER_ID ((const PClass*)intptr_t(-1)) -#define TITLE_ID ((const PClass*)intptr_t(-2)) +#define WIPER_ID ((PClass*)intptr_t(-1)) +#define TITLE_ID ((PClass*)intptr_t(-2)) //========================================================================== struct FIntermissionAction { int mSize; - const PClass *mClass; + PClass *mClass; FString mMusic; int mMusicOrder; int mCdTrack; diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 8b0bf35e9..1c8e0b39b 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -472,7 +472,7 @@ void M_SetMenu(FName menu, int param) } else { - const PClass *menuclass = PClass::FindClass(menu); + PClass *menuclass = PClass::FindClass(menu); if (menuclass != nullptr) { if (menuclass->IsDescendantOf("GenericMenu")) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index cc93c2215..bd18103fc 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -6371,7 +6371,7 @@ ExpEmit FxClassDefaults::Emit(VMFunctionBuilder *build) ExpEmit ob = obj->Emit(build); ob.Free(build); ExpEmit meta(build, REGT_POINTER); - build->Emit(OP_META, meta.RegNum, ob.RegNum); + build->Emit(OP_CLSS, meta.RegNum, ob.RegNum); build->Emit(OP_LOS, meta.RegNum, meta.RegNum, build->GetConstantInt(myoffsetof(PClass, Defaults))); return meta; @@ -6805,7 +6805,7 @@ ExpEmit FxStructMember::Emit(VMFunctionBuilder *build) { obj.Free(build); ExpEmit meta(build, REGT_POINTER); - build->Emit(OP_META, meta.RegNum, obj.RegNum); + build->Emit(membervar->Flags & VARF_Native? OP_CLSS : OP_META, meta.RegNum, obj.RegNum); obj = meta; } @@ -8832,7 +8832,7 @@ ExpEmit FxGetClass::Emit(VMFunctionBuilder *build) ExpEmit op = Self->Emit(build); op.Free(build); ExpEmit to(build, REGT_POINTER); - build->Emit(OP_META, to.RegNum, op.RegNum); + build->Emit(OP_CLSS, to.RegNum, op.RegNum); return to; } @@ -8873,7 +8873,7 @@ ExpEmit FxGetParentClass::Emit(VMFunctionBuilder *build) if (Self->IsObject()) { ExpEmit to(build, REGT_POINTER); - build->Emit(OP_META, to.RegNum, op.RegNum); + build->Emit(OP_CLSS, to.RegNum, op.RegNum); op = to; op.Free(build); } diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index e444d30a9..bd4d781a1 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -827,7 +827,14 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul if (i > 0) sc.MustGetStringName(","); if (f->Flags & VARF_Meta) { - addr = ((char*)bag.Info) + f->Offset; + if (f->Flags & VARF_Native) + { + addr = ((char*)bag.Info) + f->Offset; + } + else + { + addr = ((char*)bag.Info->Meta) + f->Offset; + } } else { diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index 3082abf80..c37e29cbf 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -109,12 +109,18 @@ begin: reg.atag[a] = ATAG_GENERIC; // using ATAG_FRAMEPOINTER will cause endless asserts. NEXTOP; - OP(META): + OP(CLSS): ASSERTA(a); ASSERTO(B); reg.a[a] = ((DObject*)reg.a[B])->GetClass(); // I wish this could be done without a special opcode but there's really no good way to guarantee initialization of the Class pointer... reg.atag[a] = ATAG_OBJECT; NEXTOP; + OP(META): + ASSERTA(a); ASSERTO(B); + reg.a[a] = ((DObject*)reg.a[B])->GetClass()->Meta; // I wish this could be done without a special opcode but there's really no good way to guarantee initialization of the Class pointer... + reg.atag[a] = ATAG_OBJECT; + NEXTOP; + OP(LB): ASSERTD(a); ASSERTA(B); ASSERTKD(C); GETADDR(PB,KC,X_READ_NIL); diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index b058dc94b..3d503932a 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -23,7 +23,8 @@ xx(LKF_R, lk, RFRII8, NOP, 0, 0), // load float constant indexed xx(LKS_R, lk, RSRII8, NOP, 0, 0), // load string constant indexed xx(LKP_R, lk, RPRII8, NOP, 0, 0), // load pointer constant indexed xx(LFP, lf, LFP, NOP, 0, 0), // load frame pointer -xx(META, meta, RPRP, NOP, 0, 0), // load a class's meta class address +xx(META, meta, RPRP, NOP, 0, 0), // load a class's meta data address +xx(CLSS, clss, RPRP, NOP, 0, 0), // load a class's descriptor address // Load from memory. rA = *(rB + rkC) xx(LB, lb, RIRPKI, LB_R, 4, REGT_INT), // load byte diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index b28226efb..6f902648e 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1070,11 +1070,6 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fiel if (field->Flags & ZCC_Meta) { varflags |= VARF_Meta | VARF_Static | VARF_ReadOnly; // metadata implies readonly - if (!(field->Flags & ZCC_Native)) - { - // Non-native meta data is not implemented yet and requires some groundwork in the class copy code. - Error(field, "Metadata member %s must be native", FName(field->Names->Name).GetChars()); - } } if (field->Type->ArraySize != nullptr) @@ -1692,7 +1687,14 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop if (f->Flags & VARF_Meta) { - addr = ((char*)bag.Info) + f->Offset; + if (f->Flags & VARF_Native) + { + addr = ((char*)bag.Info) + f->Offset; + } + else + { + addr = ((char*)bag.Info->Meta) + f->Offset; + } } else { From 78a66e001aa0c67e88f3fba81bdf2ce511542a3b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 00:45:16 +0100 Subject: [PATCH 02/12] - properly handle all meta properties for inventory items. --- src/dobject.h | 1 + src/dobjtype.cpp | 40 ++++++++++++++----- src/dobjtype.h | 6 +++ src/g_inventory/a_pickups.cpp | 5 +-- src/g_inventory/a_pickups.h | 1 - src/info.cpp | 1 - src/info.h | 1 - src/namedef.h | 2 + src/scripting/decorate/olddecorations.cpp | 4 +- src/scripting/decorate/thingdef_parse.cpp | 2 +- src/scripting/thingdef_properties.cpp | 19 --------- src/scripting/zscript/zcc_compile.cpp | 5 +++ wadsrc/static/zscript/inventory/ammo.txt | 2 +- wadsrc/static/zscript/inventory/health.txt | 4 +- wadsrc/static/zscript/inventory/inv_misc.txt | 4 +- wadsrc/static/zscript/inventory/inventory.txt | 7 +++- wadsrc/static/zscript/inventory/weapons.txt | 2 +- 17 files changed, 60 insertions(+), 46 deletions(-) diff --git a/src/dobject.h b/src/dobject.h index 41b5e2824..7510a4cff 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -486,6 +486,7 @@ public: PalEntry &ColorVar(FName field); FName &NameVar(FName field); double &FloatVar(FName field); + FString &StringVar(FName field); template T*& PointerVar(FName field); // If you need to replace one object with another and want to diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index dcb93599d..1d5cd1512 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -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, TArrayInitializeSpecials(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(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); diff --git a/src/dobjtype.h b/src/dobjtype.h index c88b00930..76e17b133 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -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 inline T *&DObject::PointerVar(FName field) { diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index 53e7d84ed..df6679d41 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -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); } //=========================================================================== diff --git a/src/g_inventory/a_pickups.h b/src/g_inventory/a_pickups.h index 817fcf176..9258d320a 100644 --- a/src/g_inventory/a_pickups.h +++ b/src/g_inventory/a_pickups.h @@ -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; diff --git a/src/info.cpp b/src/info.cpp index 7cac3569d..2bba8afb4 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -354,7 +354,6 @@ void PClassActor::DeriveData(PClass *newclass) } // Inventory stuff - newa->PickupMsg = PickupMsg; newa->ForbiddenToPlayerClass = ForbiddenToPlayerClass; newa->RestrictedToPlayerClass = RestrictedToPlayerClass; diff --git a/src/info.h b/src/info.h index 6d6329f88..f0f0f6c3c 100644 --- a/src/info.h +++ b/src/info.h @@ -321,7 +321,6 @@ public: double MissileHeight; // These are only valid for inventory items. - FString PickupMsg; TArray RestrictedToPlayerClass; TArray ForbiddenToPlayerClass; diff --git a/src/namedef.h b/src/namedef.h index 28de56818..df2841daa 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -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) diff --git a/src/scripting/decorate/olddecorations.cpp b/src/scripting/decorate/olddecorations.cpp index 50e8f9c6a..5c5714ba3 100644 --- a/src/scripting/decorate/olddecorations.cpp +++ b/src/scripting/decorate/olddecorations.cpp @@ -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")) { diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index bd4d781a1..e70059fec 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -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))) { diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index cf70b19ae..527782382 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -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(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; -} - //========================================================================== // //========================================================================== diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 6f902648e..1a9dfbe8d 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -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. diff --git a/wadsrc/static/zscript/inventory/ammo.txt b/wadsrc/static/zscript/inventory/ammo.txt index e742e806d..092a93846 100644 --- a/wadsrc/static/zscript/inventory/ammo.txt +++ b/wadsrc/static/zscript/inventory/ammo.txt @@ -37,7 +37,7 @@ class Ammo : Inventory { int BackpackAmount; int BackpackMaxAmount; - /*meta*/ int DropAmount; + meta int DropAmount; property BackpackAmount: BackpackAmount; property BackpackMaxAmount: BackpackMaxAmount; diff --git a/wadsrc/static/zscript/inventory/health.txt b/wadsrc/static/zscript/inventory/health.txt index 230b3575b..e2fb8eacf 100644 --- a/wadsrc/static/zscript/inventory/health.txt +++ b/wadsrc/static/zscript/inventory/health.txt @@ -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; diff --git a/wadsrc/static/zscript/inventory/inv_misc.txt b/wadsrc/static/zscript/inventory/inv_misc.txt index 441566786..ce4bf805b 100644 --- a/wadsrc/static/zscript/inventory/inv_misc.txt +++ b/wadsrc/static/zscript/inventory/inv_misc.txt @@ -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; diff --git a/wadsrc/static/zscript/inventory/inventory.txt b/wadsrc/static/zscript/inventory/inventory.txt index 06caedad7..cac9b9b8f 100644 --- a/wadsrc/static/zscript/inventory/inventory.txt +++ b/wadsrc/static/zscript/inventory/inventory.txt @@ -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 { diff --git a/wadsrc/static/zscript/inventory/weapons.txt b/wadsrc/static/zscript/inventory/weapons.txt index c76aaef54..de9464726 100644 --- a/wadsrc/static/zscript/inventory/weapons.txt +++ b/wadsrc/static/zscript/inventory/weapons.txt @@ -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 From a93a7e1cac9745aa8ec731e4015a3d7b71fe1da5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 01:23:12 +0100 Subject: [PATCH 03/12] - handle player meta properties. Only two really make sense, the rest is never used from scripts and may just remain where it was. --- src/d_player.h | 2 -- src/p_user.cpp | 3 --- src/scripting/thingdef_properties.cpp | 18 ----------------- src/scripting/zscript/zcc_compile.cpp | 6 ++++-- wadsrc/static/zscript/shared/player.txt | 26 ++++++++++++++----------- 5 files changed, 19 insertions(+), 36 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 2d7d439c5..43e6e53ab 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -159,8 +159,6 @@ public: FNameNoInit Face; // Doom status bar face (when used) FNameNoInit Portrait; FNameNoInit Slot[10]; - FNameNoInit InvulMode; - FNameNoInit HealingRadiusType; double HexenArmor[5]; BYTE ColorRangeStart; // Skin color range BYTE ColorRangeEnd; diff --git a/src/p_user.cpp b/src/p_user.cpp index 5bb0e2127..30db0a271 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -3325,13 +3325,10 @@ DEFINE_FIELD(APlayerPawn, FlechetteType) DEFINE_FIELD(APlayerPawn, DamageFade) DEFINE_FIELD(APlayerPawn, ViewBob) DEFINE_FIELD(APlayerPawn, FullHeight) - -DEFINE_FIELD(APlayerPawn, HealingRadiusType) DEFINE_FIELD(APlayerPawn, SoundClass) DEFINE_FIELD(APlayerPawn, Face) DEFINE_FIELD(APlayerPawn, Portrait) DEFINE_FIELD(APlayerPawn, Slot) -DEFINE_FIELD(APlayerPawn, InvulMode) DEFINE_FIELD(APlayerPawn, HexenArmor) DEFINE_FIELD(APlayerPawn, ColorRangeStart) DEFINE_FIELD(APlayerPawn, ColorRangeEnd) diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 527782382..09f6dcd95 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -2699,24 +2699,6 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, startitem, S_i, PlayerPawn) bag.DropItemList = di; } -//========================================================================== -// -//========================================================================== -DEFINE_CLASS_PROPERTY_PREFIX(player, invulnerabilitymode, S, PlayerPawn) -{ - PROP_STRING_PARM(str, 0); - defaults->InvulMode = str; -} - -//========================================================================== -// -//========================================================================== -DEFINE_CLASS_PROPERTY_PREFIX(player, healradiustype, S, PlayerPawn) -{ - PROP_STRING_PARM(str, 0); - defaults->HealingRadiusType = str; -} - //========================================================================== // //========================================================================== diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 1a9dfbe8d..548424cd9 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1188,8 +1188,10 @@ bool ZCCCompiler::CompileProperties(PClass *type, TArray &Proper FString qualifiedname; // Store the full qualified name and prepend some 'garbage' to the name so that no conflicts with other symbol types can happen. // All these will be removed from the symbol table after the compiler finishes to free up the allocated space. - if (prefix == NAME_None) qualifiedname.Format("@property@%s", FName(p->NodeName).GetChars()); - else qualifiedname.Format("@property@%s.%s", prefix.GetChars(), FName(p->NodeName).GetChars()); + FName name = FName(p->NodeName); + if (prefix == NAME_None) qualifiedname.Format("@property@%s", name.GetChars()); + else qualifiedname.Format("@property@%s.%s", prefix.GetChars(), name.GetChars()); + fields.ShrinkToFit(); if (!type->Symbols.AddSymbol(new PProperty(qualifiedname, fields))) { diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 8886e6744..9b686a551 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -8,18 +8,14 @@ class PlayerPawn : Actor native native int PlayerFlags; native Inventory InvFirst; // first inventory item displayed on inventory bar native Inventory InvSel; // selected inventory item - native meta String DisplayName; // Display name (used in menus, etc.) + native Name SoundClass; // Sound class + native Name Face; // Doom status bar face (when used) + native Name Portrait; + native Name Slot[10]; + native double HexenArmor[5]; + native uint8 ColorRangeStart; // Skin color range + native uint8 ColorRangeEnd; - native /*meta*/ Name SoundClass; // Sound class - native /*meta*/ Name Face; // Doom status bar face (when used) - native /*meta*/ Name Portrait; - native /*meta*/ Name Slot[10]; - native /*meta*/ Name InvulMode; - native /*meta*/ Name HealingRadiusType; - native /*meta*/ double HexenArmor[5]; - native /*meta*/ uint8 ColorRangeStart; // Skin color range - native /*meta*/ uint8 ColorRangeEnd; - // [GRB] Player class properties native double JumpZ; native double GruntSpeed; @@ -37,6 +33,14 @@ class PlayerPawn : Actor native native color DamageFade; // [CW] Fades for when you are being damaged. native double ViewBob; // [SP] ViewBob Multiplier native double FullHeight; + + native meta String DisplayName; // Display name (used in menus, etc.) + meta Name HealingRadiusType; + meta Name InvulMode; + + Property prefix: Player; + Property HealRadiusType: HealingradiusType; + Property InvulnerabilityMode: InvulMode; Default { From b6a1fe7fc6ac50409cc127c026e39387a5955f94 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 10:51:32 +0100 Subject: [PATCH 04/12] - scriptified the basic attack functions, its properties and the explosion properties to test the new metadata system. --- src/dobject.cpp | 14 +++- src/info.cpp | 13 ---- src/info.h | 9 --- src/namedef.h | 3 + src/p_actionfunctions.cpp | 87 +-------------------- src/p_mobj.cpp | 7 -- src/scripting/decorate/olddecorations.cpp | 6 +- src/scripting/thingdef_properties.cpp | 69 ----------------- src/scripting/zscript/zcc_parser.cpp | 1 + wadsrc/static/zscript/actor.txt | 92 ++++++++++++++++++++--- 10 files changed, 101 insertions(+), 200 deletions(-) diff --git a/src/dobject.cpp b/src/dobject.cpp index 747c1f9bf..b8097f549 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -623,12 +623,20 @@ DEFINE_ACTION_FUNCTION(DObject, MSTime) void *DObject::ScriptVar(FName field, PType *type) { - auto sym = dyn_cast(GetClass()->Symbols.FindSymbol(field, true)); + auto cls = GetClass(); + auto sym = dyn_cast(cls->Symbols.FindSymbol(field, true)); if (sym && (sym->Type == type || type == nullptr)) { - return (((char*)this) + sym->Offset); + if (!(sym->Flags & VARF_Meta)) + { + return (((char*)this) + sym->Offset); + } + else + { + return (cls->Meta + sym->Offset); + } } // This is only for internal use so I_Error is fine. - I_Error("Variable %s not found in %s\n", field.GetChars(), GetClass()->TypeName.GetChars()); + I_Error("Variable %s not found in %s\n", field.GetChars(), cls->TypeName.GetChars()); return nullptr; } diff --git a/src/info.cpp b/src/info.cpp index 2bba8afb4..0db6c7fbc 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -262,11 +262,6 @@ PClassActor::PClassActor() CameraHeight = INT_MIN; DropItems = NULL; - - DontHurtShooter = false; - ExplosionRadius = -1; - MeleeDamage = 0; - // Record this in the master list. AllActorClasses.Push(this); } @@ -330,14 +325,6 @@ void PClassActor::DeriveData(PClass *newclass) newa->DropItems = DropItems; - newa->DontHurtShooter = DontHurtShooter; - newa->ExplosionRadius = ExplosionRadius; - newa->ExplosionDamage = ExplosionDamage; - newa->MeleeDamage = MeleeDamage; - newa->MeleeSound = MeleeSound; - newa->MissileName = MissileName; - newa->MissileHeight = MissileHeight; - newa->VisibleToPlayerClass = VisibleToPlayerClass; if (DamageFactors != NULL) diff --git a/src/info.h b/src/info.h index f0f0f6c3c..9e684f462 100644 --- a/src/info.h +++ b/src/info.h @@ -311,15 +311,6 @@ public: FString SourceLumpName; FIntCVar *distancecheck; - // Old Decorate compatibility stuff - bool DontHurtShooter; - int ExplosionRadius; - int ExplosionDamage; - int MeleeDamage; - FSoundID MeleeSound; - FName MissileName; - double MissileHeight; - // These are only valid for inventory items. TArray RestrictedToPlayerClass; TArray ForbiddenToPlayerClass; diff --git a/src/namedef.h b/src/namedef.h index df2841daa..196c41fd0 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -400,6 +400,9 @@ xx(VisibleEndPitch) xx(Format) xx(PickupMsg) xx(Respawnable) +xx(ExplosionDamage) +xx(ExplosionRadius) +xx(DontHurtShooter) // Various actor names which are used internally xx(MapSpot) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 54a577e5b..1f6e6df7f 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -86,7 +86,6 @@ AActor *SingleActorFromTID(int tid, AActor *defactor); static FRandom pr_camissile ("CustomActorfire"); -static FRandom pr_camelee ("CustomMelee"); static FRandom pr_cabullet ("CustomBullet"); static FRandom pr_cajump ("CustomJump"); static FRandom pr_cwbullet ("CustomWpBullet"); @@ -924,86 +923,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_CopyFriendliness) return 0; } -//========================================================================== -// -// Customizable attack functions which use actor parameters. -// -//========================================================================== -static void DoAttack (AActor *self, bool domelee, bool domissile, - int MeleeDamage, FSoundID MeleeSound, PClassActor *MissileType,double MissileHeight) -{ - if (self->target == NULL) return; - - A_FaceTarget (self); - if (domelee && MeleeDamage>0 && self->CheckMeleeRange ()) - { - int damage = pr_camelee.HitDice(MeleeDamage); - if (MeleeSound) S_Sound (self, CHAN_WEAPON, MeleeSound, 1, ATTN_NORM); - int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); - } - else if (domissile && MissileType != NULL) - { - // This seemingly senseless code is needed for proper aiming. - double add = MissileHeight + self->GetBobOffset() - 32; - self->AddZ(add); - AActor *missile = P_SpawnMissileXYZ (self->PosPlusZ(32.), self, self->target, MissileType, false); - self->AddZ(-add); - - if (missile) - { - // automatic handling of seeker missiles - if (missile->flags2&MF2_SEEKERMISSILE) - { - missile->tracer=self->target; - } - P_CheckMissileSpawn(missile, self->radius); - } - } -} - -DEFINE_ACTION_FUNCTION(AActor, A_MeleeAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - int MeleeDamage = self->GetClass()->MeleeDamage; - FSoundID MeleeSound = self->GetClass()->MeleeSound; - DoAttack(self, true, false, MeleeDamage, MeleeSound, NULL, 0); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_MissileAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - PClassActor *MissileType = PClass::FindActor(self->GetClass()->MissileName); - DoAttack(self, false, true, 0, 0, MissileType, self->GetClass()->MissileHeight); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_ComboAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - int MeleeDamage = self->GetClass()->MeleeDamage; - FSoundID MeleeSound = self->GetClass()->MeleeSound; - PClassActor *MissileType = PClass::FindActor(self->GetClass()->MissileName); - DoAttack(self, true, true, MeleeDamage, MeleeSound, MissileType, self->GetClass()->MissileHeight); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_BasicAttack) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_INT (melee_damage); - PARAM_SOUND (melee_sound); - PARAM_CLASS (missile_type, AActor); - PARAM_FLOAT (missile_height); - - if (missile_type != NULL) - { - DoAttack(self, true, true, melee_damage, melee_sound, missile_type, missile_height); - } - return 0; -} - //========================================================================== // // Custom sound functions. @@ -1261,9 +1180,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_Explode) if (damage < 0) // get parameters from metadata { - damage = self->GetClass()->ExplosionDamage; - distance = self->GetClass()->ExplosionRadius; - flags = !self->GetClass()->DontHurtShooter; + damage = self->IntVar(NAME_ExplosionDamage); + distance = self->IntVar(NAME_ExplosionRadius); + flags = !self->BoolVar(NAME_DontHurtShooter); alert = false; } if (distance <= 0) distance = damage; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 88bb1d40a..40fa7e0c9 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -328,13 +328,6 @@ DEFINE_FIELD(PClassActor, HowlSound) DEFINE_FIELD(PClassActor, BloodType) DEFINE_FIELD(PClassActor, BloodType2) DEFINE_FIELD(PClassActor, BloodType3) -DEFINE_FIELD(PClassActor, DontHurtShooter) -DEFINE_FIELD(PClassActor, ExplosionRadius) -DEFINE_FIELD(PClassActor, ExplosionDamage) -DEFINE_FIELD(PClassActor, MeleeDamage) -DEFINE_FIELD(PClassActor, MeleeSound) -DEFINE_FIELD(PClassActor, MissileName) -DEFINE_FIELD(PClassActor, MissileHeight) //========================================================================== // diff --git a/src/scripting/decorate/olddecorations.cpp b/src/scripting/decorate/olddecorations.cpp index 5c5714ba3..8d220ec70 100644 --- a/src/scripting/decorate/olddecorations.cpp +++ b/src/scripting/decorate/olddecorations.cpp @@ -445,18 +445,18 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults, else if (def == DEF_Projectile && sc.Compare ("ExplosionRadius")) { sc.MustGetNumber (); - bag.Info->ExplosionRadius = sc.Number; + defaults->IntVar(NAME_ExplosionRadius) = sc.Number; extra.bExplosive = true; } else if (def == DEF_Projectile && sc.Compare ("ExplosionDamage")) { sc.MustGetNumber (); - bag.Info->ExplosionDamage = sc.Number; + defaults->IntVar(NAME_ExplosionDamage) = sc.Number; extra.bExplosive = true; } else if (def == DEF_Projectile && sc.Compare ("DoNotHurtShooter")) { - bag.Info->DontHurtShooter = true; + defaults->BoolVar(NAME_DontHurtShooter) = true; } else if (def == DEF_Projectile && sc.Compare ("Damage")) { diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 09f6dcd95..0e34e2da4 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -1001,35 +1001,6 @@ DEFINE_PROPERTY(hitobituary, S, Actor) static_cast(info)->HitObituary = str; } -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(donthurtshooter, 0, Actor) -{ - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->DontHurtShooter = true; -} - -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(explosionradius, I, Actor) -{ - PROP_INT_PARM(id, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->ExplosionRadius = id; -} - -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(explosiondamage, I, Actor) -{ - PROP_INT_PARM(id, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->ExplosionDamage = id; -} - //========================================================================== // //========================================================================== @@ -1068,16 +1039,6 @@ DEFINE_PROPERTY(meleethreshold, F, Actor) defaults->meleethreshold = id; } -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(meleedamage, I, Actor) -{ - PROP_INT_PARM(id, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->MeleeDamage = id; -} - //========================================================================== // //========================================================================== @@ -1087,36 +1048,6 @@ DEFINE_PROPERTY(meleerange, F, Actor) defaults->meleerange = id; } -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(meleesound, S, Actor) -{ - PROP_STRING_PARM(str, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->MeleeSound = str; -} - -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(missiletype, S, Actor) -{ - PROP_STRING_PARM(str, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->MissileName = str; -} - -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(missileheight, F, Actor) -{ - PROP_DOUBLE_PARM(id, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->MissileHeight = id; -} - //========================================================================== // //========================================================================== diff --git a/src/scripting/zscript/zcc_parser.cpp b/src/scripting/zscript/zcc_parser.cpp index 501a7b2ea..439b495b4 100644 --- a/src/scripting/zscript/zcc_parser.cpp +++ b/src/scripting/zscript/zcc_parser.cpp @@ -281,6 +281,7 @@ static void ParseSingleFile(const char *filename, int lump, void *parser, ZCCPar tokentype = ZCC_FLOATCONST; break; + case TK_None: // 'NONE' is a token for SBARINFO but not here. case TK_Identifier: value.Int = FName(sc.String); tokentype = ZCC_IDENTIFIER; diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 99c23c7bf..6a12e00f8 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -189,7 +189,7 @@ class Actor : Thinker native native State MissileState; native voidptr /*DecalBase*/ DecalGenerator; native uint8 fountaincolor; - + native meta String Obituary; // Player was killed by this actor native meta String HitObituary; // Player was killed by this actor in melee native meta double DeathHeight; // Height on normal death @@ -204,15 +204,24 @@ class Actor : Thinker native native meta Name BloodType; // Blood replacement type native meta Name BloodType2; // Bloopsplatter replacement type native meta Name BloodType3; // AxeBlood replacement type - native meta bool DontHurtShooter; - native meta int ExplosionRadius; - native meta int ExplosionDamage; - native meta int MeleeDamage; - native meta Sound MeleeSound; - native meta Name MissileName; - native meta double MissileHeight; + meta bool DontHurtShooter; + meta int ExplosionRadius; + meta int ExplosionDamage; + meta int MeleeDamage; + meta Sound MeleeSound; + meta double MissileHeight; + meta Name MissileName; + Property prefix: none; + Property MeleeDamage: MeleeDamage; + Property MeleeSound: MeleeSound; + Property MissileHeight: MissileHeight; + Property MissileType: MissileName; + Property DontHurtShooter: DontHurtShooter; + Property ExplosionRadius: ExplosionRadius; + Property ExplosionDamage: ExplosionDamage; + // need some definition work first //FRenderStyle RenderStyle; //int ConversationRoot; // THe root of the current dialogue @@ -271,6 +280,7 @@ class Actor : Thinker native DefThreshold 100; BloodType "Blood", "BloodSplatter", "AxeBlood"; ExplosionDamage 128; + ExplosionRadius -1; // i.e. use ExplosionDamage value MissileHeight 32; SpriteAngle 0; SpriteRotation 0; @@ -724,6 +734,68 @@ class Actor : Thinker native // Meh, MBF redundant functions. Only for DeHackEd support. native bool A_LineEffect(int boomspecial = 0, int tag = 0); // End of MBF redundant functions. + + + //========================================================================== + // + // old customizable attack functions which use actor parameters. + // + //========================================================================== + + private void DoAttack (bool domelee, bool domissile, int MeleeDamage, Sound MeleeSound, Class MissileType,double MissileHeight) + { + if (target == NULL) return; + + A_FaceTarget (); + if (domelee && MeleeDamage>0 && CheckMeleeRange ()) + { + int damage = random[CustomMelee](1, 8) * MeleeDamage; + if (MeleeSound) A_PlaySound (MeleeSound, CHAN_WEAPON); + int newdam = target.DamageMobj (self, self, damage, 'Melee'); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + } + else if (domissile && MissileType != NULL) + { + // This seemingly senseless code is needed for proper aiming. + double add = MissileHeight + GetBobOffset() - 32; + AddZ(add); + Actor missile = SpawnMissileXYZ (Pos + (0, 0, 32), target, MissileType, false); + AddZ(-add); + + if (missile) + { + // automatic handling of seeker missiles + if (missile.bSeekerMissile) + { + missile.tracer = target; + } + missile.CheckMissileSpawn(radius); + } + } + } + + deprecated void A_MeleeAttack() + { + DoAttack(true, false, MeleeDamage, MeleeSound, NULL, 0); + } + + deprecated void A_MissileAttack() + { + Class MissileType = MissileName; + DoAttack(false, true, 0, 0, MissileType, MissileHeight); + } + + deprecated void A_ComboAttack() + { + Class MissileType = MissileName; + DoAttack(true, true, MeleeDamage, MeleeSound, MissileType, MissileHeight); + } + + void A_BasicAttack(int melee_damage, sound melee_sound, class missile_type, double missile_height) + { + DoAttack(true, true, melee_damage, melee_sound, missile_type, missile_height); + } + native void A_MonsterRail(); native void A_Pain(); @@ -753,9 +825,6 @@ class Actor : Thinker native native void A_Wander(int flags = 0); native void A_Look2(); - deprecated native void A_MissileAttack(); - deprecated native void A_MeleeAttack(); - deprecated native void A_ComboAttack(); deprecated native void A_BulletAttack(); native void A_WolfAttack(int flags = 0, sound whattoplay = "weapons/pistol", double snipe = 1.0, int maxdamage = 64, int blocksize = 128, int pointblank = 2, int longrange = 4, double runspeed = 160.0, class pufftype = "BulletPuff"); native void A_PlaySound(sound whattoplay = "weapons/pistol", int slot = CHAN_BODY, double volume = 1.0, bool looping = false, double attenuation = ATTN_NORM, bool local = false); @@ -793,7 +862,6 @@ class Actor : Thinker native native void A_RaiseMaster(int flags = 0); native void A_RaiseChildren(int flags = 0); native void A_RaiseSiblings(int flags = 0); - deprecated native void A_BasicAttack(int meleedamage, sound meleesound, class missiletype, double missileheight); action native bool, Actor A_ThrowGrenade(class itemtype, double zheight = 0, double xyvel = 0, double zvel = 0, bool useammo = true); native void A_Weave(int xspeed, int yspeed, double xdist, double ydist); native bool A_Morph(class type, int duration = 0, int flags = 0, class enter_flash = null, class exit_flash = null); From 1311f08f4714138fb1bfa837a91672760f77d944 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 12:11:25 +0100 Subject: [PATCH 05/12] - scriptified Actor.GetBloodType as a virtual function to allow mods more flexibility here. - made CameraHeight a modifiable actor property - it was readonly before. - allow accessing the type constants from ZScript, this required quite a bit of explicit coding because the type system has no capabilities to search for basic types by name. --- src/actor.h | 30 +--------- src/dobjtype.cpp | 4 -- src/info.cpp | 5 -- src/info.h | 4 -- src/p_mobj.cpp | 21 +++++-- src/scripting/backend/codegen.cpp | 80 ++++++++++++++++++++++++--- src/scripting/thingdef_properties.cpp | 34 +----------- wadsrc/static/zscript/actor.txt | 43 +++++++++++--- 8 files changed, 129 insertions(+), 92 deletions(-) diff --git a/src/actor.h b/src/actor.h index 2ed004740..6e64b6033 100644 --- a/src/actor.h +++ b/src/actor.h @@ -817,32 +817,7 @@ public: void SetAngle(DAngle ang, bool interpolate); void SetRoll(DAngle roll, bool interpolate); - PClassActor *GetBloodType(int type = 0) const - { - PClassActor *bloodcls; - if (type == 0) - { - bloodcls = PClass::FindActor(GetClass()->BloodType); - } - else if (type == 1) - { - bloodcls = PClass::FindActor(GetClass()->BloodType2); - } - else if (type == 2) - { - bloodcls = PClass::FindActor(GetClass()->BloodType3); - } - else - { - return NULL; - } - - if (bloodcls != NULL) - { - bloodcls = bloodcls->GetReplacement(); - } - return bloodcls; - } + PClassActor *GetBloodType(int type = 0) const; double Distance2DSquared(AActor *other, bool absolute = false) { @@ -1048,7 +1023,8 @@ public: double renderradius; double projectilepassheight; // height for clipping projectile movement against this actor - + double CameraHeight; // Height of camera when used as such + SDWORD tics; // state tic counter FState *state; //VMFunction *Damage; // For missiles and monster railgun diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 1d5cd1512..f86797dfd 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -722,10 +722,6 @@ PBool::PBool() { mDescriptiveName = "Bool"; MemberOnly = false; - // Override the default max set by PInt's constructor - PSymbolConstNumeric *maxsym = static_cast(Symbols.FindSymbol(NAME_Max, false)); - assert(maxsym != nullptr && maxsym->IsKindOf(RUNTIME_CLASS(PSymbolConstNumeric))); - maxsym->Value = 1; } /* PFloat *****************************************************************/ diff --git a/src/info.cpp b/src/info.cpp index 0db6c7fbc..6f9b95f36 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -259,7 +259,6 @@ PClassActor::PClassActor() RDFactor = 1.; SelfDamageFactor = 1.; StealthAlpha = 0.; - CameraHeight = INT_MIN; DropItems = NULL; // Record this in the master list. @@ -316,11 +315,7 @@ void PClassActor::DeriveData(PClass *newclass) newa->RDFactor = RDFactor; newa->SelfDamageFactor = SelfDamageFactor; newa->StealthAlpha = StealthAlpha; - newa->CameraHeight = CameraHeight; newa->HowlSound = HowlSound; - newa->BloodType = BloodType; - newa->BloodType2 = BloodType2; - newa->BloodType3 = BloodType3; newa->distancecheck = distancecheck; newa->DropItems = DropItems; diff --git a/src/info.h b/src/info.h index 9e684f462..fd8914546 100644 --- a/src/info.h +++ b/src/info.h @@ -300,12 +300,8 @@ public: double FastSpeed; // speed in fast mode double RDFactor; // Radius damage factor double SelfDamageFactor; - double CameraHeight; // Height of camera when used as such double StealthAlpha; // Minmum alpha for MF_STEALTH. FSoundID HowlSound; // Sound being played when electrocuted or poisoned - FName BloodType; // Blood replacement type - FName BloodType2; // Bloopsplatter replacement type - FName BloodType3; // AxeBlood replacement type FDropItem *DropItems; FString SourceLumpName; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 40fa7e0c9..d95bae5b2 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -311,6 +311,7 @@ DEFINE_FIELD(AActor, ConversationRoot) DEFINE_FIELD(AActor, Conversation) DEFINE_FIELD(AActor, DecalGenerator) DEFINE_FIELD(AActor, fountaincolor) +DEFINE_FIELD(AActor, CameraHeight) DEFINE_FIELD(PClassActor, Obituary) DEFINE_FIELD(PClassActor, HitObituary) @@ -323,11 +324,7 @@ DEFINE_FIELD(PClassActor, FastSpeed) DEFINE_FIELD(PClassActor, RDFactor) DEFINE_FIELD(PClassActor, SelfDamageFactor) DEFINE_FIELD(PClassActor, StealthAlpha) -DEFINE_FIELD(PClassActor, CameraHeight) DEFINE_FIELD(PClassActor, HowlSound) -DEFINE_FIELD(PClassActor, BloodType) -DEFINE_FIELD(PClassActor, BloodType2) -DEFINE_FIELD(PClassActor, BloodType3) //========================================================================== // @@ -488,6 +485,7 @@ void AActor::Serialize(FSerializer &arc) A("spriteangle", SpriteAngle) A("spriterotation", SpriteRotation) ("alternative", alternative) + A("cameraheight", CameraHeight) A("tag", Tag) A("visiblestartangle",VisibleStartAngle) A("visibleendangle",VisibleEndAngle) @@ -3816,6 +3814,19 @@ void AActor::SetRoll(DAngle r, bool interpolate) } } +PClassActor *AActor::GetBloodType(int type) const +{ + IFVIRTUAL(AActor, GetBloodType) + { + VMValue params[] = { (DObject*)this, type }; + PClassActor *res; + VMReturn ret((void**)&res); + GlobalVMStack.Call(func, params, countof(params), &ret, 1); + return res; + } + return nullptr; +} + DVector3 AActor::GetPortalTransition(double byoffset, sector_t **pSec) { @@ -7593,7 +7604,7 @@ int AActor::GetGibHealth() const double AActor::GetCameraHeight() const { - return GetClass()->CameraHeight == INT_MIN ? Height / 2 : GetClass()->CameraHeight; + return CameraHeight == INT_MIN ? Height / 2 : CameraHeight; } DEFINE_ACTION_FUNCTION(AActor, GetCameraHeight) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index bd18103fc..893a50eed 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -6088,19 +6088,85 @@ FxExpression *FxMemberIdentifier::Resolve(FCompileContext& ctx) if (Object->ExprType == EFX_Identifier) { + auto id = static_cast(Object)->Identifier; // If the left side is a class name for a static member function call it needs to be resolved manually // because the resulting value type would cause problems in nearly every other place where identifiers are being used. - ccls = FindStructType(static_cast(Object)->Identifier, ctx); - if (ccls != nullptr) static_cast(Object)->noglobal = true; + ccls = FindStructType(id, ctx); + if (ccls != nullptr) + { + static_cast(Object)->noglobal = true; + } + else + { + PType *type; + // Another special case to deal with here is constants assigned to non-struct types. The code below cannot deal with them so it needs to be done here explicitly. + // Thanks to the messed up search logic of the type system, which doesn't allow any search by type name for the basic types at all, + // we have to do this manually, though and check for all types that may have values attached explicitly. + // (What's the point of attached fields to types if you cannot even search for the types...???) + switch (id) + { + default: + type = nullptr; + break; + + case NAME_Byte: + case NAME_uint8: + type = TypeUInt8; + break; + + case NAME_sByte: + case NAME_int8: + type = TypeSInt8; + break; + + case NAME_uShort: + case NAME_uint16: + type = TypeUInt16; + break; + + case NAME_Short: + case NAME_int16: + type = TypeSInt16; + break; + + case NAME_Int: + type = TypeSInt32; + break; + + case NAME_uInt: + type = TypeUInt32; + break; + + case NAME_Float: + type = TypeFloat32; + break; + + case NAME_Double: + type = TypeFloat64; + break; + } + if (type != nullptr) + { + auto sym = type->Symbols.FindSymbol(Identifier, true); + if (sym != nullptr) + { + // non-struct symbols must be constant numbers and can only be defined internally. + assert(sym->IsKindOf(RUNTIME_CLASS(PSymbolConstNumeric))); + auto sn = static_cast(sym); + + VMValue vmv; + if (sn->ValueType->IsKindOf(RUNTIME_CLASS(PInt))) vmv = sn->Value; + else vmv = sn->Float; + auto x = new FxConstant(sn->ValueType, vmv, ScriptPosition); + delete this; + return x->Resolve(ctx); + } + } + } } SAFE_RESOLVE(Object, ctx); - if (Identifier == FName("allmap")) - { - int a = 2; - } - // check for class or struct constants if the left side is a type name. if (Object->ValueType == TypeError) { diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 0e34e2da4..3838c3a89 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -1121,37 +1121,6 @@ DEFINE_PROPERTY(bloodcolor, C, Actor) } -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(bloodtype, Sss, Actor) -{ - PROP_STRING_PARM(str, 0) - PROP_STRING_PARM(str1, 1) - PROP_STRING_PARM(str2, 2) - - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - PClassActor *ainfo = static_cast(info); - - FName blood = str; - // normal blood - ainfo->BloodType = blood; - - if (PROP_PARM_COUNT > 1) - { - blood = str1; - } - // blood splatter - ainfo->BloodType2 = blood; - - if (PROP_PARM_COUNT > 2) - { - blood = str2; - } - // axe blood - ainfo->BloodType3 = blood; -} - //========================================================================== // //========================================================================== @@ -1387,8 +1356,7 @@ DEFINE_PROPERTY(stealthalpha, F, Actor) DEFINE_PROPERTY(cameraheight, F, Actor) { PROP_DOUBLE_PARM(i, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->CameraHeight = i; + defaults->CameraHeight = i; } //========================================================================== diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 6a12e00f8..9796c3e8d 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -189,6 +189,7 @@ class Actor : Thinker native native State MissileState; native voidptr /*DecalBase*/ DecalGenerator; native uint8 fountaincolor; + native double CameraHeight; // Height of camera when used as such native meta String Obituary; // Player was killed by this actor native meta String HitObituary; // Player was killed by this actor in melee @@ -199,12 +200,11 @@ class Actor : Thinker native native meta int WoundHealth; // Health needed to enter wound state native meta double FastSpeed; // speed in fast mode native meta double RDFactor; // Radius damage factor - native meta double CameraHeight; // Height of camera when used as such native meta Sound HowlSound; // Sound being played when electrocuted or poisoned - native meta Name BloodType; // Blood replacement type - native meta Name BloodType2; // Bloopsplatter replacement type - native meta Name BloodType3; // AxeBlood replacement type - + + meta Name BloodType; // Blood replacement type + meta Name BloodType2; // Bloopsplatter replacement type + meta Name BloodType3; // AxeBlood replacement type meta bool DontHurtShooter; meta int ExplosionRadius; meta int ExplosionDamage; @@ -221,6 +221,7 @@ class Actor : Thinker native Property DontHurtShooter: DontHurtShooter; Property ExplosionRadius: ExplosionRadius; Property ExplosionDamage: ExplosionDamage; + Property BloodType: BloodType, BloodType2, BloodType3; // need some definition work first //FRenderStyle RenderStyle; @@ -248,7 +249,7 @@ class Actor : Thinker native Health DEFAULT_HEALTH; Reactiontime 8; Radius 20; - RenderRadius 0; + RenderRadius 0; Height 16; Mass 100; RenderStyle 'Normal'; @@ -288,6 +289,7 @@ class Actor : Thinker native VisibleAngles 0, 0; VisiblePitch 0, 0; DefaultStateUsage SUF_ACTOR|SUF_OVERLAY; + CameraHeight int.min; } // Functions @@ -320,7 +322,7 @@ class Actor : Thinker native virtual native void Touch(Actor toucher); virtual native void MarkPrecacheSounds(); - // Called by PIT_CheckThing to check if two actos actually can collide. + // Called by PIT_CheckThing to check if two actors actually can collide. virtual bool CanCollideWith(Actor other, bool passive) { return true; @@ -344,6 +346,33 @@ class Actor : Thinker native { return false; } + + virtual class GetBloodType(int type) + { + Class bloodcls; + if (type == 0) + { + bloodcls = BloodType; + } + else if (type == 1) + { + bloodcls = BloodType2; + } + else if (type == 2) + { + bloodcls = BloodType3; + } + else + { + return NULL; + } + + if (bloodcls != NULL) + { + bloodcls = GetReplacement(bloodcls); + } + return bloodcls; + } native static class GetReplacement(class cls); native static class GetReplacee(class cls); From 2a4a5e7a7064c615b5d9a68e4805e999e047fba4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 12:47:44 +0100 Subject: [PATCH 06/12] - refactored a few more native meta properties. --- src/actor.h | 4 +++ src/info.cpp | 8 ------ src/info.h | 4 --- src/namedef.h | 1 + src/p_interaction.cpp | 2 +- src/p_map.cpp | 4 +-- src/p_mobj.cpp | 36 +++++++++++++++++---------- src/scripting/thingdef_properties.cpp | 19 +++----------- wadsrc/static/zscript/actor.txt | 12 +++++++-- 9 files changed, 44 insertions(+), 46 deletions(-) diff --git a/src/actor.h b/src/actor.h index 6e64b6033..e7d84f09d 100644 --- a/src/actor.h +++ b/src/actor.h @@ -1025,6 +1025,10 @@ public: double projectilepassheight; // height for clipping projectile movement against this actor double CameraHeight; // Height of camera when used as such + double RadiusDamageFactor; // Radius damage factor + double SelfDamageFactor; + double StealthAlpha; // Minmum alpha for MF_STEALTH. + SDWORD tics; // state tic counter FState *state; //VMFunction *Damage; // For missiles and monster railgun diff --git a/src/info.cpp b/src/info.cpp index 6f9b95f36..b8abba976 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -255,10 +255,6 @@ PClassActor::PClassActor() BurnHeight = -1; GibHealth = INT_MIN; WoundHealth = 6; - FastSpeed = -1.; - RDFactor = 1.; - SelfDamageFactor = 1.; - StealthAlpha = 0.; DropItems = NULL; // Record this in the master list. @@ -311,10 +307,6 @@ void PClassActor::DeriveData(PClass *newclass) newa->BloodColor = BloodColor; newa->GibHealth = GibHealth; newa->WoundHealth = WoundHealth; - newa->FastSpeed = FastSpeed; - newa->RDFactor = RDFactor; - newa->SelfDamageFactor = SelfDamageFactor; - newa->StealthAlpha = StealthAlpha; newa->HowlSound = HowlSound; newa->distancecheck = distancecheck; diff --git a/src/info.h b/src/info.h index fd8914546..f2a6101e9 100644 --- a/src/info.h +++ b/src/info.h @@ -297,10 +297,6 @@ public: PalEntry BloodColor; // Colorized blood int GibHealth; // Negative health below which this monster dies an extreme death int WoundHealth; // Health needed to enter wound state - double FastSpeed; // speed in fast mode - double RDFactor; // Radius damage factor - double SelfDamageFactor; - double StealthAlpha; // Minmum alpha for MF_STEALTH. FSoundID HowlSound; // Sound being played when electrocuted or poisoned FDropItem *DropItems; diff --git a/src/namedef.h b/src/namedef.h index 196c41fd0..7c63eb785 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -392,6 +392,7 @@ xx(Radius) xx(ReactionTime) xx(MeleeRange) xx(Speed) +xx(FastSpeed) xx(Clamp) xx(VisibleStartAngle) xx(VisibleStartPitch) diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 4c23c8123..2af2a3da1 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1022,7 +1022,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da } if (target == source && damage < TELEFRAG_DAMAGE) { - damage = int(damage * target->GetClass()->SelfDamageFactor); + damage = int(damage * target->SelfDamageFactor); } // [MC] Changed it to check rawdamage here for consistency, even though that doesn't actually do anything diff --git a/src/p_map.cpp b/src/p_map.cpp index 70b18df7f..7e110dcbf 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -5680,7 +5680,7 @@ int P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bom { points = points * splashfactor; } - points *= thing->GetClass()->RDFactor; + points *= thing->RadiusDamageFactor; double check = int(points) * bombdamage; // points and bombdamage should be the same sign (the double cast of 'points' is needed to prevent overflows and incorrect values slipping through.) @@ -5759,7 +5759,7 @@ int P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bom dist = clamp(dist - fulldamagedistance, 0, dist); int damage = Scale(bombdamage, bombdistance - int(dist), bombdistance); - double factor = splashfactor * thing->GetClass()->RDFactor; + double factor = splashfactor * thing->RadiusDamageFactor; damage = int(damage * factor); if (damage > 0 || (bombspot->flags7 & MF7_FORCEZERORADIUSDMG)) { diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index d95bae5b2..9ccdde24e 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -312,6 +312,9 @@ DEFINE_FIELD(AActor, Conversation) DEFINE_FIELD(AActor, DecalGenerator) DEFINE_FIELD(AActor, fountaincolor) DEFINE_FIELD(AActor, CameraHeight) +DEFINE_FIELD(AActor, RadiusDamageFactor) +DEFINE_FIELD(AActor, SelfDamageFactor) +DEFINE_FIELD(AActor, StealthAlpha) DEFINE_FIELD(PClassActor, Obituary) DEFINE_FIELD(PClassActor, HitObituary) @@ -320,10 +323,6 @@ DEFINE_FIELD(PClassActor, BurnHeight) DEFINE_FIELD(PClassActor, BloodColor) DEFINE_FIELD(PClassActor, GibHealth) DEFINE_FIELD(PClassActor, WoundHealth) -DEFINE_FIELD(PClassActor, FastSpeed) -DEFINE_FIELD(PClassActor, RDFactor) -DEFINE_FIELD(PClassActor, SelfDamageFactor) -DEFINE_FIELD(PClassActor, StealthAlpha) DEFINE_FIELD(PClassActor, HowlSound) //========================================================================== @@ -490,7 +489,11 @@ void AActor::Serialize(FSerializer &arc) A("visiblestartangle",VisibleStartAngle) A("visibleendangle",VisibleEndAngle) A("visiblestartpitch",VisibleStartPitch) - A("visibleendpitch",VisibleEndPitch); + A("visibleendpitch",VisibleEndPitch) + A("rdfactor", RadiusDamageFactor) + A("selfdamagefactor", SelfDamageFactor) + A("stealthalpha", StealthAlpha); + } #undef A @@ -4105,9 +4108,9 @@ void AActor::Tick () else if (visdir < 0) { Alpha -= 1.5/TICRATE; - if (Alpha < GetClass()->StealthAlpha) + if (Alpha < StealthAlpha) { - Alpha = GetClass()->StealthAlpha; + Alpha = StealthAlpha; visdir = 0; } } @@ -4828,8 +4831,11 @@ AActor *AActor::StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t a actor->renderflags = (actor->renderflags & ~RF_FULLBRIGHT) | ActorRenderFlags::FromInt (st->GetFullbright()); actor->touching_sectorlist = nullptr; // NULL head of sector list // phares 3/13/98 actor->touching_rendersectors = nullptr; - if (G_SkillProperty(SKILLP_FastMonsters) && actor->GetClass()->FastSpeed >= 0) - actor->Speed = actor->GetClass()->FastSpeed; + if (G_SkillProperty(SKILLP_FastMonsters)) + { + double f = actor->FloatVar(NAME_FastSpeed); + if (f >= 0) actor->Speed = f; + } // set subsector and/or block links actor->LinkToWorld (nullptr, SpawningMapThing); @@ -6701,10 +6707,14 @@ static double GetDefaultSpeed(PClassActor *type) { if (type == NULL) return 0; - else if (G_SkillProperty(SKILLP_FastMonsters) && type->FastSpeed >= 0) - return type->FastSpeed; - else - return GetDefaultByType(type)->Speed; + + auto def = GetDefaultByType(type); + if (G_SkillProperty(SKILLP_FastMonsters)) + { + double f = def->FloatVar(NAME_FastSpeed); + if (f >= 0) return f; + } + return def->Speed; } DEFINE_ACTION_FUNCTION(AActor, GetDefaultSpeed) diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 3838c3a89..a6657ce97 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -1310,24 +1310,13 @@ DEFINE_PROPERTY(poisondamagetype, S, Actor) defaults->PoisonDamageType = poisondamagetype; } -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(fastspeed, F, Actor) -{ - PROP_DOUBLE_PARM(i, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->FastSpeed = i; -} - //========================================================================== // //========================================================================== DEFINE_PROPERTY(radiusdamagefactor, F, Actor) { PROP_DOUBLE_PARM(i, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->RDFactor = i; + defaults->RadiusDamageFactor = i; } //========================================================================== @@ -1336,8 +1325,7 @@ DEFINE_PROPERTY(radiusdamagefactor, F, Actor) DEFINE_PROPERTY(selfdamagefactor, F, Actor) { PROP_DOUBLE_PARM(i, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->SelfDamageFactor = i; + defaults->SelfDamageFactor = i; } //========================================================================== @@ -1346,8 +1334,7 @@ DEFINE_PROPERTY(selfdamagefactor, F, Actor) DEFINE_PROPERTY(stealthalpha, F, Actor) { PROP_DOUBLE_PARM(i, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->StealthAlpha = i; + defaults->StealthAlpha = i; } //========================================================================== diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 9796c3e8d..2fc0d6d3b 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -190,6 +190,9 @@ class Actor : Thinker native native voidptr /*DecalBase*/ DecalGenerator; native uint8 fountaincolor; native double CameraHeight; // Height of camera when used as such + native double RadiusDamageFactor; // Radius damage factor + native double SelfDamageFactor; + native double StealthAlpha; native meta String Obituary; // Player was killed by this actor native meta String HitObituary; // Player was killed by this actor in melee @@ -198,8 +201,6 @@ class Actor : Thinker native native meta color BloodColor; // Colorized blood native meta int GibHealth; // Negative health below which this monster dies an extreme death native meta int WoundHealth; // Health needed to enter wound state - native meta double FastSpeed; // speed in fast mode - native meta double RDFactor; // Radius damage factor native meta Sound HowlSound; // Sound being played when electrocuted or poisoned meta Name BloodType; // Blood replacement type @@ -212,6 +213,7 @@ class Actor : Thinker native meta Sound MeleeSound; meta double MissileHeight; meta Name MissileName; + meta double FastSpeed; // speed in fast mode Property prefix: none; Property MeleeDamage: MeleeDamage; @@ -222,6 +224,7 @@ class Actor : Thinker native Property ExplosionRadius: ExplosionRadius; Property ExplosionDamage: ExplosionDamage; Property BloodType: BloodType, BloodType2, BloodType3; + Property FastSpeed: FastSpeed; // need some definition work first //FRenderStyle RenderStyle; @@ -290,6 +293,11 @@ class Actor : Thinker native VisiblePitch 0, 0; DefaultStateUsage SUF_ACTOR|SUF_OVERLAY; CameraHeight int.min; + FastSpeed -1; + RadiusDamageFactor 1; + SelfDamageFactor 1; + StealthAlpha 0; + } // Functions From d5250d6b9f87af047214926e4c8f7ac14cb65032 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 12:56:35 +0100 Subject: [PATCH 07/12] - made WoundHealth modifiable to allow more control over the wound state. --- src/actor.h | 1 + src/info.cpp | 2 -- src/info.h | 1 - src/p_interaction.cpp | 2 +- src/p_mobj.cpp | 3 ++- src/scripting/thingdef_properties.cpp | 3 +-- wadsrc/static/zscript/actor.txt | 2 ++ 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/actor.h b/src/actor.h index e7d84f09d..739f08f4a 100644 --- a/src/actor.h +++ b/src/actor.h @@ -1028,6 +1028,7 @@ public: double RadiusDamageFactor; // Radius damage factor double SelfDamageFactor; double StealthAlpha; // Minmum alpha for MF_STEALTH. + int WoundHealth; // Health needed to enter wound state SDWORD tics; // state tic counter FState *state; diff --git a/src/info.cpp b/src/info.cpp index b8abba976..d81d4d874 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -254,7 +254,6 @@ PClassActor::PClassActor() DeathHeight = -1; BurnHeight = -1; GibHealth = INT_MIN; - WoundHealth = 6; DropItems = NULL; // Record this in the master list. @@ -306,7 +305,6 @@ void PClassActor::DeriveData(PClass *newclass) newa->BurnHeight = BurnHeight; newa->BloodColor = BloodColor; newa->GibHealth = GibHealth; - newa->WoundHealth = WoundHealth; newa->HowlSound = HowlSound; newa->distancecheck = distancecheck; diff --git a/src/info.h b/src/info.h index f2a6101e9..28a684281 100644 --- a/src/info.h +++ b/src/info.h @@ -296,7 +296,6 @@ public: double BurnHeight; // Height on burning death PalEntry BloodColor; // Colorized blood int GibHealth; // Negative health below which this monster dies an extreme death - int WoundHealth; // Health needed to enter wound state FSoundID HowlSound; // Sound being played when electrocuted or poisoned FDropItem *DropItems; diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 2af2a3da1..da60af8ad 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1536,7 +1536,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da woundstate = target->FindState(NAME_Wound, mod); if (woundstate != NULL) { - int woundhealth = target->GetClass()->WoundHealth; + int woundhealth = target->WoundHealth; if (target->health <= woundhealth) { diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 9ccdde24e..22cbe1e3f 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -315,6 +315,7 @@ DEFINE_FIELD(AActor, CameraHeight) DEFINE_FIELD(AActor, RadiusDamageFactor) DEFINE_FIELD(AActor, SelfDamageFactor) DEFINE_FIELD(AActor, StealthAlpha) +DEFINE_FIELD(AActor, WoundHealth) DEFINE_FIELD(PClassActor, Obituary) DEFINE_FIELD(PClassActor, HitObituary) @@ -322,7 +323,6 @@ DEFINE_FIELD(PClassActor, DeathHeight) DEFINE_FIELD(PClassActor, BurnHeight) DEFINE_FIELD(PClassActor, BloodColor) DEFINE_FIELD(PClassActor, GibHealth) -DEFINE_FIELD(PClassActor, WoundHealth) DEFINE_FIELD(PClassActor, HowlSound) //========================================================================== @@ -490,6 +490,7 @@ void AActor::Serialize(FSerializer &arc) A("visibleendangle",VisibleEndAngle) A("visiblestartpitch",VisibleStartPitch) A("visibleendpitch",VisibleEndPitch) + A("woundhealth", WoundHealth) A("rdfactor", RadiusDamageFactor) A("selfdamagefactor", SelfDamageFactor) A("stealthalpha", StealthAlpha); diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index a6657ce97..a70fa0c9e 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -608,8 +608,7 @@ DEFINE_PROPERTY(gibhealth, I, Actor) DEFINE_PROPERTY(woundhealth, I, Actor) { PROP_INT_PARM(id, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->WoundHealth = id; + defaults->WoundHealth = id; } //========================================================================== diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 2fc0d6d3b..4fa2323b0 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -297,6 +297,8 @@ class Actor : Thinker native RadiusDamageFactor 1; SelfDamageFactor 1; StealthAlpha 0; + WoundHealth 6; + } From 851984efe0649bda9583ecc834d948c1c241a9f0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 13:40:46 +0100 Subject: [PATCH 08/12] - made GetDeathHeight a virtual scripted function. - made GetGibHealth a virtual scripted function. - removed a few more native meta properties. --- src/dobject.h | 2 + src/dobjtype.h | 5 ++ src/gi.cpp | 1 + src/info.cpp | 8 ---- src/info.h | 4 -- src/namedef.h | 1 + src/p_acs.cpp | 4 +- src/p_actionfunctions.cpp | 16 ------- src/p_interaction.cpp | 20 ++------ src/p_mobj.cpp | 32 ++++++------- src/scripting/decorate/olddecorations.cpp | 4 +- src/scripting/thingdef_properties.cpp | 40 ---------------- wadsrc/static/zscript/actor.txt | 57 +++++++++++++++++++---- wadsrc/static/zscript/base.txt | 1 + 14 files changed, 80 insertions(+), 115 deletions(-) diff --git a/src/dobject.h b/src/dobject.h index 7510a4cff..d99fbee2b 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -41,6 +41,7 @@ class PClass; class PType; class FSerializer; +class FSoundID; class DObject; /* @@ -483,6 +484,7 @@ public: // Add other types as needed. bool &BoolVar(FName field); int &IntVar(FName field); + FSoundID &SoundVar(FName field); PalEntry &ColorVar(FName field); FName &NameVar(FName field); double &FloatVar(FName field); diff --git a/src/dobjtype.h b/src/dobjtype.h index 76e17b133..f589b4e48 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -728,6 +728,11 @@ inline int &DObject::IntVar(FName field) return *(int*)ScriptVar(field, TypeSInt32); } +inline FSoundID &DObject::SoundVar(FName field) +{ + return *(FSoundID*)ScriptVar(field, TypeSound); +} + inline PalEntry &DObject::ColorVar(FName field) { return *(PalEntry*)ScriptVar(field, TypeColor); diff --git a/src/gi.cpp b/src/gi.cpp index 672ca3263..ad5c5a0ee 100644 --- a/src/gi.cpp +++ b/src/gi.cpp @@ -56,6 +56,7 @@ DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, mBackButton) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, mStatscreenMapNameFont) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, mStatscreenEnteringFont) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, mStatscreenFinishedFont) +DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, gibfactor) const char *GameNames[17] = diff --git a/src/info.cpp b/src/info.cpp index d81d4d874..76ba0fbcb 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -251,10 +251,6 @@ PClassActor::PClassActor() DamageFactors = NULL; PainChances = NULL; - DeathHeight = -1; - BurnHeight = -1; - GibHealth = INT_MIN; - DropItems = NULL; // Record this in the master list. AllActorClasses.Push(this); @@ -301,11 +297,7 @@ void PClassActor::DeriveData(PClass *newclass) newa->DefaultStateUsage = DefaultStateUsage; newa->Obituary = Obituary; newa->HitObituary = HitObituary; - newa->DeathHeight = DeathHeight; - newa->BurnHeight = BurnHeight; newa->BloodColor = BloodColor; - newa->GibHealth = GibHealth; - newa->HowlSound = HowlSound; newa->distancecheck = distancecheck; newa->DropItems = DropItems; diff --git a/src/info.h b/src/info.h index 28a684281..cd21deac4 100644 --- a/src/info.h +++ b/src/info.h @@ -292,11 +292,7 @@ public: FString Obituary; // Player was killed by this actor FString HitObituary; // Player was killed by this actor in melee - double DeathHeight; // Height on normal death - double BurnHeight; // Height on burning death PalEntry BloodColor; // Colorized blood - int GibHealth; // Negative health below which this monster dies an extreme death - FSoundID HowlSound; // Sound being played when electrocuted or poisoned FDropItem *DropItems; FString SourceLumpName; diff --git a/src/namedef.h b/src/namedef.h index 7c63eb785..50bde739f 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -393,6 +393,7 @@ xx(ReactionTime) xx(MeleeRange) xx(Speed) xx(FastSpeed) +xx(HowlSound) xx(Clamp) xx(VisibleStartAngle) xx(VisibleStartPitch) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index baf15c110..6053ce85a 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4232,7 +4232,7 @@ enum SOUND_Howl, }; -static FSoundID GetActorSound(const AActor *actor, int soundtype) +static FSoundID GetActorSound(AActor *actor, int soundtype) { switch (soundtype) { @@ -4245,7 +4245,7 @@ static FSoundID GetActorSound(const AActor *actor, int soundtype) case SOUND_Bounce: return actor->BounceSound; case SOUND_WallBounce: return actor->WallBounceSound; case SOUND_CrushPain: return actor->CrushPainSound; - case SOUND_Howl: return actor->GetClass()->HowlSound; + case SOUND_Howl: return actor->SoundVar(NAME_HowlSound); default: return 0; } } diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 1f6e6df7f..b75949f01 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -438,22 +438,6 @@ DEFINE_ACTION_FUNCTION(AActor, GetSpawnHealth) return 0; } -//========================================================================== -// -// GetGibHealth -// -//========================================================================== -DEFINE_ACTION_FUNCTION(AActor, GetGibHealth) -{ - if (numret > 0) - { - PARAM_SELF_PROLOGUE(AActor); - ret->SetInt(self->GetGibHealth()); - return 1; - } - return 0; -} - //========================================================================== // // GetSpriteAngle diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index da60af8ad..9d8d63de0 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -411,23 +411,11 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags) } flags6 |= MF6_KILLED; - // [RH] Allow the death height to be overridden using metadata. - double metaheight = -1; - if (DamageType == NAME_Fire) + IFVIRTUAL(AActor, GetDeathHeight) { - metaheight = GetClass()->BurnHeight; - } - if (metaheight < 0) - { - metaheight = GetClass()->DeathHeight; - } - if (metaheight < 0) - { - Height *= 0.25; - } - else - { - Height = MAX (metaheight, 0); + VMValue params[] = { (DObject*)this }; + VMReturn ret(&Height); + GlobalVMStack.Call(func, params, 1, &ret, 1); } // [RH] If the thing has a special, execute and remove it diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 22cbe1e3f..bc432434c 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -319,11 +319,7 @@ DEFINE_FIELD(AActor, WoundHealth) DEFINE_FIELD(PClassActor, Obituary) DEFINE_FIELD(PClassActor, HitObituary) -DEFINE_FIELD(PClassActor, DeathHeight) -DEFINE_FIELD(PClassActor, BurnHeight) -DEFINE_FIELD(PClassActor, BloodColor) -DEFINE_FIELD(PClassActor, GibHealth) -DEFINE_FIELD(PClassActor, HowlSound) +//DEFINE_FIELD(PClassActor, BloodColor) //========================================================================== // @@ -3516,7 +3512,7 @@ int AActor::GetMissileDamage (int mask, int add) void AActor::Howl () { - FSoundID howl = GetClass()->HowlSound; + FSoundID howl = IntVar(NAME_HowlSound); if (!S_IsActorPlayingSomething(this, CHAN_BODY, howl)) { S_Sound (this, CHAN_BODY, howl, 1, ATTN_NORM); @@ -7481,9 +7477,10 @@ void AActor::Crash() { FState *crashstate = NULL; + int gibh = GetGibHealth(); if (DamageType != NAME_None) { - if (health < GetGibHealth()) + if (health < gibh) { // Extreme death FName labels[] = { NAME_Crash, NAME_Extreme, DamageType }; crashstate = FindState (3, labels, true); @@ -7495,7 +7492,7 @@ void AActor::Crash() } if (crashstate == NULL) { - if (health < GetGibHealth()) + if (health < gibh) { // Extreme death crashstate = FindState(NAME_Crash, NAME_Extreme); } @@ -7601,16 +7598,15 @@ void AActor::Revive() int AActor::GetGibHealth() const { - int gibhealth = GetClass()->GibHealth; - - if (gibhealth != INT_MIN) + IFVIRTUAL(AActor, GetGibHealth) { - return -abs(gibhealth); - } - else - { - return -int(SpawnHealth() * gameinfo.gibfactor); + VMValue params[] = { (DObject*)this }; + int h; + VMReturn ret(&h); + GlobalVMStack.Call(func, params, 1, &ret, 1); + return h; } + return -SpawnHealth(); } double AActor::GetCameraHeight() const @@ -8294,9 +8290,9 @@ void PrintMiscActorInfo(AActor *query) query->args[0], query->args[1], query->args[2], query->args[3], query->args[4], query->special1, query->special2); Printf("\nTID: %d", query->tid); - Printf("\nCoord= x: %f, y: %f, z:%f, floor:%f, ceiling:%f.", + Printf("\nCoord= x: %f, y: %f, z:%f, floor:%f, ceiling:%f, height= %f", query->X(), query->Y(), query->Z(), - query->floorz, query->ceilingz); + query->floorz, query->ceilingz, query->Height); Printf("\nSpeed= %f, velocity= x:%f, y:%f, z:%f, combined:%f.\n", query->Speed, query->Vel.X, query->Vel.Y, query->Vel.Z, query->Vel.Length()); Printf("Scale: x:%f, y:%f\n", query->Scale.X, query->Scale.Y); diff --git a/src/scripting/decorate/olddecorations.cpp b/src/scripting/decorate/olddecorations.cpp index 8d220ec70..7370ddb54 100644 --- a/src/scripting/decorate/olddecorations.cpp +++ b/src/scripting/decorate/olddecorations.cpp @@ -223,7 +223,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def, PNamespace *ns) { extra.DeathHeight = ((AActor*)(type->Defaults))->Height; } - type->DeathHeight = extra.DeathHeight; + ((AActor*)(type->Defaults))->FloatVar("DeathHeight") = extra.DeathHeight; } bag.statedef.SetStateLabel("Death", &type->OwnedStates[extra.DeathStart]); } @@ -262,7 +262,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def, PNamespace *ns) } if (extra.BurnHeight == 0) extra.BurnHeight = ((AActor*)(type->Defaults))->Height; - type->BurnHeight = extra.BurnHeight; + ((AActor*)(type->Defaults))->FloatVar("BurnHeight") = extra.BurnHeight; bag.statedef.SetStateLabel("Burn", &type->OwnedStates[extra.FireDeathStart]); } diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index a70fa0c9e..e588b452c 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -592,16 +592,6 @@ DEFINE_PROPERTY(health, I, Actor) defaults->health=id; } -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(gibhealth, I, Actor) -{ - PROP_INT_PARM(id, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->GibHealth = id; -} - //========================================================================== // //========================================================================== @@ -887,16 +877,6 @@ DEFINE_PROPERTY(activesound, S, Actor) defaults->ActiveSound = str; } -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(howlsound, S, Actor) -{ - PROP_STRING_PARM(str, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->HowlSound = str; -} - //========================================================================== // //========================================================================== @@ -1000,26 +980,6 @@ DEFINE_PROPERTY(hitobituary, S, Actor) static_cast(info)->HitObituary = str; } -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(deathheight, F, Actor) -{ - PROP_DOUBLE_PARM(h, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->DeathHeight = MAX(0., h); -} - -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(burnheight, F, Actor) -{ - PROP_DOUBLE_PARM(h, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->BurnHeight = MAX(0., h); -} - //========================================================================== // //========================================================================== diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 4fa2323b0..fcb250563 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -193,16 +193,16 @@ class Actor : Thinker native native double RadiusDamageFactor; // Radius damage factor native double SelfDamageFactor; native double StealthAlpha; + native int WoundHealth; // Health needed to enter wound state + //native color BloodColor; // won't be accessible for now because it needs refactoring to remove the 255-translations limit. native meta String Obituary; // Player was killed by this actor native meta String HitObituary; // Player was killed by this actor in melee - native meta double DeathHeight; // Height on normal death - native meta double BurnHeight; // Height on burning death - native meta color BloodColor; // Colorized blood - native meta int GibHealth; // Negative health below which this monster dies an extreme death - native meta int WoundHealth; // Health needed to enter wound state - native meta Sound HowlSound; // Sound being played when electrocuted or poisoned + meta double DeathHeight; // Height on normal death + meta double BurnHeight; // Height on burning death + meta int GibHealth; // Negative health below which this monster dies an extreme death + meta Sound HowlSound; // Sound being played when electrocuted or poisoned meta Name BloodType; // Blood replacement type meta Name BloodType2; // Bloopsplatter replacement type meta Name BloodType3; // AxeBlood replacement type @@ -225,6 +225,10 @@ class Actor : Thinker native Property ExplosionDamage: ExplosionDamage; Property BloodType: BloodType, BloodType2, BloodType3; Property FastSpeed: FastSpeed; + Property HowlSound: HowlSound; + Property GibHealth: GibHealth; + Property DeathHeight: DeathHeight; + Property BurnHeight: BurnHeight; // need some definition work first //FRenderStyle RenderStyle; @@ -298,8 +302,9 @@ class Actor : Thinker native SelfDamageFactor 1; StealthAlpha 0; WoundHealth 6; - - + GibHealth int.min; + DeathHeight -1; + BurnHeight -1; } // Functions @@ -383,6 +388,41 @@ class Actor : Thinker native } return bloodcls; } + + virtual int GetGibHealth() + { + if (GibHealth != int.min) + { + return -abs(GibHealth); + } + else + { + return -int(GetSpawnHealth() * gameinfo.gibfactor); + } + } + + virtual double GetDeathHeight() + { + // [RH] Allow the death height to be overridden using metadata. + double metaheight = -1; + if (DamageType == 'Fire') + { + metaheight = BurnHeight; + } + if (metaheight < 0) + { + metaheight = DeathHeight; + } + if (metaheight < 0) + { + return Height * 0.25; + } + else + { + return MAX(metaheight, 0); + } + } + native static class GetReplacement(class cls); native static class GetReplacee(class cls); @@ -559,7 +599,6 @@ class Actor : Thinker native native double GetAngle(int flags, int ptr = AAPTR_TARGET); native double GetZAt(double px = 0, double py = 0, double angle = 0, int flags = 0, int pick_pointer = AAPTR_DEFAULT); native int GetSpawnHealth(); - native int GetGibHealth(); native double GetCrouchFactor(int ptr = AAPTR_PLAYER1); native double GetCVar(string cvar); native int GetPlayerInput(int inputnum, int ptr = AAPTR_DEFAULT); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index d8fed2f28..f5eda9022 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -310,6 +310,7 @@ struct GameInfoStruct native native GIFont mStatscreenMapNameFont; native GIFont mStatscreenEnteringFont; native GIFont mStatscreenFinishedFont; + native double gibfactor; } class Object native From fc125f7eafcac65805f3b62f9ae13eca774f0c47 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 14:30:14 +0100 Subject: [PATCH 09/12] - reworked the obituary system to use scripted virtual overrides. Let's hope this solves the problems with the original code, now that any actor needing special treatment can override it. --- src/info.cpp | 2 - src/info.h | 2 - src/p_interaction.cpp | 90 +++++---------------- src/p_mobj.cpp | 2 - src/scripting/thingdef_properties.cpp | 20 ----- wadsrc/static/zscript/actor.txt | 20 ++++- wadsrc/static/zscript/inventory/weapons.txt | 6 ++ wadsrc/static/zscript/shared/player.txt | 30 +++++++ 8 files changed, 73 insertions(+), 99 deletions(-) diff --git a/src/info.cpp b/src/info.cpp index 76ba0fbcb..d51cad115 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -295,8 +295,6 @@ void PClassActor::DeriveData(PClass *newclass) PClassActor *newa = static_cast(newclass); newa->DefaultStateUsage = DefaultStateUsage; - newa->Obituary = Obituary; - newa->HitObituary = HitObituary; newa->BloodColor = BloodColor; newa->distancecheck = distancecheck; diff --git a/src/info.h b/src/info.h index cd21deac4..d5e3eff48 100644 --- a/src/info.h +++ b/src/info.h @@ -290,8 +290,6 @@ public: TArray VisibleToPlayerClass; - FString Obituary; // Player was killed by this actor - FString HitObituary; // Player was killed by this actor in melee PalEntry BloodColor; // Colorized blood FDropItem *DropItems; diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 9d8d63de0..b4cb5d16f 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -62,7 +62,6 @@ #include "g_levellocals.h" #include "events.h" -static FRandom pr_obituary ("Obituary"); static FRandom pr_botrespawn ("BotRespawn"); static FRandom pr_killmobj ("ActorDie"); FRandom pr_damagemobj ("ActorTakeDamage"); @@ -186,14 +185,11 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf const char *message; const char *messagename; char gendermessage[1024]; - int gender; // No obituaries for non-players, voodoo dolls or when not wanted if (self->player == NULL || self->player->mo != self || !show_obituaries) return; - gender = self->player->userinfo.GetGender(); - // Treat voodoo dolls as unknown deaths if (inflictor && inflictor->player && inflictor->player->mo != inflictor) MeansOfDeath = NAME_None; @@ -217,93 +213,47 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf } FString obit = DamageTypeDefinition::GetObituary(mod); - if (obit.IsNotEmpty()) messagename = obit; + if (attacker == nullptr) messagename = obit; else { switch (mod) { - case NAME_Suicide: messagename = "OB_SUICIDE"; break; - case NAME_Falling: messagename = "OB_FALLING"; break; - case NAME_Crush: messagename = "OB_CRUSH"; break; - case NAME_Exit: messagename = "OB_EXIT"; break; - case NAME_Drowning: messagename = "OB_WATER"; break; - case NAME_Slime: messagename = "OB_SLIME"; break; - case NAME_Fire: if (attacker == NULL) messagename = "OB_LAVA"; break; + case NAME_Suicide: message = "$OB_SUICIDE"; break; + case NAME_Falling: message = "$OB_FALLING"; break; + case NAME_Crush: message = "$OB_CRUSH"; break; + case NAME_Exit: message = "$OB_EXIT"; break; + case NAME_Drowning: message = "$OB_WATER"; break; + case NAME_Slime: message = "$OB_SLIME"; break; + case NAME_Fire: messagename = "$OB_LAVA"; break; } } // Check for being killed by a voodoo doll. if (inflictor && inflictor->player && inflictor->player->mo != inflictor) { - messagename = "OB_VOODOO"; + messagename = "$OB_VOODOO"; } - if (messagename != NULL) - message = GStrings(messagename); - if (attacker != NULL && message == NULL) { if (attacker == self) { - message = GStrings("OB_KILLEDSELF"); + message = "$OB_KILLEDSELF"; } - else if (attacker->player == NULL) + else { - if (mod == NAME_Telefrag) + IFVIRTUALPTR(attacker, AActor, GetObituary) { - message = GStrings("OB_MONTELEFRAG"); - } - else if (mod == NAME_Melee && attacker->GetClass()->HitObituary.IsNotEmpty()) - { - message = attacker->GetClass()->HitObituary; - } - else if (attacker->GetClass()->Obituary.IsNotEmpty()) - { - message = attacker->GetClass()->Obituary; + VMValue params[] = { attacker, self, inflictor, mod.GetIndex(), !!(dmgflags & DMG_PLAYERATTACK) }; + FString ret; + VMReturn rett(&ret); + GlobalVMStack.Call(func, params, countof(params), &rett, 1); + if (ret.IsNotEmpty()) message = ret; } } } - - if (message == NULL && attacker != NULL && attacker->player != NULL) - { - if (self->player != attacker->player && self->IsTeammate(attacker)) - { - self = attacker; - gender = self->player->userinfo.GetGender(); - mysnprintf (gendermessage, countof(gendermessage), "OB_FRIENDLY%c", '1' + (pr_obituary() & 3)); - message = GStrings(gendermessage); - } - else - { - if (mod == NAME_Telefrag) message = GStrings("OB_MPTELEFRAG"); - if (message == NULL) - { - if (inflictor != NULL && inflictor->GetClass()->Obituary.IsNotEmpty()) - { - message = inflictor->GetClass()->Obituary; - } - if (message == NULL && (dmgflags & DMG_PLAYERATTACK) && attacker->player->ReadyWeapon != NULL) - { - message = attacker->player->ReadyWeapon->GetClass()->Obituary; - } - if (message == NULL) - { - switch (mod) - { - case NAME_BFGSplash: messagename = "OB_MPBFG_SPLASH"; break; - case NAME_Railgun: messagename = "OB_RAILGUN"; break; - } - if (messagename != NULL) - message = GStrings(messagename); - } - if (message == NULL) - { - message = attacker->GetClass()->Obituary; - } - } - } - } - else attacker = self; // for the message creation + if (message == nullptr) message = messagename; // fallback to defaults if possible. + if (attacker->player == nullptr) attacker = self; // for the message creation if (message != NULL && message[0] == '$') { @@ -319,7 +269,7 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker, int dmgf if (message == NULL || strlen(message) <= 0) return; - SexMessage (message, gendermessage, gender, + SexMessage (message, gendermessage, self->player->userinfo.GetGender(), self->player->userinfo.GetName(), attacker->player->userinfo.GetName()); Printf (PRINT_MEDIUM, "%s\n", gendermessage); } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index bc432434c..4446393d7 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -317,8 +317,6 @@ DEFINE_FIELD(AActor, SelfDamageFactor) DEFINE_FIELD(AActor, StealthAlpha) DEFINE_FIELD(AActor, WoundHealth) -DEFINE_FIELD(PClassActor, Obituary) -DEFINE_FIELD(PClassActor, HitObituary) //DEFINE_FIELD(PClassActor, BloodColor) //========================================================================== diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index e588b452c..e41523b8c 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -960,26 +960,6 @@ DEFINE_PROPERTY(alpha, F, Actor) defaults->Alpha = id; } -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(obituary, S, Actor) -{ - PROP_STRING_PARM(str, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->Obituary = str; -} - -//========================================================================== -// -//========================================================================== -DEFINE_PROPERTY(hitobituary, S, Actor) -{ - PROP_STRING_PARM(str, 0); - assert(info->IsKindOf(RUNTIME_CLASS(PClassActor))); - static_cast(info)->HitObituary = str; -} - //========================================================================== // //========================================================================== diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index fcb250563..97e2bf6bb 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -196,9 +196,8 @@ class Actor : Thinker native native int WoundHealth; // Health needed to enter wound state //native color BloodColor; // won't be accessible for now because it needs refactoring to remove the 255-translations limit. - native meta String Obituary; // Player was killed by this actor - native meta String HitObituary; // Player was killed by this actor in melee - + meta String Obituary; // Player was killed by this actor + meta String HitObituary; // Player was killed by this actor in melee meta double DeathHeight; // Height on normal death meta double BurnHeight; // Height on burning death meta int GibHealth; // Negative health below which this monster dies an extreme death @@ -216,6 +215,8 @@ class Actor : Thinker native meta double FastSpeed; // speed in fast mode Property prefix: none; + Property Obituary: Obituary; + Property HitObituary: HitObituary; Property MeleeDamage: MeleeDamage; Property MeleeSound: MeleeSound; Property MissileHeight: MissileHeight; @@ -423,6 +424,19 @@ class Actor : Thinker native } } + virtual String GetObituary(Actor victim, Actor inflictor, Name mod, bool playerattack) + { + if (mod == 'Telefrag') + { + return "$OB_MONTELEFRAG"; + } + else if (mod == 'Melee' && HitObituary.Length() > 0) + { + return HitObituary; + } + return Obituary; + } + native static class GetReplacement(class cls); native static class GetReplacee(class cls); diff --git a/wadsrc/static/zscript/inventory/weapons.txt b/wadsrc/static/zscript/inventory/weapons.txt index de9464726..860d387e2 100644 --- a/wadsrc/static/zscript/inventory/weapons.txt +++ b/wadsrc/static/zscript/inventory/weapons.txt @@ -89,6 +89,12 @@ class Weapon : StateProvider native return s; } + override String GetObituary(Actor victim, Actor inflictor, Name mod, bool playerattack) + { + // Weapons may never return HitObituary by default. Override this if it is needed. + return Obituary; + } + action void A_GunFlash(statelabel flashlabel = null, int flags = 0) { let player = player; diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 9b686a551..14347a41c 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -119,6 +119,36 @@ class PlayerPawn : Actor native } } + override String GetObituary(Actor victim, Actor inflictor, Name mod, bool playerattack) + { + if (victim.player != player && victim.IsTeammate(self)) + { + victim = self; + return String.Format("$OB_FRIENDLY%c", random[Obituary](49, 53)); + } + else + { + if (mod == 'Telefrag') return "$OB_MPTELEFRAG"; + + String message; + if (inflictor != NULL) + { + message = inflictor.GetObituary(victim, inflictor, mod, playerattack); + } + if (message.Length() == 0 && playerattack && player.ReadyWeapon != NULL) + { + message = player.ReadyWeapon.GetObituary(victim, inflictor, mod, playerattack); + } + if (message.Length() == 0) + { + if (mod == 'BFGSplash') return "$OB_MPBFG_SPLASH"; + if (mod == 'Railgun') return "$OB_RAILGUN"; + message = Obituary; + } + return message; + } + } + // This is for SBARINFO. int, int GetEffectTicsForItem(class item) { From bc0ffc4185d4c5c42e10b488b925cf2aec2be230 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 14:33:46 +0100 Subject: [PATCH 10/12] - removed access to the PlayerPawn's DisplayName variable. This one has implicit semantics, so wherever a displayable name is needed GetPrintableDisplayName should be called instead to allow later refactoring of the internal handling. --- src/p_user.cpp | 2 -- wadsrc/static/zscript/shared/player.txt | 1 - 2 files changed, 3 deletions(-) diff --git a/src/p_user.cpp b/src/p_user.cpp index 30db0a271..0f8954e56 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -3333,8 +3333,6 @@ DEFINE_FIELD(APlayerPawn, HexenArmor) DEFINE_FIELD(APlayerPawn, ColorRangeStart) DEFINE_FIELD(APlayerPawn, ColorRangeEnd) -DEFINE_FIELD(PClassActor, DisplayName) - DEFINE_FIELD_X(PlayerInfo, player_t, mo) DEFINE_FIELD_X(PlayerInfo, player_t, playerstate) DEFINE_FIELD_X(PlayerInfo, player_t, original_oldbuttons) diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 14347a41c..2e7bda8f6 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -34,7 +34,6 @@ class PlayerPawn : Actor native native double ViewBob; // [SP] ViewBob Multiplier native double FullHeight; - native meta String DisplayName; // Display name (used in menus, etc.) meta Name HealingRadiusType; meta Name InvulMode; From 168627f549a353794d74aa83452b9139c5366f71 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 14:38:50 +0100 Subject: [PATCH 11/12] - native meta variables are not needed anymore. They were only a temporary aid to properly handle this, but now all have been redone. --- src/scripting/backend/codegen.cpp | 2 +- src/scripting/decorate/thingdef_parse.cpp | 9 +----- src/scripting/zscript/zcc_compile.cpp | 39 +++++++++++------------ 3 files changed, 21 insertions(+), 29 deletions(-) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 893a50eed..8e41f44ab 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -6871,7 +6871,7 @@ ExpEmit FxStructMember::Emit(VMFunctionBuilder *build) { obj.Free(build); ExpEmit meta(build, REGT_POINTER); - build->Emit(membervar->Flags & VARF_Native? OP_CLSS : OP_META, meta.RegNum, obj.RegNum); + build->Emit(OP_META, meta.RegNum, obj.RegNum); obj = meta; } diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index e70059fec..72cac7cde 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -827,14 +827,7 @@ static void DispatchScriptProperty(FScanner &sc, PProperty *prop, AActor *defaul if (i > 0) sc.MustGetStringName(","); if (f->Flags & VARF_Meta) { - if (f->Flags & VARF_Native) - { - addr = ((char*)bag.Info) + f->Offset; - } - else - { - addr = ((char*)bag.Info->Meta) + f->Offset; - } + addr = ((char*)bag.Info->Meta) + f->Offset; } else { diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 548424cd9..5574fcc18 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1095,22 +1095,28 @@ bool ZCCCompiler::CompileFields(PStruct *type, TArray &Fiel if (varflags & VARF_Native) { - auto querytype = (varflags & VARF_Meta) ? type->GetClass() : type; - fd = FindField(querytype, FName(name->Name).GetChars()); - if (fd == nullptr) + if (varflags & VARF_Meta) { - Error(field, "The member variable '%s.%s' has not been exported from the executable.", type->TypeName.GetChars(), FName(name->Name).GetChars()); + Error(field, "Native meta variable %s not allowed", FName(name->Name).GetChars()); } - else if (thisfieldtype->Size != fd->FieldSize && fd->BitValue == 0) - { - Error(field, "The member variable '%s.%s' has mismatching sizes in internal and external declaration. (Internal = %d, External = %d)", type->TypeName.GetChars(), FName(name->Name).GetChars(), fd->FieldSize, thisfieldtype->Size); - } - // Q: Should we check alignment, too? A mismatch may be an indicator for bad assumptions. else { - // for bit fields the type must point to the source variable. - if (fd->BitValue != 0) thisfieldtype = fd->FieldSize == 1 ? TypeUInt8 : fd->FieldSize == 2 ? TypeUInt16 : TypeUInt32; - type->AddNativeField(name->Name, thisfieldtype, fd->FieldOffset, varflags, fd->BitValue); + fd = FindField(type, FName(name->Name).GetChars()); + if (fd == nullptr) + { + Error(field, "The member variable '%s.%s' has not been exported from the executable.", type->TypeName.GetChars(), FName(name->Name).GetChars()); + } + else if (thisfieldtype->Size != fd->FieldSize && fd->BitValue == 0) + { + Error(field, "The member variable '%s.%s' has mismatching sizes in internal and external declaration. (Internal = %d, External = %d)", type->TypeName.GetChars(), FName(name->Name).GetChars(), fd->FieldSize, thisfieldtype->Size); + } + // Q: Should we check alignment, too? A mismatch may be an indicator for bad assumptions. + else + { + // for bit fields the type must point to the source variable. + if (fd->BitValue != 0) thisfieldtype = fd->FieldSize == 1 ? TypeUInt8 : fd->FieldSize == 2 ? TypeUInt16 : TypeUInt32; + type->AddNativeField(name->Name, thisfieldtype, fd->FieldOffset, varflags, fd->BitValue); + } } } else if (hasnativechildren) @@ -1694,14 +1700,7 @@ void ZCCCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt *prop if (f->Flags & VARF_Meta) { - if (f->Flags & VARF_Native) - { - addr = ((char*)bag.Info) + f->Offset; - } - else - { - addr = ((char*)bag.Info->Meta) + f->Offset; - } + addr = ((char*)bag.Info->Meta) + f->Offset; } else { From 5f6da0d2223569ea9f5c346f791ac7e913236d0b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 14:44:18 +0100 Subject: [PATCH 12/12] fixed double allocation of metadata. --- src/dobjtype.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index f86797dfd..cd128b656 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -3361,7 +3361,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)) + if (field != nullptr && !(flags & VARF_Native) && Meta != nullptr) { Meta = (BYTE *)M_Realloc(Meta, MetaSize); memset(Meta + oldsize, 0, MetaSize - oldsize);