diff --git a/source/common/scripting/backend/codegen.cpp b/source/common/scripting/backend/codegen.cpp index 4b9ffb083..1e30148c7 100644 --- a/source/common/scripting/backend/codegen.cpp +++ b/source/common/scripting/backend/codegen.cpp @@ -1639,23 +1639,6 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) // don't go through the entire list if the types are the same. goto basereturn; } - else if ((basex->ValueType == TypeString || basex->ValueType == TypeName) && ValueType == TypeVMFunction && basex->isConstant()) - { - FxExpression* x = new FxStringCast(basex); - x = x->Resolve(ctx); - basex = nullptr; - auto c = static_cast(x)->GetValue().GetString().GetChars(); - auto func = FindVMFunction(c); - if (func == nullptr) - { - ScriptPosition.Message(MSG_ERROR, "VM function %s not found", c); - delete this; - return nullptr; - } - auto newx = new FxConstant(func, ScriptPosition); - delete this; - return newx->Resolve(ctx); - } else if (basex->ValueType == TypeNullPtr && ValueType->isPointer()) { goto basereturn; @@ -6375,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. @@ -6386,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/source/common/scripting/core/imports.cpp b/source/common/scripting/core/imports.cpp index 08ae1a330..ff6d7ceba 100644 --- a/source/common/scripting/core/imports.cpp +++ b/source/common/scripting/core/imports.cpp @@ -150,6 +150,7 @@ 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. :( // //========================================================================== diff --git a/source/common/scripting/frontend/zcc_compile.cpp b/source/common/scripting/frontend/zcc_compile.cpp index fbe3d80dd..815af694b 100644 --- a/source/common/scripting/frontend/zcc_compile.cpp +++ b/source/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/source/core/states.h b/source/core/states.h index f7bb4ba92..6c9bb7fa3 100644 --- a/source/core/states.h +++ b/source/core/states.h @@ -99,7 +99,10 @@ struct FStateParamInfo struct FState { FState *NextState; - VMFunction *ActionFunc; + VMFunction *ActionFunc; // called when an attached animation triggers an event. (i.e. Blood's SEQs. Should be made game independent.) + VMFunction *EnterFunc; // called when entering the state. + VMFunction *TickFunc; // called when ticking the state. + VMFunction *MoveFunc; // called when moving the actor int16_t sprite; int16_t Tics; uint8_t Frame; diff --git a/source/core/thingdef.h b/source/core/thingdef.h index d862d99e2..0df39c192 100644 --- a/source/core/thingdef.h +++ b/source/core/thingdef.h @@ -161,6 +161,7 @@ union FPropParam int i; double d; const char *s; + VMFunction* fu; FxExpression *exp; }; @@ -233,6 +234,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/source/core/thingdef_properties.cpp b/source/core/thingdef_properties.cpp index c487ad153..d7aefe7ea 100644 --- a/source/core/thingdef_properties.cpp +++ b/source/core/thingdef_properties.cpp @@ -392,3 +392,24 @@ DEFINE_PROPERTY(precacheclass, Sssssssssssssssssssssssssssssss, CoreActor) } } +// hopefully this can later be integrated into the state block and made usable for all games. +// for now we need something that can be made to work quickly without messing around with the parser. +DEFINE_PROPERTY(aistate, SSIIGGGGs, CoreActor) +{ + PROP_STRING_PARM(label, 0); + PROP_STRING_PARM(seq, 1); // either a sequence name or an Id as '#123'. + PROP_INT_PARM(type, 2); + PROP_INT_PARM(duration, 3); + PROP_FUNC_PARM(action, 4); + PROP_FUNC_PARM(enter, 5); + PROP_FUNC_PARM(tick, 6); + PROP_FUNC_PARM(move, 7); + const char* next = nullptr; + if (PROP_PARM_COUNT > 8) + { + PROP_STRING_PARM(_next, 8); + next = _next; + } + +} + diff --git a/source/core/version.h b/source/core/version.h index 1e195b3b6..98c186eca 100644 --- a/source/core/version.h +++ b/source/core/version.h @@ -49,8 +49,8 @@ const char *GetVersionString(); #define RC_PRODUCTVERSION2 VERSIONSTR // These are for content versioning. #define VER_MAJOR 4 -#define VER_MINOR 10 -#define VER_REVISION 0 +#define VER_MINOR 11 +#define VER_REVISION 100 #define ENG_MAJOR 1 #define ENG_MINOR 7 @@ -71,15 +71,15 @@ const char *GetVersionString(); #define SAVEGAME_EXT "dsave" -#define MINSAVEVER_DN3D 19 -#define MINSAVEVER_BLD 19 -#define MINSAVEVER_SW 19 -#define MINSAVEVER_PS 19 +#define MINSAVEVER_DN3D 20 +#define MINSAVEVER_BLD 20 +#define MINSAVEVER_SW 20 +#define MINSAVEVER_PS 20 -#define SAVEVER_DN3D 19 -#define SAVEVER_BLD 19 -#define SAVEVER_SW 19 -#define SAVEVER_PS 19 +#define SAVEVER_DN3D 20 +#define SAVEVER_BLD 20 +#define SAVEVER_SW 20 +#define SAVEVER_PS 20 #define NETGAMEVERSION 1 diff --git a/source/core/zcc_compile_raze.cpp b/source/core/zcc_compile_raze.cpp index 233611363..de4313ab6 100644 --- a/source/core/zcc_compile_raze.cpp +++ b/source/core/zcc_compile_raze.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); //========================================================================== // @@ -329,6 +330,10 @@ void ZCCRazeCompiler::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) { @@ -610,13 +615,7 @@ void ZCCRazeCompiler::DispatchScriptProperty(PProperty *prop, ZCC_PropertyStmt * } else if (f->Type == TypeVMFunction) { - auto name = GetStringConst(ex, ctx); - auto vmfunc = FindVMFunction(name); - if (!vmfunc) - { - Error(property, "'%s': Unknown function", name); - } - *(void**)addr = vmfunc; + *(VMFunction**)addr = GetFuncConst(ex, ctx); } else if (f->Type == TypeSound) { diff --git a/source/games/blood/src/ai.cpp b/source/games/blood/src/ai.cpp index e2d7466f3..83bac4ddd 100644 --- a/source/games/blood/src/ai.cpp +++ b/source/games/blood/src/ai.cpp @@ -91,7 +91,7 @@ void aiNewState(DBloodActor* actor, AISTATE* pAIState) { seqStartId += pAIState->seqId; if (getSequence(seqStartId)) - seqSpawn(seqStartId, actor, *pAIState->funcId); + seqSpawn(seqStartId, actor, pAIState->funcId? *pAIState->funcId : nullptr); } if (pAIState->enterFunc) diff --git a/source/games/blood/src/blood.h b/source/games/blood/src/blood.h index ee552ab02..5eaaa02c9 100644 --- a/source/games/blood/src/blood.h +++ b/source/games/blood/src/blood.h @@ -249,7 +249,7 @@ DEF_ANIMATOR(ThrowCallback2) // event callbacks DEF_ANIMATOR(fxFlameLick) // 0 -DEF_ANIMATOR(Remove) // 1 +DEF_ANIMATOR(RemoveActor) // 1 DEF_ANIMATOR(FlareBurst) // 2 DEF_ANIMATOR(fxFlareSpark) // 3 DEF_ANIMATOR(fxFlareSparkLite) // 4 diff --git a/source/games/blood/src/callback.cpp b/source/games/blood/src/callback.cpp index 8726657ad..e78738538 100644 --- a/source/games/blood/src/callback.cpp +++ b/source/games/blood/src/callback.cpp @@ -68,7 +68,7 @@ void fxFlameLick(DBloodActor* actor) // 0 // //--------------------------------------------------------------------------- -void Remove(DBloodActor* actor) // 1 +void RemoveActor(DBloodActor* actor) // 1 { if (!actor) return; evKillActor(actor, AF(fxFlareSpark)); @@ -101,9 +101,9 @@ void FlareBurst(DBloodActor* actor) // 2 auto spAngVec = DAngle::fromBam(i << 29).ToVector().Rotated90CW() * nRadius; if (i & 1) spAngVec *= 0.5; spawnedactor->vel += DVector3(DVector2(0, spAngVec.X).Rotated(nAngVec.X, nAngVec.Y), spAngVec.Y); - evPostActor(spawnedactor, 960, AF(Remove)); + evPostActor(spawnedactor, 960, AF(RemoveActor)); } - evPostActor(actor, 0, AF(Remove)); + evPostActor(actor, 0, AF(RemoveActor)); } //--------------------------------------------------------------------------- @@ -598,7 +598,7 @@ void returnFlagToBase(DBloodActor* actor) // 17 break; } } - evPostActor(actor, 0, AF(Remove)); + evPostActor(actor, 0, AF(RemoveActor)); } //--------------------------------------------------------------------------- @@ -723,7 +723,7 @@ void DropVoodooCb(DBloodActor* actor) // unused auto Owner = actor->GetOwner(); if (Owner == nullptr) { - evPostActor(actor, 0, AF(Remove)); + evPostActor(actor, 0, AF(RemoveActor)); return; } DBloodPlayer* pPlayer; @@ -733,7 +733,7 @@ void DropVoodooCb(DBloodActor* actor) // unused pPlayer = nullptr; if (!pPlayer) { - evPostActor(actor, 0, AF(Remove)); + evPostActor(actor, 0, AF(RemoveActor)); return; } actor->spr.Angles.Yaw = (Owner->spr.pos - actor->spr.pos).Angle(); @@ -741,7 +741,7 @@ void DropVoodooCb(DBloodActor* actor) // unused { if (actor->xspr.data1 == 0) { - evPostActor(actor, 0, AF(Remove)); + evPostActor(actor, 0, AF(RemoveActor)); return; } @@ -775,7 +775,7 @@ void DropVoodooCb(DBloodActor* actor) // unused int nDmg = actDamageSprite(actor, actor2, kDamageSpirit, actor->xspr.data1 << 4); actor->xspr.data1 = ClipLow(actor->xspr.data1 - nDmg, 0); sub_76A08(actor2, actor, pPlayer2); - evPostActor(actor, 0, AF(Remove)); + evPostActor(actor, 0, AF(RemoveActor)); return; } } @@ -816,7 +816,7 @@ void DropVoodooCb(DBloodActor* actor) // unused if (vd && (Chance(vd) || nextactor == nullptr)) { sub_76A08(actor2, actor, NULL); - evPostActor(actor, 0, AF(Remove)); + evPostActor(actor, 0, AF(RemoveActor)); return; } } @@ -824,7 +824,7 @@ void DropVoodooCb(DBloodActor* actor) // unused } } actor->xspr.data1 = ClipLow(actor->xspr.data1 - 1, 0); - evPostActor(actor, 0, AF(Remove)); + evPostActor(actor, 0, AF(RemoveActor)); } } diff --git a/source/games/blood/src/fx.cpp b/source/games/blood/src/fx.cpp index 0233f019f..bb666a7d4 100644 --- a/source/games/blood/src/fx.cpp +++ b/source/games/blood/src/fx.cpp @@ -189,7 +189,7 @@ DBloodActor* CFX::fxSpawnActor(FX_ID nFx, sectortype* pSector, const DVector3& p if (angle == nullAngle) angle = mapangle(pFX->defangle); if (angle != nullAngle) - evPostActor(actor, angle.Buildang() + Random2(angle.Buildang() >> 1), AF(Remove)); + evPostActor(actor, angle.Buildang() + Random2(angle.Buildang() >> 1), AF(RemoveActor)); return actor; } diff --git a/source/games/blood/src/nnexts.cpp b/source/games/blood/src/nnexts.cpp index 57e91e80a..474961ca4 100644 --- a/source/games/blood/src/nnexts.cpp +++ b/source/games/blood/src/nnexts.cpp @@ -3804,7 +3804,7 @@ void useSeqSpawnerGen(DBloodActor* sourceactor, int objType, sectortype* pSector } // should be: the more is seqs, the shorter is timer - evPostActor(spawned, 1000, AF(Remove)); + evPostActor(spawned, 1000, AF(RemoveActor)); } } else @@ -9211,9 +9211,9 @@ void callbackUniMissileBurst(DBloodActor* actor) // 22 auto spAngVec = DAngle::fromBam(i << 29).ToVector().Rotated90CW() * nRadius; if (i & 1) spAngVec *= 0.5; burstactor->vel += DVector3(DVector2(0, spAngVec.X).Rotated(nAngVec.X, nAngVec.Y), spAngVec.Y); - evPostActor(burstactor, 960, AF(Remove)); + evPostActor(burstactor, 960, AF(RemoveActor)); } - evPostActor(actor, 0, AF(Remove)); + evPostActor(actor, 0, AF(RemoveActor)); } diff --git a/source/games/blood/src/player.cpp b/source/games/blood/src/player.cpp index 4c519c4a4..6b78a31a4 100644 --- a/source/games/blood/src/player.cpp +++ b/source/games/blood/src/player.cpp @@ -2191,7 +2191,7 @@ int playerDamageSprite(DBloodActor* source, DBloodPlayer* pPlayer, DAMAGE_TYPE n DBloodActor* pItem = nullptr; if (pPlayer->GetActor()->xspr.dropMsg && (pItem = actDropObject(pActor, pPlayer->GetActor()->xspr.dropMsg)) != NULL) - evPostActor(pItem, 500, AF(Remove)); + evPostActor(pItem, 500, AF(RemoveActor)); if (pPlayer->GetActor()->xspr.key) { @@ -2202,7 +2202,7 @@ int playerDamageSprite(DBloodActor* source, DBloodPlayer* pPlayer, DAMAGE_TYPE n } if (i == 0 && (pItem = actDropObject(pActor, (pPlayer->GetActor()->xspr.key + kItemKeyBase) - 1)) != NULL) - evPostActor(pItem, 500, AF(Remove)); + evPostActor(pItem, 500, AF(RemoveActor)); } diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index d0dc0adbd..aab2ff7b3 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -1,4 +1,4 @@ -version "4.10" +version "4.11.100" #include "zscript/engine/base.zs" #include "zscript/engine/dynarrays.zs" #include "zscript/engine/inputevents.zs" diff --git a/wadsrc/static/zscript/games/blood/actors/missiles.zs b/wadsrc/static/zscript/games/blood/actors/missiles.zs index 1d81b6aa2..10d74d233 100644 --- a/wadsrc/static/zscript/games/blood/actors/missiles.zs +++ b/wadsrc/static/zscript/games/blood/actors/missiles.zs @@ -10,7 +10,7 @@ class BloodMissileBase : BloodActor meta double randomVel; meta int seqID; meta name seqName; - meta VMFunction seqCallbackID; + meta VMFunction seqCallback; property prefix: none; property speed: speed; @@ -23,7 +23,7 @@ class BloodMissileBase : BloodActor property randomVel: randomVel; property seqID: seqID; property seqName: seqName; - property seqCallbackID: seqCallbackID; + property seqCallback: seqCallback; default { @@ -44,7 +44,7 @@ class BloodMissileBase : BloodActor } else if (self.seqID > -1) { - self.seqSpawnID(self.seqID, self.seqCallbackID); + self.seqSpawnID(self.seqID, self.seqCallback); } if (self.callback != null) { @@ -91,7 +91,7 @@ class BloodMissileFlareRegular : BloodMissileBase scale 0.500000, 0.500000; shade -128; clipdist 8.000000; - callback "BloodActor.fxFlareSpark"; + callback fxFlareSpark; spawnsoundID 422; } } @@ -104,7 +104,7 @@ class BloodMissileTeslaAlt : BloodMissileBase scale 0.500000, 0.500000; shade -128; clipdist 8.000000; - callback "BloodActor.fxTeslaAlt"; + callback fxTeslaAlt; } } class BloodMissileFlareAlt : BloodMissileBase @@ -116,14 +116,14 @@ class BloodMissileFlareAlt : BloodMissileBase scale 0.500000, 0.500000; shade -128; clipdist 1.000000; - callback "BloodActor.fxFlareSpark"; + callback fxFlareSpark; spawnsoundID 422; } override void initMissile(BloodActor spawner) { super.initMissile(spawner); - self.evPostActorCallback(30, "BloodActor.FlareBurst"); + self.evPostActorCallback(30, FlareBurst); } } class BloodMissileFlameSpray : BloodMissileBase @@ -156,7 +156,7 @@ class BloodMissileFireball : BloodMissileBase clipdist 8.000000; spawnsoundID 441; seqID 22; - seqCallbackID "BloodActor.FireballSeqCallback"; + seqCallback FireballSeqCallback; } } class BloodMissileTeslaRegular : BloodMissileBase @@ -238,7 +238,7 @@ class BloodMissileFireballNapalm : BloodMissileBase clipdist 6.000000; spawnsoundID 441; seqID 61; - seqCallbackID "BloodActor.NapalmSeqCallback"; + seqCallback NapalmSeqCallback; } } class BloodMissileFireballCerberus : BloodMissileBase @@ -250,7 +250,7 @@ class BloodMissileFireballCerberus : BloodMissileBase shade -128; clipdist 6.000000; seqID 61; - seqCallbackID "BloodActor.Fx32Callback"; + seqCallback Fx32Callback; } } class BloodMissileFireballTchernobog : BloodMissileBase @@ -262,7 +262,7 @@ class BloodMissileFireballTchernobog : BloodMissileBase shade -128; clipdist 4.000000; seqID 23; - seqCallbackID "BloodActor.Fx33Callback"; + seqCallback Fx33Callback; movementAdd 0.5; RandomVel 0x11111; } @@ -276,7 +276,7 @@ class BloodMissileLifeLeechRegular : BloodMissileBase scale 0.500000, 0.500000; shade -128; clipdist 4.000000; - callback "BloodActor.fxFlameLick"; + callback fxFlameLick; } } class BloodMissileLifeLeechAltNormal : BloodMissileBase @@ -299,7 +299,7 @@ class BloodMissileLifeLeechAltSmall : BloodMissileBase scale 0.500000, 0.500000; shade -128; clipdist 4.000000; - callback "BloodActor.fxArcSpark"; + callback fxArcSpark; } } diff --git a/wadsrc/static/zscript/games/blood/bloodactor.zs b/wadsrc/static/zscript/games/blood/bloodactor.zs index 0cb60e4c3..ec33e0055 100644 --- a/wadsrc/static/zscript/games/blood/bloodactor.zs +++ b/wadsrc/static/zscript/games/blood/bloodactor.zs @@ -302,7 +302,7 @@ native void FireballTrapSeqCallback(); native void MGunFireSeqCallback(); native void MGunOpenSeqCallback(); native void fxFlameLick(); // 0 -native void Remove(); // 1 +native void RemoveActor(); // 1 native void FlareBurst(); // 2 native void fxFlareSpark(); // 3 native void fxFlareSparkLite(); // 4 @@ -410,7 +410,7 @@ native void DropVoodooCb(); // unused } if (itemtype is 'BloodFlagBase' && gGameOptions.nGameType == Blood.kTeamplay) { - spawned.evPostActorCallback(1800, "BloodActor.returnFlagToBase"); + spawned.evPostActorCallback(1800, returnFlagToBase); } double top, bottom; @@ -465,7 +465,7 @@ native void DropVoodooCb(); // unused spawned.cstat |= CSTAT_SPRITE_BLOCK; spawned.xspr.target = null; - spawned.evPostActorCallback(600, "BloodActor.Remove"); + spawned.evPostActorCallback(600, RemoveActor); spawned.initMissile(self); // handle type specific init.