mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 23:02:08 +00:00
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.
This commit is contained in:
parent
15ddf70f58
commit
6529931281
9 changed files with 81 additions and 86 deletions
|
@ -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<PClass *>(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<PField>(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;
|
||||
}
|
||||
|
|
|
@ -137,6 +137,13 @@ struct PSymbolTable
|
|||
// Frees all symbols from this table.
|
||||
void ReleaseSymbols();
|
||||
|
||||
typedef TMap<FName, PSymbol *> 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<FName, PSymbol *> 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();
|
||||
|
|
29
src/info.cpp
29
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
|
|
|
@ -1917,13 +1917,19 @@ void ZCCCompiler::InitDefaults()
|
|||
if (ti->ParentClass->Defaults == DEFAULTS_VMEXPORT)
|
||||
{
|
||||
ti->ParentClass->Defaults = nullptr;
|
||||
static_cast<PClassActor *>(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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue