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;