- split Damage into two variables: DamageVal for the old constant and DamageFunc for the DECORATE function.

The way this was done was a major headache inducer, requiring reconstruction of the function each time the value was changed and in general made actor damage a major hassle.
There was a DECORATE wrapper to mimic the original behavior but this looked quite broken because it completely ignored the different semantics of both damage calculation types.
It also made it impossible to determine if damage was a function or a value.
This accessor has been reverted to what it should be, only returning the constant, which now is -1 for a damage function. I am sorry if this may break the odd mod out but a quick look over some DECORATE-heavy stuff showed that this was never combined in any of them so that accessing 'damage' in DECORATE code depended on an actual damage function.

To get proper damage, a future commit will add a DECORATE function which calls AActor::GetMissileDamage.
This commit is contained in:
Christoph Oelckers 2016-09-19 03:36:51 +02:00
commit f1ba19073f
16 changed files with 81 additions and 207 deletions

View file

@ -139,7 +139,7 @@ IMPLEMENT_POINTY_CLASS (AActor)
DECLARE_POINTER (LastHeard)
DECLARE_POINTER (master)
DECLARE_POINTER (Poisoner)
DECLARE_POINTER (Damage)
DECLARE_POINTER (DamageFunc)
DECLARE_POINTER (alternative)
END_POINTERS
@ -149,73 +149,6 @@ AActor::~AActor ()
// Use Destroy() instead.
}
//==========================================================================
//
// CalcDamageValue
//
// Given a script function, returns an integer to represent it in a
// savegame. This encoding is compatible with previous incarnations
// where damage was an integer.
//
// 0 : use null function
// 0x40000000 : use default function
// anything else : use function that returns this number
//
//==========================================================================
static int CalcDamageValue(VMFunction *func)
{
if (func == NULL)
{
return 0;
}
VMScriptFunction *sfunc = dyn_cast<VMScriptFunction>(func);
if (sfunc == NULL)
{
return 0x40000000;
}
VMOP *op = sfunc->Code;
// If the function was created by CreateDamageFunction(), extract
// the value used to create it and return that. Otherwise, return
// indicating to use the default function.
if (op->op == OP_RETI && op->a == 0)
{
return op->i16;
}
if (op->op == OP_RET && op->a == 0 && op->b == (REGT_INT | REGT_KONST))
{
return sfunc->KonstD[op->c];
}
return 0x40000000;
}
//==========================================================================
//
// UncalcDamageValue
//
// Given a damage integer, returns a script function for it.
//
//==========================================================================
static VMFunction *UncalcDamageValue(int dmg, VMFunction *def)
{
if (dmg == 0)
{
return NULL;
}
if ((dmg & 0xC0000000) == 0x40000000)
{
return def;
}
// Does the default version return this? If so, use it. Otherwise,
// create a new function.
if (CalcDamageValue(def) == dmg)
{
return def;
}
return CreateDamageFunction(dmg);
}
//==========================================================================
//
// AActor :: Serialize
@ -263,18 +196,16 @@ void AActor::Serialize(FArchive &arc)
<< projectilepassheight
<< Vel
<< tics
<< state;
if (arc.IsStoring())
<< state
<< DamageVal;
if (DamageVal == 0x40000000 || DamageVal == -1)
{
int dmg;
dmg = CalcDamageValue(Damage);
arc << dmg;
DamageVal = -1;
DamageFunc = GetDefault()->DamageFunc;
}
else
{
int dmg;
arc << dmg;
Damage = UncalcDamageValue(dmg, GetDefault()->Damage);
DamageFunc = nullptr;
}
P_SerializeTerrain(arc, floorterrain);
arc << projectileKickback
@ -2975,8 +2906,21 @@ CCMD(utid)
int AActor::GetMissileDamage (int mask, int add)
{
if (Damage == NULL)
if (DamageVal >= 0)
{
if (mask == 0)
{
return add * DamageVal;
}
else
{
return ((pr_missiledamage() & mask) + add) * DamageVal;
}
}
if (DamageFunc == nullptr)
{
// This should never happen
assert(false && "No damage function found");
return 0;
}
VMFrameStack stack;
@ -2988,22 +2932,11 @@ int AActor::GetMissileDamage (int mask, int add)
results[0].IntAt(&amount);
results[1].IntAt(&calculated);
if (stack.Call(Damage, &param, 1, results, 2) < 1)
if (stack.Call(DamageFunc, &param, 1, results, 2) < 1)
{ // No results
return 0;
}
if (calculated)
{
return amount;
}
else if (mask == 0)
{
return add * amount;
}
else
{
return ((pr_missiledamage() & mask) + add) * amount;
}
return amount;
}
void AActor::Howl ()
@ -3695,7 +3628,7 @@ void AActor::Tick ()
// still have missiles that go straight up and down through actors without
// damaging anything.
// (for backwards compatibility this must check for lack of damage function, not for zero damage!)
if ((flags & MF_MISSILE) && Vel.X == 0 && Vel.Y == 0 && Damage != NULL)
if ((flags & MF_MISSILE) && Vel.X == 0 && Vel.Y == 0 && !IsZeroDamage())
{
Vel.X = MinVel;
}