diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index d9af4044a..7e80eca0c 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -2322,12 +2322,19 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size) const PClass *existclass = FindClass(name); // This is a placeholder so fill it in - if (existclass != NULL && existclass->Size == (unsigned)-1) + if (existclass != NULL && (existclass->Size == TClass_Fatal || existclass->Size == TClass_Nonfatal)) { type = const_cast(existclass); if (!IsDescendantOf(type->ParentClass)) { - I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars()); + if (existclass->Size == TClass_Fatal) + { + I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars()); + } + else + { + Printf(TEXTCOLOR_RED "%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars()); + } } DPrintf("Defining placeholder class %s\n", name.GetChars()); notnew = true; @@ -2380,7 +2387,7 @@ unsigned int PClass::Extend(unsigned int extension) // //========================================================================== -PClass *PClass::FindClassTentative(FName name) +PClass *PClass::FindClassTentative(FName name, bool fatal) { if (name == NAME_None) { @@ -2400,7 +2407,7 @@ PClass *PClass::FindClassTentative(FName name) type->TypeName = name; type->ParentClass = this; - type->Size = -1; + type->Size = fatal? TClass_Fatal : TClass_Nonfatal; type->bRuntimeClass = true; TypeTable.AddType(type, RUNTIME_CLASS(PClass), (intptr_t)type->Outer, name, bucket); return type; diff --git a/src/dobjtype.h b/src/dobjtype.h index 313130ddb..900059cab 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -599,6 +599,12 @@ public: // Meta-info for every class derived from DObject --------------------------- +enum +{ + TClass_Fatal = UINT_MAX, + TClass_Nonfatal = UINT_MAX - 1 +}; + class PClassClass; class PClass : public PStruct { @@ -661,7 +667,7 @@ public: static PClassActor *FindActor(const FString &name) { return FindActor(FName(name, true)); } static PClassActor *FindActor(ENamedName name) { return FindActor(FName(name)); } static PClassActor *FindActor(FName name); - PClass *FindClassTentative(FName name); // not static! + PClass *FindClassTentative(FName name, bool fatal = true); // not static! static TArray AllClasses; diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp index 2d179e01d..9f0a9a951 100644 --- a/src/thingdef/thingdef.cpp +++ b/src/thingdef/thingdef.cpp @@ -340,10 +340,15 @@ static void FinishThingdef() { PClassActor *ti = PClassActor::AllActorClasses[i]; - if (ti->Size == (unsigned)-1) + if (ti->Size == TClass_Fatal || ti->Size == TClass_Nonfatal) { - Printf("Class %s referenced but not defined\n", ti->TypeName.GetChars()); - errorcount++; + Printf(TEXTCOLOR_RED "Class %s referenced but not defined\n", ti->TypeName.GetChars()); + if (ti->Size == TClass_Fatal) errorcount++; + else + { + // In order to prevent a crash, this class needs to be completed, even though it defines nothing. + ti->ParentClass->CreateDerivedClass(ti->TypeName, ti->ParentClass->Size); + } continue; } diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 9124071e5..b86c690f5 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -3546,23 +3546,13 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) if (clsname != NAME_None) { - cls = desttype->FindClassTentative(clsname); - if (cls == NULL) + // for backwards compatibility with old times it cannot be made a fatal error, if the class is not defined. :( + cls = desttype->FindClassTentative(clsname, false); + if (!cls->IsDescendantOf(desttype)) { - /* lax */ - // Since this happens in released WADs it must pass without a terminal error... :( - ScriptPosition.Message(MSG_WARNING, - "Unknown class name '%s'", - clsname.GetChars(), desttype->TypeName.GetChars()); - } - else - { - if (!cls->IsDescendantOf(desttype)) - { - ScriptPosition.Message(MSG_ERROR,"class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars()); - delete this; - return NULL; - } + ScriptPosition.Message(MSG_ERROR,"class '%s' is not compatible with '%s'", clsname.GetChars(), desttype->TypeName.GetChars()); + delete this; + return NULL; } ScriptPosition.Message(MSG_DEBUG,"resolving '%s' as class name", clsname.GetChars()); }