mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-01-31 04:50:48 +00:00
- Added a RETI instruction for returning 15-bit signed immediate values.
- Changed Actor's Damage property into an actual function. All access to the damage property must now be done through GetMissileDamage. actor->GetMissileDamage(0, 1) is equivalent to the former actor->Damage, for the case where actor->Damage was not an expression. (I suppose I will probably need to make a thunk for DECORATE expressions that want to read it.) - Cleaned up some decorate expression evaluation functions that are no longer used. SVN r3919 (scripting)
This commit is contained in:
parent
5e184260ac
commit
6e88529324
23 changed files with 271 additions and 196 deletions
|
@ -797,7 +797,7 @@ public:
|
||||||
fixed_t velx, vely, velz; // velocity
|
fixed_t velx, vely, velz; // velocity
|
||||||
SDWORD tics; // state tic counter
|
SDWORD tics; // state tic counter
|
||||||
FState *state;
|
FState *state;
|
||||||
SDWORD Damage; // For missiles and monster railgun
|
VMFunction *Damage; // For missiles and monster railgun
|
||||||
int projectileKickback;
|
int projectileKickback;
|
||||||
DWORD flags;
|
DWORD flags;
|
||||||
DWORD flags2; // Heretic flags
|
DWORD flags2; // Heretic flags
|
||||||
|
|
|
@ -852,7 +852,7 @@ static int PatchThing (int thingy)
|
||||||
}
|
}
|
||||||
else if (linelen == 14 && stricmp (Line1, "Missile damage") == 0)
|
else if (linelen == 14 && stricmp (Line1, "Missile damage") == 0)
|
||||||
{
|
{
|
||||||
info->Damage = val;
|
info->Damage = CreateDamageFunction(val);
|
||||||
}
|
}
|
||||||
else if (linelen == 5)
|
else if (linelen == 5)
|
||||||
{
|
{
|
||||||
|
|
|
@ -47,7 +47,7 @@ static void BrainishExplosion (fixed_t x, fixed_t y, fixed_t z)
|
||||||
boom->SetState (state);
|
boom->SetState (state);
|
||||||
}
|
}
|
||||||
boom->effects = 0;
|
boom->effects = 0;
|
||||||
boom->Damage = 0; // disables collision detection which is not wanted here
|
boom->Damage = NULL; // disables collision detection which is not wanted here
|
||||||
boom->tics -= pr_brainscream() & 7;
|
boom->tics -= pr_brainscream() & 7;
|
||||||
if (boom->tics < 1)
|
if (boom->tics < 1)
|
||||||
boom->tics = 1;
|
boom->tics = 1;
|
||||||
|
|
|
@ -144,7 +144,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom)
|
||||||
|
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
{
|
{
|
||||||
n = self->Damage; // GetMissileDamage (0, 1);
|
n = self->GetMissileDamage(0, 1);
|
||||||
}
|
}
|
||||||
if (spawntype == NULL)
|
if (spawntype == NULL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -65,7 +65,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BetaSkullAttack)
|
||||||
return 0;
|
return 0;
|
||||||
S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM);
|
S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM);
|
||||||
A_FaceTarget(self);
|
A_FaceTarget(self);
|
||||||
damage = (pr_oldsoul()%8+1)*self->Damage;
|
damage = (pr_oldsoul()%8+1)*self->GetMissileDamage(0,1);
|
||||||
P_DamageMobj(self->target, self, self, damage, NAME_None);
|
P_DamageMobj(self->target, self, self, damage, NAME_None);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,7 +116,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LichAttack)
|
||||||
fire->velx = baseFire->velx;
|
fire->velx = baseFire->velx;
|
||||||
fire->vely = baseFire->vely;
|
fire->vely = baseFire->vely;
|
||||||
fire->velz = baseFire->velz;
|
fire->velz = baseFire->velz;
|
||||||
fire->Damage = 0;
|
fire->Damage = NULL;
|
||||||
fire->health = (i+1) * 2;
|
fire->health = (i+1) * 2;
|
||||||
P_CheckMissileSpawn (fire);
|
P_CheckMissileSpawn (fire);
|
||||||
}
|
}
|
||||||
|
|
|
@ -356,7 +356,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LastZap)
|
||||||
{
|
{
|
||||||
mo->SetState (mo->FindState (NAME_Death));
|
mo->SetState (mo->FindState (NAME_Death));
|
||||||
mo->velz = 40*FRACUNIT;
|
mo->velz = 40*FRACUNIT;
|
||||||
mo->Damage = 0;
|
mo->Damage = NULL;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -302,6 +302,9 @@ size_t PClassActor::PropagateMark()
|
||||||
GC::Mark(OwnedStates[i].ActionFunc);
|
GC::Mark(OwnedStates[i].ActionFunc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Mark damage function
|
||||||
|
GC::Mark(((AActor *)Defaults)->Damage);
|
||||||
|
|
||||||
// marked += ActorInfo->NumOwnedStates * sizeof(FState);
|
// marked += ActorInfo->NumOwnedStates * sizeof(FState);
|
||||||
return Super::PropagateMark();
|
return Super::PropagateMark();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2832,7 +2832,7 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case APROP_Damage:
|
case APROP_Damage:
|
||||||
actor->Damage = value;
|
actor->Damage = CreateDamageFunction(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case APROP_Alpha:
|
case APROP_Alpha:
|
||||||
|
@ -2994,7 +2994,7 @@ int DLevelScript::GetActorProperty (int tid, int property)
|
||||||
{
|
{
|
||||||
case APROP_Health: return actor->health;
|
case APROP_Health: return actor->health;
|
||||||
case APROP_Speed: return actor->Speed;
|
case APROP_Speed: return actor->Speed;
|
||||||
case APROP_Damage: return actor->Damage; // Should this call GetMissileDamage() instead?
|
case APROP_Damage: return actor->GetMissileDamage(0,1);
|
||||||
case APROP_DamageFactor:return actor->DamageFactor;
|
case APROP_DamageFactor:return actor->DamageFactor;
|
||||||
case APROP_Alpha: return actor->alpha;
|
case APROP_Alpha: return actor->alpha;
|
||||||
case APROP_RenderStyle: for (int style = STYLE_None; style < STYLE_Count; ++style)
|
case APROP_RenderStyle: for (int style = STYLE_None; style < STYLE_Count; ++style)
|
||||||
|
|
|
@ -136,6 +136,7 @@ IMPLEMENT_POINTY_CLASS (AActor)
|
||||||
DECLARE_POINTER (LastHeard)
|
DECLARE_POINTER (LastHeard)
|
||||||
DECLARE_POINTER (master)
|
DECLARE_POINTER (master)
|
||||||
DECLARE_POINTER (Poisoner)
|
DECLARE_POINTER (Poisoner)
|
||||||
|
DECLARE_POINTER (Damage)
|
||||||
END_POINTERS
|
END_POINTERS
|
||||||
|
|
||||||
AActor::~AActor ()
|
AActor::~AActor ()
|
||||||
|
@ -2778,21 +2779,34 @@ CCMD(utid)
|
||||||
|
|
||||||
int AActor::GetMissileDamage (int mask, int add)
|
int AActor::GetMissileDamage (int mask, int add)
|
||||||
{
|
{
|
||||||
if ((Damage & 0xC0000000) == 0x40000000)
|
if (Damage == NULL)
|
||||||
{
|
|
||||||
return EvalExpressionI (Damage & 0x3FFFFFFF, this);
|
|
||||||
}
|
|
||||||
if (Damage == 0)
|
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
VMFrameStack stack;
|
||||||
|
VMValue param = this;
|
||||||
|
VMReturn results[2];
|
||||||
|
|
||||||
|
int amount, calculated = false;
|
||||||
|
|
||||||
|
results[0].IntAt(&amount);
|
||||||
|
results[1].IntAt(&calculated);
|
||||||
|
|
||||||
|
if (stack.Call(Damage, ¶m, 1, results, 2) < 1)
|
||||||
|
{ // No results
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (calculated)
|
||||||
|
{
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
else if (mask == 0)
|
else if (mask == 0)
|
||||||
{
|
{
|
||||||
return add * Damage;
|
return add * amount;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return ((pr_missiledamage() & mask) + add) * Damage;
|
return ((pr_missiledamage() & mask) + add) * amount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -495,7 +495,7 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
|
||||||
else if (def == DEF_Projectile && sc.Compare ("Damage"))
|
else if (def == DEF_Projectile && sc.Compare ("Damage"))
|
||||||
{
|
{
|
||||||
sc.MustGetNumber ();
|
sc.MustGetNumber ();
|
||||||
defaults->Damage = sc.Number;
|
defaults->Damage = CreateDamageFunction(sc.Number);
|
||||||
}
|
}
|
||||||
else if (def == DEF_Projectile && sc.Compare ("DamageType"))
|
else if (def == DEF_Projectile && sc.Compare ("DamageType"))
|
||||||
{
|
{
|
||||||
|
|
|
@ -261,6 +261,17 @@ void FinishActor(const FScriptPosition &sc, PClassActor *info, Baggage &bag)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
static void DumpFunction(FILE *dump, VMScriptFunction *sfunc, const char *label, int labellen)
|
||||||
|
{
|
||||||
|
const char *marks = "=======================================================";
|
||||||
|
fprintf(dump, "\n%.*s %s %.*s", MAX(3, 38 - labellen / 2), marks, label, MAX(3, 38 - labellen / 2), marks);
|
||||||
|
fprintf(dump, "\nInteger regs: %-3d Float regs: %-3d Address regs: %-3d String regs: %-3d\nStack size: %d\n",
|
||||||
|
sfunc->NumRegD, sfunc->NumRegF, sfunc->NumRegA, sfunc->NumRegS, sfunc->MaxParam);
|
||||||
|
VMDumpConstants(dump, sfunc);
|
||||||
|
fprintf(dump, "\nDisassembly @ %p:\n", sfunc->Code);
|
||||||
|
VMDisasm(dump, sfunc->Code, sfunc->CodeSize, sfunc);
|
||||||
|
}
|
||||||
|
|
||||||
static void FinishThingdef()
|
static void FinishThingdef()
|
||||||
{
|
{
|
||||||
int errorcount = StateParams.ResolveAll();
|
int errorcount = StateParams.ResolveAll();
|
||||||
|
@ -305,17 +316,10 @@ static void FinishThingdef()
|
||||||
sfunc->NumArgs = NAP;
|
sfunc->NumArgs = NAP;
|
||||||
func = sfunc;
|
func = sfunc;
|
||||||
#if 1
|
#if 1
|
||||||
const char *marks = "=======================================================";
|
|
||||||
char label[64];
|
char label[64];
|
||||||
int labellen = mysnprintf(label, countof(label), "Function %s.States[%d] (*%d)",
|
int labellen = mysnprintf(label, countof(label), "Function %s.States[%d] (*%d)",
|
||||||
tcall->ActorClass->TypeName.GetChars(),
|
tcall->ActorClass->TypeName.GetChars(), tcall->FirstState, tcall->NumStates);
|
||||||
tcall->FirstState, tcall->NumStates);
|
DumpFunction(dump, sfunc, label, labellen);
|
||||||
fprintf(dump, "\n%.*s %s %.*s", MAX(3, 38 - labellen / 2), marks, label, MAX(3, 38 - labellen / 2), marks);
|
|
||||||
fprintf(dump, "\nInteger regs: %-3d Float regs: %-3d Address regs: %-3d String regs: %-3d\nStack size: %d\n",
|
|
||||||
sfunc->NumRegD, sfunc->NumRegF, sfunc->NumRegA, sfunc->NumRegS, sfunc->MaxParam);
|
|
||||||
VMDumpConstants(dump, sfunc);
|
|
||||||
fprintf(dump, "\nDisassembly @ %p:\n", sfunc->Code);
|
|
||||||
VMDisasm(dump, sfunc->Code, sfunc->CodeSize, sfunc);
|
|
||||||
codesize += sfunc->CodeSize;
|
codesize += sfunc->CodeSize;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -324,10 +328,6 @@ static void FinishThingdef()
|
||||||
tcall->ActorClass->OwnedStates[tcall->FirstState + k].SetAction(func);
|
tcall->ActorClass->OwnedStates[tcall->FirstState + k].SetAction(func);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if 1
|
|
||||||
fprintf(dump, "\n*************************************************************************\n%i code bytes\n", codesize * 4);
|
|
||||||
#endif
|
|
||||||
fclose(dump);
|
|
||||||
|
|
||||||
for (i = 0; i < PClassActor::AllActorClasses.Size(); i++)
|
for (i = 0; i < PClassActor::AllActorClasses.Size(); i++)
|
||||||
{
|
{
|
||||||
|
@ -348,7 +348,42 @@ static void FinishThingdef()
|
||||||
errorcount++;
|
errorcount++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (def->Damage != NULL)
|
||||||
|
{
|
||||||
|
VMScriptFunction *sfunc;
|
||||||
|
FxDamageValue *dmg = (FxDamageValue *)def->Damage;
|
||||||
|
sfunc = dmg->GetFunction();
|
||||||
|
if (sfunc == NULL)
|
||||||
|
{
|
||||||
|
FCompileContext ctx(ti, true);
|
||||||
|
dmg->Resolve(ctx);
|
||||||
|
VMFunctionBuilder buildit;
|
||||||
|
buildit.Registers[REGT_POINTER].Get(1); // The self pointer
|
||||||
|
dmg->Emit(&buildit);
|
||||||
|
sfunc = buildit.MakeFunction();
|
||||||
|
sfunc->NumArgs = 1;
|
||||||
|
// Save this function in case this damage value was reused
|
||||||
|
// (which happens quite easily with inheritance).
|
||||||
|
dmg->SetFunction(sfunc);
|
||||||
}
|
}
|
||||||
|
def->Damage = sfunc;
|
||||||
|
#if 1
|
||||||
|
if (sfunc != NULL)
|
||||||
|
{
|
||||||
|
char label[64];
|
||||||
|
int labellen = mysnprintf(label, countof(label), "Function %s.Damage",
|
||||||
|
ti->TypeName.GetChars());
|
||||||
|
DumpFunction(dump, sfunc, label, labellen);
|
||||||
|
codesize += sfunc->CodeSize;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if 1
|
||||||
|
fprintf(dump, "\n*************************************************************************\n%i code bytes\n", codesize * 4);
|
||||||
|
#endif
|
||||||
|
fclose(dump);
|
||||||
if (errorcount > 0)
|
if (errorcount > 0)
|
||||||
{
|
{
|
||||||
I_Error("%d errors during actor postprocessing", errorcount);
|
I_Error("%d errors during actor postprocessing", errorcount);
|
||||||
|
@ -399,3 +434,23 @@ void LoadActors ()
|
||||||
// Base time: ~52 ms
|
// Base time: ~52 ms
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// CreateDamageFunction
|
||||||
|
//
|
||||||
|
// Creates a damage function suitable for a constant, non-expressioned
|
||||||
|
// value.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
VMScriptFunction *CreateDamageFunction(int dmg)
|
||||||
|
{
|
||||||
|
VMFunctionBuilder build;
|
||||||
|
build.Registers[REGT_POINTER].Get(1); // The self pointer
|
||||||
|
build.EmitRetInt(0, false, dmg);
|
||||||
|
build.EmitRetInt(1, true, 0);
|
||||||
|
VMScriptFunction *sfunc = build.MakeFunction();
|
||||||
|
sfunc->NumArgs = 1;
|
||||||
|
return sfunc;
|
||||||
|
}
|
||||||
|
|
|
@ -141,8 +141,8 @@ public:
|
||||||
void Clear();
|
void Clear();
|
||||||
int Add(FxExpression *x, PClassActor *o, bool c);
|
int Add(FxExpression *x, PClassActor *o, bool c);
|
||||||
int Reserve(int num, PClassActor *cls);
|
int Reserve(int num, PClassActor *cls);
|
||||||
void Set(int num, FxExpression *x, bool cloned = false);
|
// void Set(int num, FxExpression *x, bool cloned = false);
|
||||||
void Copy(int dest, int src, int cnt);
|
// void Copy(int dest, int src, int cnt);
|
||||||
int ResolveAll();
|
int ResolveAll();
|
||||||
FxExpression *Get(int no);
|
FxExpression *Get(int no);
|
||||||
unsigned int Size() { return expressions.Size(); }
|
unsigned int Size() { return expressions.Size(); }
|
||||||
|
@ -184,6 +184,14 @@ inline void ResetBaggage (Baggage *bag, PClassActor *stateclass)
|
||||||
bag->statedef.MakeStateDefines(stateclass);
|
bag->statedef.MakeStateDefines(stateclass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// Damage function creation
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
VMScriptFunction *CreateDamageFunction(int dmg);
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// Action function lookup
|
// Action function lookup
|
||||||
|
@ -270,6 +278,7 @@ union FPropParam
|
||||||
int i;
|
int i;
|
||||||
float f;
|
float f;
|
||||||
const char *s;
|
const char *s;
|
||||||
|
FxExpression *exp;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*PropHandler)(AActor *defaults, PClassActor *info, Baggage &bag, FPropParam *params);
|
typedef void (*PropHandler)(AActor *defaults, PClassActor *info, Baggage &bag, FPropParam *params);
|
||||||
|
@ -328,6 +337,9 @@ int MatchString (const char *in, const char **strings);
|
||||||
#define PROP_STRING_PARM(var, no) \
|
#define PROP_STRING_PARM(var, no) \
|
||||||
const char *var = params[(no)+1].s;
|
const char *var = params[(no)+1].s;
|
||||||
|
|
||||||
|
#define PROP_EXP_PARM(var, no) \
|
||||||
|
FxExpression *var = params[(no)+1].exp;
|
||||||
|
|
||||||
#define PROP_INT_PARM(var, no) \
|
#define PROP_INT_PARM(var, no) \
|
||||||
int var = params[(no)+1].i;
|
int var = params[(no)+1].i;
|
||||||
|
|
||||||
|
@ -375,44 +387,6 @@ int MatchString (const char *in, const char **strings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int EvalExpressionI (DWORD x, AActor *self);
|
|
||||||
int EvalExpressionCol (DWORD x, AActor *self);
|
|
||||||
FSoundID EvalExpressionSnd (DWORD x, AActor *self);
|
|
||||||
double EvalExpressionF (DWORD x, AActor *self);
|
|
||||||
fixed_t EvalExpressionFix (DWORD x, AActor *self);
|
|
||||||
FState *EvalExpressionState (DWORD x, AActor *self);
|
|
||||||
const PClass *EvalExpressionClass (DWORD x, AActor *self);
|
|
||||||
FName EvalExpressionName (DWORD x, AActor *self);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
#define ACTION_PARAM_START(count)
|
|
||||||
|
|
||||||
#define ACTION_PARAM_INT(var, i) \
|
|
||||||
int var = EvalExpressionI(ParameterIndex+i, self);
|
|
||||||
#define ACTION_PARAM_BOOL(var,i) \
|
|
||||||
bool var = !!EvalExpressionI(ParameterIndex+i, self);
|
|
||||||
#define ACTION_PARAM_FIXED(var,i) \
|
|
||||||
fixed_t var = EvalExpressionFix(ParameterIndex+i, self);
|
|
||||||
#define ACTION_PARAM_FLOAT(var,i) \
|
|
||||||
float var = float(EvalExpressionF(ParameterIndex+i, self));
|
|
||||||
#define ACTION_PARAM_DOUBLE(var,i) \
|
|
||||||
double var = EvalExpressionF(ParameterIndex+i, self);
|
|
||||||
#define ACTION_PARAM_CLASS(var,i) \
|
|
||||||
const PClass *var = EvalExpressionClass(ParameterIndex+i, self);
|
|
||||||
#define ACTION_PARAM_STATE(var,i) \
|
|
||||||
FState *var = EvalExpressionState(ParameterIndex+i, stateowner);
|
|
||||||
#define ACTION_PARAM_COLOR(var,i) \
|
|
||||||
PalEntry var = EvalExpressionCol(ParameterIndex+i, self);
|
|
||||||
#define ACTION_PARAM_SOUND(var,i) \
|
|
||||||
FSoundID var = EvalExpressionSnd(ParameterIndex+i, self);
|
|
||||||
#define ACTION_PARAM_STRING(var,i) \
|
|
||||||
const char *var = EvalExpressionName(ParameterIndex+i, self);
|
|
||||||
#define ACTION_PARAM_NAME(var,i) \
|
|
||||||
FName var = EvalExpressionName(ParameterIndex+i, self);
|
|
||||||
#define ACTION_PARAM_ANGLE(var,i) \
|
|
||||||
angle_t var = angle_t(EvalExpressionF(ParameterIndex+i, self)*ANGLE_90/90.f);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define ACTION_SET_RESULT(v) do { if (numret > 0) { assert(ret != NULL); ret->SetInt(v); numret = 1; } } while(0)
|
#define ACTION_SET_RESULT(v) do { if (numret > 0) { assert(ret != NULL); ret->SetInt(v); numret = 1; } } while(0)
|
||||||
|
|
||||||
// Checks to see what called the current action function
|
// Checks to see what called the current action function
|
||||||
|
|
|
@ -904,6 +904,28 @@ public:
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
class FxDamageValue : public FxExpression
|
||||||
|
{
|
||||||
|
FxExpression *val;
|
||||||
|
bool Calculated;
|
||||||
|
VMScriptFunction *MyFunction;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
FxDamageValue(FxExpression *v, bool calc);
|
||||||
|
~FxDamageValue();
|
||||||
|
FxExpression *Resolve(FCompileContext&);
|
||||||
|
|
||||||
|
ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
|
VMScriptFunction *GetFunction() const { return MyFunction; }
|
||||||
|
void SetFunction(VMScriptFunction *func) { MyFunction = func; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
FxExpression *ParseExpression (FScanner &sc, PClassActor *cls);
|
FxExpression *ParseExpression (FScanner &sc, PClassActor *cls);
|
||||||
|
|
|
@ -79,7 +79,7 @@ DEFINE_MEMBER_VARIABLE_ALIAS(momy, vely, AActor)
|
||||||
DEFINE_MEMBER_VARIABLE_ALIAS(momz, velz, AActor)
|
DEFINE_MEMBER_VARIABLE_ALIAS(momz, velz, AActor)
|
||||||
DEFINE_MEMBER_VARIABLE(scaleX, AActor)
|
DEFINE_MEMBER_VARIABLE(scaleX, AActor)
|
||||||
DEFINE_MEMBER_VARIABLE(scaleY, AActor)
|
DEFINE_MEMBER_VARIABLE(scaleY, AActor)
|
||||||
DEFINE_MEMBER_VARIABLE(Damage, AActor)
|
//DEFINE_MEMBER_VARIABLE(Damage, AActor)
|
||||||
DEFINE_MEMBER_VARIABLE(Score, AActor)
|
DEFINE_MEMBER_VARIABLE(Score, AActor)
|
||||||
DEFINE_MEMBER_VARIABLE(accuracy, AActor)
|
DEFINE_MEMBER_VARIABLE(accuracy, AActor)
|
||||||
DEFINE_MEMBER_VARIABLE(stamina, AActor)
|
DEFINE_MEMBER_VARIABLE(stamina, AActor)
|
||||||
|
@ -120,89 +120,6 @@ static PSymbol *FindDecorateBuiltinFunction(FName funcname, VMNativeFunction::Na
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
// EvalExpression
|
|
||||||
// [GRB] Evaluates previously stored expression
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
|
|
||||||
int EvalExpressionI (DWORD xi, AActor *self)
|
|
||||||
{
|
|
||||||
FxExpression *x = StateParams.Get(xi);
|
|
||||||
if (x == NULL) return 0;
|
|
||||||
|
|
||||||
return x->EvalExpression (self).GetInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
int EvalExpressionCol (DWORD xi, AActor *self)
|
|
||||||
{
|
|
||||||
FxExpression *x = StateParams.Get(xi);
|
|
||||||
if (x == NULL) return 0;
|
|
||||||
|
|
||||||
return x->EvalExpression (self).GetColor();
|
|
||||||
}
|
|
||||||
|
|
||||||
FSoundID EvalExpressionSnd (DWORD xi, AActor *self)
|
|
||||||
{
|
|
||||||
FxExpression *x = StateParams.Get(xi);
|
|
||||||
if (x == NULL) return 0;
|
|
||||||
|
|
||||||
return x->EvalExpression (self).GetSoundID();
|
|
||||||
}
|
|
||||||
|
|
||||||
double EvalExpressionF (DWORD xi, AActor *self)
|
|
||||||
{
|
|
||||||
FxExpression *x = StateParams.Get(xi);
|
|
||||||
if (x == NULL) return 0;
|
|
||||||
|
|
||||||
return x->EvalExpression (self).GetFloat();
|
|
||||||
}
|
|
||||||
|
|
||||||
fixed_t EvalExpressionFix (DWORD xi, AActor *self)
|
|
||||||
{
|
|
||||||
FxExpression *x = StateParams.Get(xi);
|
|
||||||
if (x == NULL) return 0;
|
|
||||||
|
|
||||||
ExpVal val = x->EvalExpression (self);
|
|
||||||
|
|
||||||
switch (val.Type)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
case VAL_Int:
|
|
||||||
return val.Int << FRACBITS;
|
|
||||||
case VAL_Float:
|
|
||||||
return fixed_t(val.Float*FRACUNIT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FName EvalExpressionName (DWORD xi, AActor *self)
|
|
||||||
{
|
|
||||||
FxExpression *x = StateParams.Get(xi);
|
|
||||||
if (x == NULL) return 0;
|
|
||||||
|
|
||||||
return x->EvalExpression (self).GetName();
|
|
||||||
}
|
|
||||||
|
|
||||||
const PClass * EvalExpressionClass (DWORD xi, AActor *self)
|
|
||||||
{
|
|
||||||
FxExpression *x = StateParams.Get(xi);
|
|
||||||
if (x == NULL) return 0;
|
|
||||||
|
|
||||||
return x->EvalExpression (self).GetClass();
|
|
||||||
}
|
|
||||||
|
|
||||||
FState *EvalExpressionState (DWORD xi, AActor *self)
|
|
||||||
{
|
|
||||||
FxExpression *x = StateParams.Get(xi);
|
|
||||||
if (x == NULL) return 0;
|
|
||||||
|
|
||||||
return x->EvalExpression (self).GetState();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
@ -4025,6 +3942,64 @@ ExpEmit FxMultiNameState::Emit(VMFunctionBuilder *build)
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
FxDamageValue::FxDamageValue(FxExpression *v, bool calc)
|
||||||
|
: FxExpression(v->ScriptPosition)
|
||||||
|
{
|
||||||
|
val = v;
|
||||||
|
ValueType = VAL_Unknown;
|
||||||
|
Calculated = calc;
|
||||||
|
MyFunction = NULL;
|
||||||
|
|
||||||
|
if (!calc)
|
||||||
|
{
|
||||||
|
assert(v->isConstant() && "Non-calculated damage must be constant");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FxDamageValue::~FxDamageValue()
|
||||||
|
{
|
||||||
|
SAFE_DELETE(val);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
FxExpression *FxDamageValue::Resolve(FCompileContext &ctx)
|
||||||
|
{
|
||||||
|
CHECKRESOLVED();
|
||||||
|
SAFE_RESOLVE(val, ctx)
|
||||||
|
|
||||||
|
if (!val->ValueType.isNumeric())
|
||||||
|
{
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Numeric type expected");
|
||||||
|
delete this;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a highly-specialized "expression" type that emits a complete function.
|
||||||
|
ExpEmit FxDamageValue::Emit(VMFunctionBuilder *build)
|
||||||
|
{
|
||||||
|
if (val->isConstant())
|
||||||
|
{
|
||||||
|
build->EmitRetInt(0, false, val->EvalExpression(NULL).Int);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ExpEmit emitval = val->Emit(build);
|
||||||
|
assert(emitval.RegType == REGT_INT);
|
||||||
|
build->Emit(OP_RET, 0, REGT_INT | (emitval.Konst ? REGT_KONST : 0), emitval.RegNum);
|
||||||
|
}
|
||||||
|
build->Emit(OP_RETI, 1, 0x8000 | (int)Calculated);
|
||||||
|
|
||||||
|
return ExpEmit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -4096,38 +4071,6 @@ int FStateExpressions::Reserve(int num, PClassActor *cls)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void FStateExpressions::Set(int num, FxExpression *x, bool cloned)
|
|
||||||
{
|
|
||||||
if (num >= 0 && num < int(Size()))
|
|
||||||
{
|
|
||||||
assert(expressions[num].expr == NULL || expressions[num].cloned);
|
|
||||||
expressions[num].expr = x;
|
|
||||||
expressions[num].cloned = cloned;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void FStateExpressions::Copy(int dest, int src, int cnt)
|
|
||||||
{
|
|
||||||
for(int i=0; i<cnt; i++)
|
|
||||||
{
|
|
||||||
// For now set only a reference because these expressions may change when being resolved
|
|
||||||
expressions[dest+i].expr = (FxExpression*)intptr_t(src+i);
|
|
||||||
expressions[dest+i].cloned = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
int FStateExpressions::ResolveAll()
|
int FStateExpressions::ResolveAll()
|
||||||
{
|
{
|
||||||
int errorcount = 0;
|
int errorcount = 0;
|
||||||
|
|
|
@ -669,16 +669,26 @@ static bool ParsePropertyParams(FScanner &sc, FPropertyInfo *prop, AActor *defau
|
||||||
switch ((*p) & 223)
|
switch ((*p) & 223)
|
||||||
{
|
{
|
||||||
case 'X': // Expression in parentheses or number.
|
case 'X': // Expression in parentheses or number.
|
||||||
|
{
|
||||||
|
FxExpression *x = NULL;
|
||||||
|
|
||||||
if (sc.CheckString ("("))
|
if (sc.CheckString ("("))
|
||||||
{
|
{
|
||||||
FxExpression *x = ParseExpression(sc, bag.Info);
|
x = new FxDamageValue(new FxIntCast(ParseExpression(sc, bag.Info)), true);
|
||||||
conv.i = 0x40000000 | StateParams.Add(x, bag.Info, false);
|
|
||||||
params.Push(conv);
|
|
||||||
sc.MustGetStringName(")");
|
sc.MustGetStringName(")");
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
// fall through
|
else
|
||||||
|
{
|
||||||
|
sc.MustGetNumber();
|
||||||
|
if (sc.Number != 0)
|
||||||
|
{
|
||||||
|
x = new FxDamageValue(new FxConstant(sc.Number, bag.ScriptPosition), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
conv.exp = x;
|
||||||
|
params.Push(conv);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 'I':
|
case 'I':
|
||||||
sc.MustGetNumber();
|
sc.MustGetNumber();
|
||||||
|
|
|
@ -449,7 +449,7 @@ DEFINE_PROPERTY(painthreshold, I, Actor)
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
DEFINE_PROPERTY(damage, X, Actor)
|
DEFINE_PROPERTY(damage, X, Actor)
|
||||||
{
|
{
|
||||||
PROP_INT_PARM(id, 0);
|
PROP_EXP_PARM(id, 0);
|
||||||
|
|
||||||
// Damage can either be a single number, in which case it is subject
|
// Damage can either be a single number, in which case it is subject
|
||||||
// to the original damage calculation rules. Or, it can be an expression
|
// to the original damage calculation rules. Or, it can be an expression
|
||||||
|
@ -457,7 +457,9 @@ DEFINE_PROPERTY(damage, X, Actor)
|
||||||
// compatibility reasons, expressions must be enclosed within
|
// compatibility reasons, expressions must be enclosed within
|
||||||
// parentheses.
|
// parentheses.
|
||||||
|
|
||||||
defaults->Damage = id;
|
// Store this expression here for now. It will be converted to a function
|
||||||
|
// later once all actors have been processed.
|
||||||
|
defaults->Damage = (VMFunction *)id;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
|
@ -490,6 +490,27 @@ size_t VMFunctionBuilder::EmitLoadInt(int regnum, int value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
// VMFunctionBuilder :: EmitRetInt
|
||||||
|
//
|
||||||
|
// Returns an integer, using either an immediate value or a constant
|
||||||
|
// register, as appropriate.
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
size_t VMFunctionBuilder::EmitRetInt(int retnum, bool final, int value)
|
||||||
|
{
|
||||||
|
if (value >= -16384 && value <= 16383)
|
||||||
|
{
|
||||||
|
return Emit(OP_RETI, retnum, value | (final << 15));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Emit(OP_RETI, retnum, REGT_INT | REGT_KONST | (final ? REGT_FINAL : 0), GetConstantInt(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// VMFunctionBuilder :: Backpatch
|
// VMFunctionBuilder :: Backpatch
|
||||||
|
|
|
@ -37,6 +37,7 @@ public:
|
||||||
size_t Emit(int opcode, int opa, VM_SHALF opbc);
|
size_t Emit(int opcode, int opa, VM_SHALF opbc);
|
||||||
size_t Emit(int opcode, int opabc);
|
size_t Emit(int opcode, int opabc);
|
||||||
size_t EmitLoadInt(int regnum, int value);
|
size_t EmitLoadInt(int regnum, int value);
|
||||||
|
size_t EmitRetInt(int retnum, bool final, int value);
|
||||||
|
|
||||||
void Backpatch(size_t addr, size_t target);
|
void Backpatch(size_t addr, size_t target);
|
||||||
void BackpatchToHere(size_t addr);
|
void BackpatchToHere(size_t addr);
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#define RII16 MODE_AI | MODE_BCJOINT | MODE_BCIMMS
|
#define RII16 MODE_AI | MODE_BCJOINT | MODE_BCIMMS
|
||||||
#define I24 MODE_ABCJOINT
|
#define I24 MODE_ABCJOINT
|
||||||
#define I8 MODE_AIMMZ | MODE_BUNUSED | MODE_CUNUSED
|
#define I8 MODE_AIMMZ | MODE_BUNUSED | MODE_CUNUSED
|
||||||
|
#define I8I16 MODE_AIMMZ | MODE_BCIMMZ
|
||||||
#define __BCP MODE_AUNUSED | MODE_BCJOINT | MODE_BCPARAM
|
#define __BCP MODE_AUNUSED | MODE_BCJOINT | MODE_BCPARAM
|
||||||
#define RPI8 MODE_AP | MODE_BIMMZ | MODE_CUNUSED
|
#define RPI8 MODE_AP | MODE_BIMMZ | MODE_CUNUSED
|
||||||
#define KPI8 MODE_AKP | MODE_BIMMZ | MODE_CUNUSED
|
#define KPI8 MODE_AKP | MODE_BIMMZ | MODE_CUNUSED
|
||||||
|
@ -246,6 +247,22 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OP_RETI:
|
||||||
|
if (a == 0 && code[i].i16 & 0x8000)
|
||||||
|
{
|
||||||
|
col = printf_wrapper(out, "%d", (code[i].i16 << 17) >> 17);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
col = print_reg(out, 0, a, (mode & MODE_ATYPE) >> MODE_ASHIFT, 24, func);
|
||||||
|
col += print_reg(out, col, (code[i].i16 << 17) >> 17, MODE_IMMS, 16, func);
|
||||||
|
if (code[i].i16 & 0x8000)
|
||||||
|
{
|
||||||
|
col += printf_wrapper(out, " [final]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if ((mode & MODE_BCTYPE) == MODE_BCCAST)
|
if ((mode & MODE_BCTYPE) == MODE_BCCAST)
|
||||||
{
|
{
|
||||||
|
|
|
@ -593,6 +593,18 @@ begin:
|
||||||
return a < numret ? a + 1 : numret;
|
return a < numret ? a + 1 : numret;
|
||||||
}
|
}
|
||||||
NEXTOP;
|
NEXTOP;
|
||||||
|
OP(RETI):
|
||||||
|
assert(ret != NULL || numret == 0);
|
||||||
|
if (a < numret)
|
||||||
|
{
|
||||||
|
// Shifting by 17 to wipe out the final bit
|
||||||
|
ret[a].SetInt(((pc[-1].i16) << 17) >> 17);
|
||||||
|
}
|
||||||
|
if (pc[-1].i16 & 0x8000)
|
||||||
|
{
|
||||||
|
return a < numret ? a + 1 : numret;
|
||||||
|
}
|
||||||
|
NEXTOP;
|
||||||
OP(RESULT):
|
OP(RESULT):
|
||||||
// This instruction is just a placeholder to indicate where a return
|
// This instruction is just a placeholder to indicate where a return
|
||||||
// value should be stored. It does nothing on its own and should not
|
// value should be stored. It does nothing on its own and should not
|
||||||
|
|
|
@ -81,6 +81,7 @@ xx(TAIL, tail, RPI8), // Call+Ret in a single instruction
|
||||||
xx(TAIL_K, tail, KPI8),
|
xx(TAIL_K, tail, KPI8),
|
||||||
xx(RESULT, result, __BCP), // Result should go in register encoded in BC (in caller, after CALL)
|
xx(RESULT, result, __BCP), // Result should go in register encoded in BC (in caller, after CALL)
|
||||||
xx(RET, ret, I8BCP), // Copy value from register encoded in BC to return value A, possibly returning
|
xx(RET, ret, I8BCP), // Copy value from register encoded in BC to return value A, possibly returning
|
||||||
|
xx(RETI, reti, I8I16), // Copy immediate from BC to return value A, possibly returning
|
||||||
xx(TRY, try, I24), // When an exception is thrown, start searching for a handler at pc + ABC
|
xx(TRY, try, I24), // When an exception is thrown, start searching for a handler at pc + ABC
|
||||||
xx(UNTRY, untry, I8), // Pop A entries off the exception stack
|
xx(UNTRY, untry, I8), // Pop A entries off the exception stack
|
||||||
xx(THROW, throw, THROW), // A == 0: Throw exception object pB
|
xx(THROW, throw, THROW), // A == 0: Throw exception object pB
|
||||||
|
|
|
@ -41,7 +41,7 @@ ACTOR Actor native //: Thinker
|
||||||
native int tid;
|
native int tid;
|
||||||
native int TIDtoHate;
|
native int TIDtoHate;
|
||||||
native int waterlevel;
|
native int waterlevel;
|
||||||
native int damage;
|
//native int damage;
|
||||||
native fixed_t x;
|
native fixed_t x;
|
||||||
native fixed_t y;
|
native fixed_t y;
|
||||||
native fixed_t z;
|
native fixed_t z;
|
||||||
|
|
Loading…
Reference in a new issue