diff --git a/src/common/objects/dobject.h b/src/common/objects/dobject.h index ce591b6d65..aed2230716 100644 --- a/src/common/objects/dobject.h +++ b/src/common/objects/dobject.h @@ -179,8 +179,6 @@ public: \ #include "dobjgc.h" -class AActor; - class DObject { public: @@ -245,6 +243,7 @@ public: inline DAngle &AngleVar(FName field); inline FString &StringVar(FName field); template T*& PointerVar(FName field); + inline int* IntArray(FName field); // This is only needed for swapping out PlayerPawns and absolutely nothing else! virtual size_t PointerSubstitution (DObject *old, DObject *notOld); @@ -435,6 +434,11 @@ inline int &DObject::IntVar(FName field) return *(int*)ScriptVar(field, nullptr); } +inline int* DObject::IntArray(FName field) +{ + return (int*)ScriptVar(field, nullptr); +} + inline FTextureID &DObject::TextureIDVar(FName field) { return *(FTextureID*)ScriptVar(field, nullptr); diff --git a/src/common/scripting/backend/codegen.cpp b/src/common/scripting/backend/codegen.cpp index 9711abf728..1e30148c7c 100644 --- a/src/common/scripting/backend/codegen.cpp +++ b/src/common/scripting/backend/codegen.cpp @@ -6358,6 +6358,16 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) ABORT(newex); goto foundit; } + else if (sym->IsKindOf(RUNTIME_CLASS(PFunction))) + { + if (ctx.Version >= MakeVersion(4, 11, 100)) + { + // VMFunction is only supported since 4.12 and Raze 1.8. + newex = new FxConstant(static_cast(sym)->Variants[0].Implementation, ScriptPosition); + goto foundit; + + } + } } // now check in the owning class. @@ -6369,6 +6379,15 @@ FxExpression *FxIdentifier::Resolve(FCompileContext& ctx) newex = FxConstant::MakeConstant(sym, ScriptPosition); goto foundit; } + else if (sym->IsKindOf(RUNTIME_CLASS(PFunction))) + { + if (ctx.Version >= MakeVersion(4, 11, 100)) + { + // VMFunction is only supported since 4.12 and Raze 1.8. + newex = new FxConstant(static_cast(sym)->Variants[0].Implementation, ScriptPosition); + goto foundit; + } + } else if (ctx.Function == nullptr) { ScriptPosition.Message(MSG_ERROR, "Unable to access class member %s from constant declaration", sym->SymbolName.GetChars()); diff --git a/src/common/scripting/backend/codegen.h b/src/common/scripting/backend/codegen.h index 2781adbe5a..5dd066b570 100644 --- a/src/common/scripting/backend/codegen.h +++ b/src/common/scripting/backend/codegen.h @@ -506,6 +506,13 @@ public: isresolved = true; } + FxConstant(VMFunction* state, const FScriptPosition& pos) : FxExpression(EFX_Constant, pos) + { + value.pointer = state; + ValueType = value.Type = TypeVMFunction; + isresolved = true; + } + FxConstant(const FScriptPosition &pos) : FxExpression(EFX_Constant, pos) { value.pointer = nullptr; diff --git a/src/common/scripting/core/imports.cpp b/src/common/scripting/core/imports.cpp index eed84980a9..ff6d7ceba7 100644 --- a/src/common/scripting/core/imports.cpp +++ b/src/common/scripting/core/imports.cpp @@ -147,6 +147,24 @@ VMFunction *FindVMFunction(PClass *cls, const char *name) } +//========================================================================== +// +// Find an action function in AActor's table from a qualified name +// This cannot search in structs. sorry. :( +// +//========================================================================== + +VMFunction* FindVMFunction( const char* name) +{ + auto p = strchr(name, '.'); + if (p == nullptr) return nullptr; + std::string clsname(name, p - name); + auto cls = PClass::FindClass(clsname.c_str()); + if (cls == nullptr) return nullptr; + return FindVMFunction(cls, p + 1); +} + + //========================================================================== // // Sorting helpers diff --git a/src/common/scripting/core/types.cpp b/src/common/scripting/core/types.cpp index 6543dde9e9..f27faa7ab5 100644 --- a/src/common/scripting/core/types.cpp +++ b/src/common/scripting/core/types.cpp @@ -75,6 +75,7 @@ PStruct *TypeStringStruct; PStruct* TypeQuaternionStruct; PPointer *TypeNullPtr; PPointer *TypeVoidPtr; +PPointer* TypeVMFunction; // CODE -------------------------------------------------------------------- @@ -322,6 +323,7 @@ void PType::StaticInit() TypeTable.AddType(TypeTextureID = new PTextureID, NAME_TextureID); TypeVoidPtr = NewPointer(TypeVoid, false); + TypeVMFunction = NewPointer(NewStruct("VMFunction", nullptr, true)); TypeColorStruct = NewStruct("@ColorStruct", nullptr); //This name is intentionally obfuscated so that it cannot be used explicitly. The point of this type is to gain access to the single channels of a color value. TypeStringStruct = NewStruct("Stringstruct", nullptr, true); TypeQuaternionStruct = NewStruct("QuatStruct", nullptr, true); diff --git a/src/common/scripting/core/types.h b/src/common/scripting/core/types.h index 789cc7d3e4..850c354a81 100644 --- a/src/common/scripting/core/types.h +++ b/src/common/scripting/core/types.h @@ -697,6 +697,8 @@ extern PPointer *TypeFont; extern PStateLabel *TypeStateLabel; extern PPointer *TypeNullPtr; extern PPointer *TypeVoidPtr; +extern PPointer* TypeVMFunction; + inline FString &DObject::StringVar(FName field) { diff --git a/src/common/scripting/frontend/zcc_compile.cpp b/src/common/scripting/frontend/zcc_compile.cpp index fbe3d80ddc..815af694b7 100644 --- a/src/common/scripting/frontend/zcc_compile.cpp +++ b/src/common/scripting/frontend/zcc_compile.cpp @@ -57,6 +57,13 @@ double GetFloatConst(FxExpression *ex, FCompileContext &ctx) return ex ? static_cast(ex)->GetValue().GetFloat() : 0; } +VMFunction* GetFuncConst(FxExpression* ex, FCompileContext& ctx) +{ + ex = new FxTypeCast(ex, TypeVMFunction, false); + ex = ex->Resolve(ctx); + return static_cast(ex ? static_cast(ex)->GetValue().GetPointer() : nullptr); +} + const char * ZCCCompiler::GetStringConst(FxExpression *ex, FCompileContext &ctx) { ex = new FxStringCast(ex); diff --git a/src/common/scripting/frontend/zcc_compile.h b/src/common/scripting/frontend/zcc_compile.h index 82c6342ff7..19e9f8ff07 100644 --- a/src/common/scripting/frontend/zcc_compile.h +++ b/src/common/scripting/frontend/zcc_compile.h @@ -6,7 +6,6 @@ struct Baggage; struct FPropertyInfo; -class AActor; class FxExpression; typedef TDeletingArray FArgumentList; diff --git a/src/common/scripting/vm/vm.h b/src/common/scripting/vm/vm.h index 6442034c1e..2b7344d5dc 100644 --- a/src/common/scripting/vm/vm.h +++ b/src/common/scripting/vm/vm.h @@ -797,6 +797,7 @@ class AActor; class PFunction; VMFunction *FindVMFunction(PClass *cls, const char *name); +VMFunction* FindVMFunction(const char* name); #define DECLARE_VMFUNC(cls, name) static VMFunction *name; if (name == nullptr) name = FindVMFunction(RUNTIME_CLASS(cls), #name); FString FStringFormat(VM_ARGS, int offset = 0); diff --git a/src/common/utility/configfile.h b/src/common/utility/configfile.h index cc484a3c24..f1a5ab87d6 100644 --- a/src/common/utility/configfile.h +++ b/src/common/utility/configfile.h @@ -66,6 +66,10 @@ public: bool NextInSection (const char *&key, const char *&value); const char *GetValueForKey (const char *key) const; void SetValueForKey (const char *key, const char *value, bool duplicates=false); + void SetValueForKey(const char* key, const FString& value, bool duplicates = false) + { + SetValueForKey(key, value.GetChars(), duplicates); + } const char *GetPathName () const { return PathName.GetChars(); } void ChangePathName (const char *path); diff --git a/src/g_statusbar/sbar.h b/src/g_statusbar/sbar.h index 767e4de6eb..b19a29245c 100644 --- a/src/g_statusbar/sbar.h +++ b/src/g_statusbar/sbar.h @@ -43,6 +43,7 @@ #include "v_draw.h" #include "c_cvars.h" +class AActor; EXTERN_CVAR(Int, con_scaletext); inline int active_con_scaletext(F2DDrawer* drawer, bool newconfont = false) diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 320c28cd40..34cd346667 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -256,6 +256,7 @@ union FPropParam int i; double d; const char *s; + VMFunction* fu; FxExpression *exp; }; @@ -313,6 +314,9 @@ int MatchString (const char *in, const char **strings); #define PROP_STRING_PARM(var, no) \ const char *var = params[(no)+1].s; +#define PROP_NAME_PARM(var, no) \ + FName var = params[(no)+1].s; + #define PROP_EXP_PARM(var, no) \ FxExpression *var = params[(no)+1].exp; @@ -325,6 +329,9 @@ int MatchString (const char *in, const char **strings); #define PROP_DOUBLE_PARM(var, no) \ double var = params[(no)+1].d; +#define PROP_FUNC_PARM(var, no) \ + auto var = params[(no)+1].fu; + #define PROP_COLOR_PARM(var, no, scriptpos) \ int var = params[(no)+1].i== 0? params[(no)+2].i : V_GetColor(params[(no)+2].s, scriptpos); diff --git a/src/scripting/zscript/zcc_compile_doom.cpp b/src/scripting/zscript/zcc_compile_doom.cpp index d6b8780f93..8c21659dcd 100644 --- a/src/scripting/zscript/zcc_compile_doom.cpp +++ b/src/scripting/zscript/zcc_compile_doom.cpp @@ -50,6 +50,7 @@ bool isActor(PContainerType *type); void AddActorInfo(PClass *cls); int GetIntConst(FxExpression* ex, FCompileContext& ctx); double GetFloatConst(FxExpression* ex, FCompileContext& ctx); +VMFunction* GetFuncConst(FxExpression* ex, FCompileContext& ctx); //========================================================================== // @@ -282,6 +283,10 @@ void ZCCDoomCompiler::DispatchProperty(FPropertyInfo *prop, ZCC_PropertyStmt *pr conv.d = GetFloatConst(ex, ctx); break; + case 'G': + conv.fu = GetFuncConst(ex, ctx); + break; + case 'Z': // an optional string. Does not allow any numeric value. if (ex->ValueType != TypeString) {