- deconstruct A_Jump with multiple labels into A_Jump(chance, RandomPick(label1, label2, label3,...)) to remove this ugly special case from the VM calling convention.

This also adds the number of available choices to OP_IJMP.
This commit is contained in:
Christoph Oelckers 2018-11-17 12:34:20 +01:00
parent 68afc419af
commit adde0510fe
4 changed files with 52 additions and 10 deletions

View file

@ -75,7 +75,6 @@ AActor *SingleActorFromTID(int tid, AActor *defactor);
static FRandom pr_camissile ("CustomActorfire");
static FRandom pr_cabullet ("CustomBullet");
static FRandom pr_cajump ("CustomJump");
static FRandom pr_cwbullet ("CustomWpBullet");
static FRandom pr_cwjump ("CustomWpJump");
static FRandom pr_cwpunch ("CustomWpPunch");
@ -87,6 +86,7 @@ static FRandom pr_burst ("Burst");
static FRandom pr_monsterrefire ("MonsterRefire");
static FRandom pr_teleport("A_Teleport");
static FRandom pr_bfgselfdamage("BFGSelfDamage");
FRandom pr_cajump("CustomJump");
//==========================================================================
//
@ -1129,13 +1129,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_Jump)
{
PARAM_ACTION_PROLOGUE(AActor);
PARAM_INT(maxchance);
PARAM_STATE_ACTION(jumpto);
paramnum++; // Increment paramnum to point at the first jump target
int count = numparam - paramnum;
if (count > 0 && (maxchance >= 256 || pr_cajump() < maxchance))
if (maxchance >= 256 || pr_cajump() < maxchance)
{
int jumpnum = (count == 1 ? 0 : (pr_cajump() % count));
PARAM_STATE_ACTION_AT(paramnum + jumpnum, jumpto);
ACTION_RETURN_STATE(jumpto);
}
ACTION_RETURN_STATE(NULL);

View file

@ -5660,7 +5660,7 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build)
ExpEmit resultreg(build, REGT_INT);
build->Emit(OP_RESULT, 0, REGT_INT, resultreg.RegNum);
build->Emit(OP_IJMP, resultreg.RegNum, 0);
build->Emit(OP_IJMP, resultreg.RegNum, choices.Size());
// Free the result register now. The simple code generation algorithm should
// automatically pick it as the destination register for each case.
@ -8781,6 +8781,41 @@ VMFunction *FxVMFunctionCall::GetDirectFunction(PFunction *callingfunc, const Ve
return nullptr;
}
//==========================================================================
//
// FxVMFunctionCall :: UnravelVarArgAJump
//
// Converts A_Jump(chance, a, b, c, d) -> A_Jump(chance, RandomPick[cajump](a, b, c, d))
// so that varargs are restricted to either text formatting or graphics drawing.
//
//==========================================================================
extern FRandom pr_cajump;
bool FxVMFunctionCall::UnravelVarArgAJump(FCompileContext &ctx)
{
FArgumentList rplist;
for (unsigned i = 1; i < ArgList.Size(); i++)
{
// This needs a bit of casting voodoo because RandomPick wants integer parameters.
auto x = new FxIntCast(new FxTypeCast(ArgList[i], TypeStateLabel, true, true), true, true);
rplist.Push(x->Resolve(ctx));
ArgList[i] = nullptr;
if (rplist[i - 1] == nullptr)
{
return false;
}
}
FxExpression *x = new FxRandomPick(&pr_cajump, rplist, false, ScriptPosition, true);
x = x->Resolve(ctx);
// This cannot be done with a cast because that interprets the value as an index.
// All we want here is to take the literal value and change its type.
if (x) x->ValueType = TypeStateLabel;
ArgList[1] = x;
ArgList.Clamp(2);
return x != nullptr;
}
//==========================================================================
//
// FxVMFunctionCall :: Resolve
@ -8813,9 +8848,18 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx)
return nullptr;
}
if (Function->Variants[0].Implementation->PrintableName.CompareNoCase("CustomStatusBar.DrawTexture") == 0)
// Unfortunately the PrintableName is the only safe thing to catch this special case here.
if (Function->Variants[0].Implementation->PrintableName.CompareNoCase("Actor.A_Jump [Native]") == 0)
{
int a = 0;
// Unravel the varargs part of this function here so that the VM->native interface does not have to deal with it anymore.
if (ArgList.Size() > 2)
{
auto ret = UnravelVarArgAJump(ctx);
if (!ret)
{
return nullptr;
}
}
}
CallingFunction = ctx.Function;

View file

@ -1764,6 +1764,7 @@ class FxVMFunctionCall : public FxExpression
PFunction *CallingFunction;
bool CheckAccessibility(const VersionInfo &ver);
bool UnravelVarArgAJump(FCompileContext&);
public:
FxVMFunctionCall(FxExpression *self, PFunction *func, FArgumentList &args, const FScriptPosition &pos, bool novirtual);

View file

@ -1062,7 +1062,7 @@ class Actor : Thinker native
deprecated("2.3") native void A_PlaySoundEx(sound whattoplay, name slot, bool looping = false, int attenuation = 0);
deprecated("2.3") native void A_StopSoundEx(name slot);
native void A_SeekerMissile(int threshold, int turnmax, int flags = 0, int chance = 50, int distance = 10);
native action state A_Jump(int chance, statelabel label, ...);
native action state A_Jump(int chance, statelabel label);
native Actor A_SpawnProjectile(class<Actor> missiletype, double spawnheight = 32, double spawnofs_xy = 0, double angle = 0, int flags = 0, double pitch = 0, int ptr = AAPTR_TARGET);
native void A_CustomBulletAttack(double spread_xy, double spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", double range = 0, int flags = 0, int ptr = AAPTR_TARGET, class<Actor> missile = null, double Spawnheight = 32, double Spawnofs_xy = 0);
native void A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = 0, color color2 = 0, int flags = 0, int aim = 0, double maxdiff = 0, class<Actor> pufftype = "BulletPuff", double spread_xy = 0, double spread_z = 0, double range = 0, int duration = 0, double sparsity = 1.0, double driftspeed = 1.0, class<Actor> spawnclass = null, double spawnofs_z = 0, int spiraloffset = 270, int limit = 0, double veleffect = 3);