From 65299312813c91dbcd856ce113e55f6c97c3d05f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 11 Nov 2016 14:40:32 +0100 Subject: [PATCH] fixed and completed the special field init code. Strings can now be used as class members, and so can structs which contain strings. - made 'DamageMultiply' an actor property and moved the initialization of ConversationRoot to the property handler for the compiler to get this stuff out of the type classes. - consolidate default initialization into one function which performs all the required setup. The original implementation did this when adding the fields but that cannot work because at that time no defaults have been created yet. - fixed: When deriving a class the child class's defaults also must initialize the copied parent fields with special initialization. This part was completely missing. - removed DECORATE code for parsing native classes because it's no longer needed. --- src/dobjtype.cpp | 66 +++++++++++++++++------ src/dobjtype.h | 9 +++- src/info.cpp | 29 ---------- src/info.h | 1 - src/scripting/decorate/thingdef_parse.cpp | 38 ++----------- src/scripting/thingdef.h | 2 - src/scripting/thingdef_properties.cpp | 9 ++++ src/scripting/zscript/zcc_compile.cpp | 10 +++- wadsrc/static/zscript/actor.txt | 3 +- 9 files changed, 81 insertions(+), 86 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 71bfd542b..0e17299cd 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2778,14 +2778,14 @@ void PClass::StaticBootstrap() PClass::PClass() { Size = sizeof(DObject); - ParentClass = NULL; - Pointers = NULL; - FlatPointers = NULL; - HashNext = NULL; - Defaults = NULL; + ParentClass = nullptr; + Pointers = nullptr; + FlatPointers = nullptr; + HashNext = nullptr; + Defaults = nullptr; bRuntimeClass = false; bExported = false; - ConstructNative = NULL; + ConstructNative = nullptr; mDescriptiveName = "Class"; PClass::AllClasses.Push(this); @@ -2969,10 +2969,7 @@ DObject *PClass::CreateNew() const ConstructNative (mem); ((DObject *)mem)->SetClass (const_cast(this)); - if (Defaults != NULL) - { - InitializeSpecials(mem); - } + InitializeSpecials(mem); return (DObject *)mem; } @@ -3037,16 +3034,52 @@ void PClass::Derive(PClass *newclass) { newclass->ParentClass = this; newclass->ConstructNative = ConstructNative; + newclass->Symbols.SetParentTable(&this->Symbols); + newclass->InitializeDefaults(); +} - // Set up default instance of the new class. - newclass->Defaults = (BYTE *)M_Malloc(newclass->Size); - if (Defaults) memcpy(newclass->Defaults, Defaults, Size); - if (newclass->Size > Size) +//========================================================================== +// +// PClassActor :: InitializeNativeDefaults +// +//========================================================================== + +void PClass::InitializeDefaults() +{ + assert(Defaults == NULL); + Defaults = (BYTE *)M_Malloc(Size); + if (ParentClass->Defaults != NULL) { - memset(newclass->Defaults + Size, 0, newclass->Size - Size); + memcpy(Defaults, ParentClass->Defaults, ParentClass->Size); + if (Size > ParentClass->Size) + { + memset(Defaults + ParentClass->Size, 0, Size - ParentClass->Size); + } + } + else + { + memset(Defaults, 0, Size); } - newclass->Symbols.SetParentTable(&this->Symbols); + if (bRuntimeClass) + { + // Copy parent values from the parent defaults. + assert(ParentClass != NULL); + ParentClass->InitializeSpecials(Defaults); + + // and initialize our own special values. + auto it = Symbols.GetIterator(); + PSymbolTable::MapType::Pair *pair; + + while (it.NextPair(pair)) + { + auto field = dyn_cast(pair->Value); + if (field != nullptr && !(field->Flags & VARF_Native)) + { + field->Type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits); + } + } + } } //========================================================================== @@ -3136,7 +3169,6 @@ PField *PClass::AddField(FName name, PType *type, DWORD flags) { Defaults = (BYTE *)M_Realloc(Defaults, Size); memset(Defaults + oldsize, 0, Size - oldsize); - type->SetDefaultValue(Defaults, unsigned(field->Offset), &SpecialInits); } return field; } diff --git a/src/dobjtype.h b/src/dobjtype.h index e1f95a828..62860d0bd 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -137,6 +137,13 @@ struct PSymbolTable // Frees all symbols from this table. void ReleaseSymbols(); + typedef TMap MapType; + + MapType::Iterator GetIterator() + { + return MapType::Iterator(Symbols); + } + // add a name to help debugging. #ifdef _DEBUG FString name; @@ -147,7 +154,6 @@ struct PSymbolTable private: - typedef TMap MapType; PSymbolTable *ParentSymbolTable; MapType Symbols; @@ -761,6 +767,7 @@ public: void WriteAllFields(FSerializer &ar, const void *addr) const; bool ReadValue(FSerializer &ar, const char *key,void *addr) const override; bool ReadAllFields(FSerializer &ar, void *addr) const; + void InitializeDefaults(); virtual void DeriveData(PClass *newclass) {} static void StaticInit(); diff --git a/src/info.cpp b/src/info.cpp index 09d0905f6..83b455fb4 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -355,35 +355,6 @@ size_t PClassActor::PropagateMark() return Super::PropagateMark(); } -//========================================================================== -// -// PClassActor :: InitializeNativeDefaults -// -// This is used by DECORATE to assign ActorInfos to internal classes -// -//========================================================================== - -void PClassActor::InitializeNativeDefaults() -{ - assert(Defaults == NULL); - Defaults = (BYTE *)M_Malloc(Size); - if (ParentClass->Defaults != NULL) - { - memcpy(Defaults, ParentClass->Defaults, ParentClass->Size); - if (Size > ParentClass->Size) - { - memset(Defaults + ParentClass->Size, 0, Size - ParentClass->Size); - } - } - else - { - memset (Defaults, 0, Size); - // Non-DECORATE properties that must be set. - ((AActor*)Defaults)->DamageMultiply = 1.; // fixme: Make this a DECORATE property. - ((AActor*)Defaults)->ConversationRoot = -1; - } -} - //========================================================================== // // PClassActor :: SetReplacement diff --git a/src/info.h b/src/info.h index ad25bdcaf..6aee02bed 100644 --- a/src/info.h +++ b/src/info.h @@ -234,7 +234,6 @@ public: void SetDamageFactor(FName type, double factor); void SetPainChance(FName type, int chance); size_t PropagateMark(); - void InitializeNativeDefaults(); bool SetReplacement(FName replaceName); void SetDropItems(DDropItem *drops); virtual void Finalize(FStateDefinitions &statedef); diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index 07da3cf57..baa662047 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -875,7 +875,7 @@ static void ParseActorProperty(FScanner &sc, Baggage &bag) // Starts a new actor definition // //========================================================================== -PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName parentName, bool native) +PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName parentName) { PClassActor *replacee = NULL; PClassActor *ti = NULL; @@ -908,36 +908,7 @@ PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName par parent = RUNTIME_CLASS(AActor); } } - - if (native) - { - ti = PClass::FindActor(typeName); - if (ti == NULL) - { - extern void DumpTypeTable(); - DumpTypeTable(); - sc.Message(MSG_ERROR, "Unknown native actor '%s'", typeName.GetChars()); - goto create; - } - else if (ti != RUNTIME_CLASS(AActor) && ti->ParentClass->NativeClass() != parent->NativeClass()) - { - sc.Message(MSG_ERROR, "Native class '%s' does not inherit from '%s'", typeName.GetChars(), parentName.GetChars()); - parent = RUNTIME_CLASS(AActor); - goto create; - } - else if (ti->Defaults != NULL) - { - sc.Message(MSG_ERROR, "Redefinition of internal class '%s'", typeName.GetChars()); - goto create; - } - ti->InitializeNativeDefaults(); - ti->ParentClass->DeriveData(ti); - } - else - { - create: - ti = DecoDerivedClass(sc, parent, typeName); - } + ti = DecoDerivedClass(sc, parent, typeName); ti->Replacee = ti->Replacement = NULL; ti->DoomEdNum = -1; @@ -1025,12 +996,13 @@ static PClassActor *ParseActorHeader(FScanner &sc, Baggage *bag) if (sc.CheckString("native")) { - native = true; + sc.ScriptMessage("Cannot define native classes in DECORATE"); + FScriptPosition::ErrorCounter++; } try { - PClassActor *info = CreateNewActor(sc, typeName, parentName, native); + PClassActor *info = CreateNewActor(sc, typeName, parentName); info->DoomEdNum = DoomEdNum > 0 ? DoomEdNum : -1; info->SourceLumpName = Wads.GetLumpFullPath(sc.LumpNum); diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 6529059e6..2c13d8eb7 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -164,8 +164,6 @@ void CreateDamageFunction(PClassActor *info, AActor *defaults, FxExpression *id, // //========================================================================== -PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName parentName, bool native); - void HandleActorFlag(FScanner &sc, Baggage &bag, const char *part1, const char *part2, int mod); FxExpression *ParseParameter(FScanner &sc, PClassActor *cls, PType *type, bool constant); diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index aa4508950..45d78557c 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -652,6 +652,15 @@ DEFINE_PROPERTY(damage, X, Actor) CreateDamageFunction(bag.Info, defaults, id, true); } +//========================================================================== +// +//========================================================================== +DEFINE_PROPERTY(damagemultiply, F, Actor) +{ + PROP_FLOAT_PARM(dmgm, 0); + defaults->DamageMultiply = dmgm; +} + //========================================================================== // //========================================================================== diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 7db62d6fb..a2e2262f2 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -1917,13 +1917,19 @@ void ZCCCompiler::InitDefaults() if (ti->ParentClass->Defaults == DEFAULTS_VMEXPORT) { ti->ParentClass->Defaults = nullptr; - static_cast(ti->ParentClass)->InitializeNativeDefaults(); + ti->ParentClass->InitializeDefaults(); ti->ParentClass->ParentClass->DeriveData(ti->ParentClass); } - ti->InitializeNativeDefaults(); + ti->InitializeDefaults(); ti->ParentClass->DeriveData(ti); + // We need special treatment for this one field in AActor's defaults which cannot be made visible to DECORATE as a property. + // It's better to do this here under controlled conditions than deeper down in the class type classes. + if (ti == RUNTIME_CLASS(AActor)) + { + ((AActor*)ti->Defaults)->ConversationRoot = 1; + } Baggage bag; #ifdef _DEBUG diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 5aa1af293..c70ab28a1 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -23,7 +23,8 @@ class Actor : Thinker native FloatBobPhase -1; // randomly initialize by default Gravity 1; Friction 1; - DamageFactor 1.0; + DamageFactor 1.0; // damage multiplier as target of damage. + DamageMultiply 1.0; // damage multiplier as source of damage. PushFactor 0.25; WeaveIndexXY 0; WeaveIndexZ 16;