From f343d36ea941829b68c239eb91d0f68c4e7a3b38 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 27 Feb 2017 23:28:19 +0100 Subject: [PATCH 01/16] - 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 75193b868b..dcb93599dc 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 0151e6c119..c88b00930b 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 cdc100d888..f0b423150c 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 8b0bf35e97..1c8e0b39bb 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 cc93c22156..bd18103fca 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 e444d30a9f..bd4d781a10 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 3082abf802..c37e29cbf1 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 b058dc94b6..3d503932aa 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 b28226efbb..6f902648e2 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/16] - 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 41b5e2824d..7510a4cff3 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 dcb93599dc..1d5cd15122 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 c88b00930b..76e17b1331 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 53e7d84ed7..df6679d41a 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 817fcf1769..9258d320a5 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 7cac3569d9..2bba8afb4b 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 6d6329f88f..f0f0f6c3c6 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 28de568183..df2841daa1 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 50e8f9c6a8..5c5714ba3b 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 bd4d781a10..e70059fecb 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 cf70b19aee..527782382c 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 6f902648e2..1a9dfbe8d1 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 e742e806d9..092a93846b 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 230b3575be..e2fb8eacfd 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 441566786c..ce4bf805b4 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 06caedad73..cac9b9b8f2 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 c76aaef54c..de94647265 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/16] - 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 2d7d439c57..43e6e53ab2 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 5bb0e2127e..30db0a2711 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 527782382c..09f6dcd954 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 1a9dfbe8d1..548424cd97 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 8886e6744c..9b686a5513 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/16] - 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 747c1f9bfa..b8097f5498 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 2bba8afb4b..0db6c7fbc5 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 f0f0f6c3c6..9e684f462b 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 df2841daa1..196c41fd05 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 54a577e5b9..1f6e6df7f8 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 88bb1d40a9..40fa7e0c95 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 5c5714ba3b..8d220ec707 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 09f6dcd954..0e34e2da48 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 501a7b2ea8..439b495b4c 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 99c23c7bfe..6a12e00f8f 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/16] - 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 2ed0047405..6e64b6033e 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 1d5cd15122..f86797dfd2 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 0db6c7fbc5..6f9b95f36d 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 9e684f462b..fd89145465 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 40fa7e0c95..d95bae5b2f 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 bd18103fca..893a50eed9 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 0e34e2da48..3838c3a89a 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 6a12e00f8f..9796c3e8df 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/16] - 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 6e64b6033e..e7d84f09d5 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 6f9b95f36d..b8abba9760 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 fd89145465..f2a6101e9b 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 196c41fd05..7c63eb7859 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 4c23c8123c..2af2a3da13 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 70b18df7fa..7e110dcbf4 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 d95bae5b2f..9ccdde24e3 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 3838c3a89a..a6657ce972 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 9796c3e8df..2fc0d6d3bd 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/16] - 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 e7d84f09d5..739f08f4ab 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 b8abba9760..d81d4d8743 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 f2a6101e9b..28a684281b 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 2af2a3da13..da60af8ad9 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 9ccdde24e3..22cbe1e3fa 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 a6657ce972..a70fa0c9e1 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 2fc0d6d3bd..4fa2323b00 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/16] - 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 7510a4cff3..d99fbee2b8 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 76e17b1331..f589b4e489 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 672ca3263a..ad5c5a0eea 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 d81d4d8743..76ba0fbcbe 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 28a684281b..cd21deac44 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 7c63eb7859..50bde739f2 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 baf15c1105..6053ce85ab 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 1f6e6df7f8..b75949f01b 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 da60af8ad9..9d8d63de0a 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 22cbe1e3fa..bc432434c3 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 8d220ec707..7370ddb54f 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 a70fa0c9e1..e588b452ca 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 4fa2323b00..fcb250563a 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 d8fed2f28a..f5eda90227 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/16] - 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 76ba0fbcbe..d51cad1155 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 cd21deac44..d5e3eff481 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 9d8d63de0a..b4cb5d16f5 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 bc432434c3..4446393d71 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 e588b452ca..e41523b8cf 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 fcb250563a..97e2bf6bb8 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 de94647265..860d387e27 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 9b686a5513..14347a41c9 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/16] - 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 30db0a2711..0f8954e56e 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 14347a41c9..2e7bda8f65 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/16] - 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 893a50eed9..8e41f44ab4 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 e70059fecb..72cac7cde7 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 548424cd97..5574fcc187 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/16] 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 f86797dfd2..cd128b6560 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); From bb1709228cb0e9b66150094d9d836e50468772b4 Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Tue, 28 Feb 2017 18:23:40 +0800 Subject: [PATCH 13/16] Changed FOV from a CCMD to a CVar, allowing players' FOV settings to persist. Also exported SetFOV to PlayerInfo for ZScript. --- src/c_cmds.cpp | 28 ----------------- src/d_player.h | 3 ++ src/p_mobj.cpp | 3 +- src/p_user.cpp | 41 +++++++++++++++++++++++++ wadsrc/static/zscript/shared/player.txt | 1 + 5 files changed, 47 insertions(+), 29 deletions(-) diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index 7e0a66c4b1..4bdca624a2 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -732,34 +732,6 @@ CCMD (dir) chdir (curdir); } -CCMD (fov) -{ - player_t *player = who ? who->player : &players[consoleplayer]; - - if (argv.argc() != 2) - { - Printf ("fov is %g\n", player->DesiredFOV); - return; - } - else if (dmflags & DF_NO_FOV) - { - if (consoleplayer == Net_Arbitrator) - { - Net_WriteByte (DEM_FOV); - } - else - { - Printf ("A setting controller has disabled FOV changes.\n"); - return; - } - } - else - { - Net_WriteByte (DEM_MYFOV); - } - Net_WriteByte (clamp (atoi (argv[1]), 5, 179)); -} - //========================================================================== // // CCMD warp diff --git a/src/d_player.h b/src/d_player.h index 2d7d439c57..35daa57a2c 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -529,6 +529,9 @@ public: DPSprite *GetPSprite(PSPLayers layer); bool GetPainFlash(FName type, PalEntry *color) const; + + // [Nash] set player FOV + void SetFOV(float fov); }; // Bookkeeping on players - state. diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index f38ac12bb3..d5c1332652 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5305,6 +5305,7 @@ DEFINE_ACTION_FUNCTION(AActor, AdjustFloorClip) // EXTERN_CVAR (Bool, chasedemo) EXTERN_CVAR(Bool, sv_singleplayerrespawn) +EXTERN_CVAR(Float, fov) extern bool demonew; @@ -5442,7 +5443,7 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags) mobj->sprite = Skins[p->userinfo.GetSkin()].sprite; } - p->DesiredFOV = p->FOV = 90.f; + p->DesiredFOV = p->FOV = fov; p->camera = p->mo; p->playerstate = PST_LIVE; p->refire = 0; diff --git a/src/p_user.cpp b/src/p_user.cpp index 5bb0e2127e..62d44c74ed 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -88,6 +88,13 @@ CUSTOM_CVAR(Float, cl_predict_lerpthreshold, 2.00f, CVAR_ARCHIVE | CVAR_GLOBALCO ColorSetList ColorSets; PainFlashList PainFlashes; +// [Nash] FOV cvar setting +CUSTOM_CVAR(Float, fov, 90.f, CVAR_ARCHIVE | CVAR_USERINFO | CVAR_NOINITCALL) +{ + player_t *p = &players[consoleplayer]; + p->SetFOV(fov); +} + struct PredictPos { int gametic; @@ -550,6 +557,40 @@ int player_t::GetSpawnClass() return static_cast(GetDefaultByType(type))->SpawnMask; } +// [Nash] Set FOV +void player_t::SetFOV(float fov) +{ + player_t *p = &players[consoleplayer]; + if (p != nullptr && p->mo != nullptr) + { + if (dmflags & DF_NO_FOV) + { + if (consoleplayer == Net_Arbitrator) + { + Net_WriteByte(DEM_MYFOV); + } + else + { + Printf("A setting controller has disabled FOV changes.\n"); + return; + } + } + else + { + Net_WriteByte(DEM_MYFOV); + } + Net_WriteByte((BYTE)clamp(fov, 5.f, 179.f)); + } +} + +DEFINE_ACTION_FUNCTION(_PlayerInfo, SetFOV) +{ + PARAM_SELF_STRUCT_PROLOGUE(player_t); + PARAM_FLOAT(fov); + self->SetFOV((float)fov); + return 0; +} + //=========================================================================== // // EnumColorsets diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 8886e6744c..d2bd2d0120 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -320,6 +320,7 @@ usercmd_t original_cmd; native int GetGender(); native int GetTeam(); native float GetAutoaim(); + native void SetFOV(float fov); } struct PlayerClass native From dc6c91042bb1c34330774a4677fcb33cd785b124 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 18:47:18 +0100 Subject: [PATCH 14/16] - fixed misordered ACS functions. --- src/p_acs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 6053ce85ab..5ea7dfa075 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4369,8 +4369,8 @@ enum EACSFunctions ACSF_GetActorFloorTerrain, ACSF_StrArg, ACSF_Floor, - ACSF_Ceil, ACSF_Round, + ACSF_Ceil, // OpenGL stuff From 12915b5f6e27e36e2eb69356114f287347df2134 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 28 Feb 2017 21:45:47 +0100 Subject: [PATCH 15/16] - use an inventory flag to decide what items are slipped by DF_NO_HEALTH and DF_NO_ARMOR. With all the changes over the last 10 years this had become too spotty. - use an enum type for ItemFlags, just like it was done for actor flags. Since the flag word is almost full it may soon be necessary to add a second one and then this kind of security check may become necessary. --- src/g_inventory/a_pickups.h | 10 ++++-- src/p_enemy.cpp | 4 +-- src/p_mobj.cpp | 36 +++++++++----------- src/scripting/thingdef_data.cpp | 2 ++ wadsrc/static/zscript/doom/doomartifacts.txt | 3 ++ wadsrc/static/zscript/inventory/armor.txt | 1 + wadsrc/static/zscript/inventory/health.txt | 2 ++ 7 files changed, 34 insertions(+), 24 deletions(-) diff --git a/src/g_inventory/a_pickups.h b/src/g_inventory/a_pickups.h index 9258d320a5..9b2fc1cc1a 100644 --- a/src/g_inventory/a_pickups.h +++ b/src/g_inventory/a_pickups.h @@ -17,7 +17,7 @@ struct visstyle_t; // A pickup is anything the player can pickup (i.e. weapons, ammo, powerups, etc) -enum +enum ItemFlag { IF_ACTIVATABLE = 1<<0, // can be activated IF_ACTIVATED = 1<<1, // is currently activated @@ -46,8 +46,14 @@ enum IF_TRANSFER = 1<<24, // All inventory items that the inventory item contains is also transfered to the pickuper IF_NOTELEPORTFREEZE = 1<<25, // does not 'freeze' the player right after teleporting. IF_NOSCREENBLINK = 1<<26, // Does not blink the screen overlay when expiring. + IF_ISHEALTH = 1<<27, // for the DM flag so that it can recognize items that are not obviously health givers. + IF_ISARMOR = 1<<28, // for the DM flag so that it can recognize items that are not obviously armor givers. }; +typedef TFlags InvFlags; +//typedef TFlags ItemFlags2; +DEFINE_TFLAGS_OPERATORS(InvFlags) +//DEFINE_TFLAGS_OPERATORS(ItemFlags2) class AInventory : public AActor { @@ -89,7 +95,7 @@ public: PClassActor *SpawnPointClass; // For respawning like Heretic's mace FTextureID AltHUDIcon; - DWORD ItemFlags; + InvFlags ItemFlags; PClassActor *PickupFlash; // actor to spawn as pickup flash FSoundIDNoInit PickupSound; diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 5841e6b994..dde4fce29c 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -3217,13 +3217,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_ActiveSound) //--------------------------------------------------------------------------- void ModifyDropAmount(AInventory *inv, int dropamount) { - int flagmask = IF_IGNORESKILL; + auto flagmask = IF_IGNORESKILL; double dropammofactor = G_SkillProperty(SKILLP_DropAmmoFactor); // Default drop amount is half of regular amount * regular ammo multiplication if (dropammofactor == -1) { dropammofactor = 0.5; - flagmask = 0; + flagmask = ItemFlag(0); } if (dropamount > 0) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index fc40982f51..104a424711 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5821,27 +5821,23 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position) // [RH] Other things that shouldn't be spawned depending on dmflags if (deathmatch || alwaysapplydmflags) { - // Fixme: This needs to be done differently, it's quite broken. - if (dmflags & DF_NO_HEALTH) + if (i->IsDescendantOf(RUNTIME_CLASS(AInventory))) { - if (i->IsDescendantOf (PClass::FindActor(NAME_Health))) - return NULL; - if (i->TypeName == NAME_Berserk) - return NULL; - if (i->TypeName == NAME_Megasphere) - return NULL; - } - if (dmflags & DF_NO_ITEMS) - { -// if (i->IsDescendantOf (RUNTIME_CLASS(AArtifact))) -// return; - } - if (dmflags & DF_NO_ARMOR) - { - if (i->IsDescendantOf (PClass::FindActor(NAME_Armor))) - return NULL; - if (i->TypeName == NAME_Megasphere) - return NULL; + auto it = static_cast(GetDefaultByType(i)); + + if (dmflags & DF_NO_HEALTH) + { + if (it->ItemFlags & IF_ISHEALTH) return nullptr; + } + if (dmflags & DF_NO_ITEMS) + { + // if (i->IsDescendantOf (RUNTIME_CLASS(AArtifact))) + // return; + } + if (dmflags & DF_NO_ARMOR) + { + if (it->ItemFlags & IF_ISARMOR) return nullptr; + } } } diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 265dc079b4..4b65e6413e 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -430,6 +430,8 @@ static FFlagDef InventoryFlagDefs[] = DEFINE_FLAG(IF, TRANSFER, AInventory, ItemFlags), DEFINE_FLAG(IF, NOTELEPORTFREEZE, AInventory, ItemFlags), DEFINE_FLAG(IF, NOSCREENBLINK, AInventory, ItemFlags), + DEFINE_FLAG(IF, ISARMOR, AInventory, ItemFlags), + DEFINE_FLAG(IF, ISHEALTH, AInventory, ItemFlags), DEFINE_DUMMY_FLAG(FORCERESPAWNINSURVIVAL, false), diff --git a/wadsrc/static/zscript/doom/doomartifacts.txt b/wadsrc/static/zscript/doom/doomartifacts.txt index ad5e304c66..a6996cb886 100644 --- a/wadsrc/static/zscript/doom/doomartifacts.txt +++ b/wadsrc/static/zscript/doom/doomartifacts.txt @@ -72,6 +72,8 @@ class Megasphere : CustomInventory { +COUNTITEM +INVENTORY.ALWAYSPICKUP + +INVENTORY.ISHEALTH + +INVENTORY.ISARMOR Inventory.PickupMessage "$GOTMSPHERE"; Inventory.PickupSound "misc/p_pkup"; } @@ -183,6 +185,7 @@ class Berserk : CustomInventory { +COUNTITEM +INVENTORY.ALWAYSPICKUP + +INVENTORY.ISHEALTH Inventory.PickupMessage "$GOTBERSERK"; Inventory.PickupSound "misc/p_pkup"; } diff --git a/wadsrc/static/zscript/inventory/armor.txt b/wadsrc/static/zscript/inventory/armor.txt index ae9ab562e2..600c4e5265 100644 --- a/wadsrc/static/zscript/inventory/armor.txt +++ b/wadsrc/static/zscript/inventory/armor.txt @@ -38,6 +38,7 @@ class Armor : Inventory Default { Inventory.PickupSound "misc/armor_pkup"; + +INVENTORY.ISARMOR } } diff --git a/wadsrc/static/zscript/inventory/health.txt b/wadsrc/static/zscript/inventory/health.txt index e2fb8eacfd..e64bbfd4a9 100644 --- a/wadsrc/static/zscript/inventory/health.txt +++ b/wadsrc/static/zscript/inventory/health.txt @@ -43,6 +43,7 @@ class Health : Inventory Default { + +INVENTORY.ISHEALTH Inventory.Amount 1; Inventory.MaxAmount 0; Inventory.PickupSound "misc/health_pkup"; @@ -99,6 +100,7 @@ class HealthPickup : Inventory { Inventory.DefMaxAmount; +INVENTORY.INVBAR + +INVENTORY.ISHEALTH } //=========================================================================== From cb295e0441cccae57b011fd764b3e0d5c49774db Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 Mar 2017 00:04:17 +0100 Subject: [PATCH 16/16] - added parameter to PLayerPawn::GetMaxHealth to return the real maximum health, including stamina upgrades. --- src/b_think.cpp | 2 +- src/d_player.h | 2 +- src/g_statusbar/sbarinfo_commands.cpp | 4 ++-- src/p_mobj.cpp | 2 +- src/p_user.cpp | 11 +++++++---- wadsrc/static/zscript/shared/player.txt | 2 +- wadsrc/static/zscript/shared/player_cheat.txt | 2 +- 7 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/b_think.cpp b/src/b_think.cpp index da3fb61246..f286dd30f5 100644 --- a/src/b_think.cpp +++ b/src/b_think.cpp @@ -358,7 +358,7 @@ void DBot::WhatToGet (AActor *item) } else if ((typeis (Megasphere) || typeis (Soulsphere) || typeis (HealthBonus)) && player->mo->health >= deh.MaxSoulsphere) return; - else if (item->IsKindOf (PClass::FindActor(NAME_Health)) && player->mo->health >= player->mo->GetMaxHealth() + player->mo->stamina) + else if (item->IsKindOf (PClass::FindActor(NAME_Health)) && player->mo->health >= player->mo->GetMaxHealth(true)) return; if ((dest == NULL || diff --git a/src/d_player.h b/src/d_player.h index 39698d6d8a..2787df231d 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -93,7 +93,7 @@ public: virtual bool UpdateWaterLevel (bool splash) override; bool ResetAirSupply (bool playgasp = true); - int GetMaxHealth() const; + int GetMaxHealth(bool withupgrades = false) const; void TweakSpeeds (double &forwardmove, double &sidemove); void MorphPlayerThink (); void ActivateMorphWeapon (); diff --git a/src/g_statusbar/sbarinfo_commands.cpp b/src/g_statusbar/sbarinfo_commands.cpp index ae6ba5b000..ad2da961d4 100644 --- a/src/g_statusbar/sbarinfo_commands.cpp +++ b/src/g_statusbar/sbarinfo_commands.cpp @@ -2744,7 +2744,7 @@ class CommandDrawBar : public SBarInfoCommand max = 0; } else //default to the class's health - max = statusBar->CPlayer->mo->GetMaxHealth() + statusBar->CPlayer->mo->stamina; + max = statusBar->CPlayer->mo->GetMaxHealth(true); break; case ARMOR: value = statusBar->armor != NULL ? statusBar->armor->Amount : 0; @@ -3251,7 +3251,7 @@ class CommandDrawGem : public SBarInfoCommand void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) { goalValue = armor ? (statusBar->armor ? statusBar->armor->Amount : 0) : statusBar->CPlayer->mo->health; - int max = armor ? 100 : statusBar->CPlayer->mo->GetMaxHealth() + statusBar->CPlayer->mo->stamina; + int max = armor ? 100 : statusBar->CPlayer->mo->GetMaxHealth(true); if(max != 0 && goalValue > 0) { goalValue = (goalValue*100)/max; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 104a424711..b4affd5394 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1330,7 +1330,7 @@ bool P_GiveBody(AActor *actor, int num, int max) // calls while supporting health pickups. if (max <= 0) { - max = static_cast(actor)->GetMaxHealth() + player->mo->stamina; + max = static_cast(actor)->GetMaxHealth(true); // [MH] First step in predictable generic morph effects if (player->morphTics) { diff --git a/src/p_user.cpp b/src/p_user.cpp index 7509e9bca4..ab4390ba2c 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1350,15 +1350,18 @@ const char *APlayerPawn::GetSoundClass() const // //=========================================================================== -int APlayerPawn::GetMaxHealth() const +int APlayerPawn::GetMaxHealth(bool withupgrades) const { - return MaxHealth > 0? MaxHealth : ((i_compatflags&COMPATF_DEHHEALTH)? 100 : deh.MaxHealth); + int ret = MaxHealth > 0? MaxHealth : ((i_compatflags&COMPATF_DEHHEALTH)? 100 : deh.MaxHealth); + if (withupgrades) ret += stamina; + return ret; } DEFINE_ACTION_FUNCTION(APlayerPawn, GetMaxHealth) { PARAM_SELF_PROLOGUE(APlayerPawn); - ACTION_RETURN_INT(self->GetMaxHealth()); + PARAM_BOOL_DEF(withupgrades); + ACTION_RETURN_INT(self->GetMaxHealth(withupgrades)); } //=========================================================================== @@ -2869,7 +2872,7 @@ void P_PlayerThink (player_t *player) // Apply degeneration. if (dmflags2 & DF2_YES_DEGENERATION) { - int maxhealth = player->mo->GetMaxHealth() + player->mo->stamina; + int maxhealth = player->mo->GetMaxHealth(true); if ((level.time % TICRATE) == 0 && player->health > maxhealth) { if (player->health - 5 < maxhealth) diff --git a/wadsrc/static/zscript/shared/player.txt b/wadsrc/static/zscript/shared/player.txt index 0b60e3d51a..97e065c2ab 100644 --- a/wadsrc/static/zscript/shared/player.txt +++ b/wadsrc/static/zscript/shared/player.txt @@ -166,7 +166,7 @@ class PlayerPawn : Actor native return -1, -1; } - native int GetMaxHealth(); + native int GetMaxHealth(bool withupgrades = false); native bool ResetAirSupply (bool playgasp = false); native void CheckWeaponSwitch(class item); native static String GetPrintableDisplayName(Class cls); diff --git a/wadsrc/static/zscript/shared/player_cheat.txt b/wadsrc/static/zscript/shared/player_cheat.txt index 2aaa01ba87..15bad043cf 100644 --- a/wadsrc/static/zscript/shared/player_cheat.txt +++ b/wadsrc/static/zscript/shared/player_cheat.txt @@ -76,7 +76,7 @@ extend class PlayerPawn } else { - player.health = health = GetMaxHealth(); + player.health = health = GetMaxHealth(true); } }