implemented proper handling of VM functions as identifiers.

This commit is contained in:
Christoph Oelckers 2023-10-06 18:24:57 +02:00
parent 2c08ee0c5d
commit 6250906879
17 changed files with 107 additions and 70 deletions

View file

@ -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<FxConstant*>(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<PFunction*>(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<PFunction*>(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());

View file

@ -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. :(
//
//==========================================================================

View file

@ -57,6 +57,13 @@ double GetFloatConst(FxExpression *ex, FCompileContext &ctx)
return ex ? static_cast<FxConstant*>(ex)->GetValue().GetFloat() : 0;
}
VMFunction* GetFuncConst(FxExpression* ex, FCompileContext& ctx)
{
ex = new FxTypeCast(ex, TypeVMFunction, false);
ex = ex->Resolve(ctx);
return static_cast<VMFunction*>(ex ? static_cast<FxConstant*>(ex)->GetValue().GetPointer() : nullptr);
}
const char * ZCCCompiler::GetStringConst(FxExpression *ex, FCompileContext &ctx)
{
ex = new FxStringCast(ex);

View file

@ -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;

View file

@ -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);

View file

@ -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;
}
}

View file

@ -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

View file

@ -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)
{

View file

@ -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)

View file

@ -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

View file

@ -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));
}
}

View file

@ -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;
}

View file

@ -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));
}

View file

@ -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));
}

View file

@ -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"

View file

@ -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;
}
}

View file

@ -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.