by Gez » Thu Dec 04, 2014 3:03 pm
Yeah I'm not sure either why there are all these variants, but it's not really code redundancy. Behind the hood, they're all the same function.
Spoiler:
Code: Select all
//===========================================================================
//
// Common A_Damage handler
//
// A_Damage* (int amount, str damagetype, int flags)
// Damages the specified actor by the specified amount. Negative values heal.
//
//===========================================================================
enum DMSS
{
DMSS_FOILINVUL = 1,
DMSS_AFFECTARMOR = 2,
DMSS_KILL = 4,
DMSS_NOFACTOR = 8,
DMSS_FOILBUDDHA = 16,
DMSS_NOPROTECT = 32,
};
static void DoDamage(AActor *dmgtarget, AActor *self, int amount, FName DamageType, int flags)
{
int dmgFlags = 0;
if (flags & DMSS_FOILINVUL)
dmgFlags += DMG_FOILINVUL;
if (flags & DMSS_FOILBUDDHA)
dmgFlags += DMG_FOILBUDDHA;
if ((flags & DMSS_KILL) || (flags & DMSS_NOFACTOR)) //Kill implies NoFactor
dmgFlags += DMG_NO_FACTOR;
if (!(flags & DMSS_AFFECTARMOR) || (flags & DMSS_KILL)) //Kill overrides AffectArmor
dmgFlags += DMG_NO_ARMOR;
if (flags & DMSS_KILL) //Kill adds the value of the damage done to it. Allows for more controlled extreme death types.
amount += dmgtarget->health;
if (flags & DMSS_NOPROTECT) //Ignore PowerProtection.
dmgFlags += DMG_NO_PROTECT;
if (amount > 0)
P_DamageMobj(dmgtarget, self, self, amount, DamageType, dmgFlags); //Should wind up passing them through just fine.
else if (amount < 0)
{
amount = -amount;
P_GiveBody(dmgtarget, amount);
}
}
//===========================================================================
//
//
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSelf)
{
ACTION_PARAM_START(3);
ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1);
ACTION_PARAM_INT(flags, 2);
DoDamage(self, self, amount, DamageType, flags);
}
//===========================================================================
//
//
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTarget)
{
ACTION_PARAM_START(3);
ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1);
ACTION_PARAM_INT(flags, 2);
if (self->target != NULL) DoDamage(self->target, self, amount, DamageType, flags);
}
//===========================================================================
//
//
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTracer)
{
ACTION_PARAM_START(3);
ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1);
ACTION_PARAM_INT(flags, 2);
if (self->tracer != NULL) DoDamage(self->tracer, self, amount, DamageType, flags);
}
//===========================================================================
//
//
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageMaster)
{
ACTION_PARAM_START(3);
ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1);
ACTION_PARAM_INT(flags, 2);
if (self->master != NULL) DoDamage(self->master, self, amount, DamageType, flags);
}
//===========================================================================
//
//
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageChildren)
{
ACTION_PARAM_START(3);
ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1);
ACTION_PARAM_INT(flags, 2);
TThinkerIterator<AActor> it;
AActor * mo;
while ( (mo = it.Next()) )
{
if (mo->master == self) DoDamage(mo, self, amount, DamageType, flags);
}
}
//===========================================================================
//
//
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSiblings)
{
ACTION_PARAM_START(3);
ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1);
ACTION_PARAM_INT(flags, 2);
TThinkerIterator<AActor> it;
AActor * mo;
if (self->master != NULL)
{
while ((mo = it.Next()))
{
if (mo->master == self->master && mo != self) DoDamage(mo, self, amount, DamageType, flags);
}
}
}
See? Only _Siblings and _Children actually have some logic on their own, so as to iterate over the multiple valid targets. Having just one A_Damage function wouldn't really reduce actual code bloat.
Yeah I'm not sure either why there are all these variants, but it's not really code redundancy. Behind the hood, they're all the same function.
[spoiler][code]//===========================================================================
//
// Common A_Damage handler
//
// A_Damage* (int amount, str damagetype, int flags)
// Damages the specified actor by the specified amount. Negative values heal.
//
//===========================================================================
enum DMSS
{
DMSS_FOILINVUL = 1,
DMSS_AFFECTARMOR = 2,
DMSS_KILL = 4,
DMSS_NOFACTOR = 8,
DMSS_FOILBUDDHA = 16,
DMSS_NOPROTECT = 32,
};
static void DoDamage(AActor *dmgtarget, AActor *self, int amount, FName DamageType, int flags)
{
int dmgFlags = 0;
if (flags & DMSS_FOILINVUL)
dmgFlags += DMG_FOILINVUL;
if (flags & DMSS_FOILBUDDHA)
dmgFlags += DMG_FOILBUDDHA;
if ((flags & DMSS_KILL) || (flags & DMSS_NOFACTOR)) //Kill implies NoFactor
dmgFlags += DMG_NO_FACTOR;
if (!(flags & DMSS_AFFECTARMOR) || (flags & DMSS_KILL)) //Kill overrides AffectArmor
dmgFlags += DMG_NO_ARMOR;
if (flags & DMSS_KILL) //Kill adds the value of the damage done to it. Allows for more controlled extreme death types.
amount += dmgtarget->health;
if (flags & DMSS_NOPROTECT) //Ignore PowerProtection.
dmgFlags += DMG_NO_PROTECT;
if (amount > 0)
P_DamageMobj(dmgtarget, self, self, amount, DamageType, dmgFlags); //Should wind up passing them through just fine.
else if (amount < 0)
{
amount = -amount;
P_GiveBody(dmgtarget, amount);
}
}
//===========================================================================
//
//
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSelf)
{
ACTION_PARAM_START(3);
ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1);
ACTION_PARAM_INT(flags, 2);
DoDamage(self, self, amount, DamageType, flags);
}
//===========================================================================
//
//
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTarget)
{
ACTION_PARAM_START(3);
ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1);
ACTION_PARAM_INT(flags, 2);
if (self->target != NULL) DoDamage(self->target, self, amount, DamageType, flags);
}
//===========================================================================
//
//
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTracer)
{
ACTION_PARAM_START(3);
ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1);
ACTION_PARAM_INT(flags, 2);
if (self->tracer != NULL) DoDamage(self->tracer, self, amount, DamageType, flags);
}
//===========================================================================
//
//
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageMaster)
{
ACTION_PARAM_START(3);
ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1);
ACTION_PARAM_INT(flags, 2);
if (self->master != NULL) DoDamage(self->master, self, amount, DamageType, flags);
}
//===========================================================================
//
//
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageChildren)
{
ACTION_PARAM_START(3);
ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1);
ACTION_PARAM_INT(flags, 2);
TThinkerIterator<AActor> it;
AActor * mo;
while ( (mo = it.Next()) )
{
if (mo->master == self) DoDamage(mo, self, amount, DamageType, flags);
}
}
//===========================================================================
//
//
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSiblings)
{
ACTION_PARAM_START(3);
ACTION_PARAM_INT(amount, 0);
ACTION_PARAM_NAME(DamageType, 1);
ACTION_PARAM_INT(flags, 2);
TThinkerIterator<AActor> it;
AActor * mo;
if (self->master != NULL)
{
while ((mo = it.Next()))
{
if (mo->master == self->master && mo != self) DoDamage(mo, self, amount, DamageType, flags);
}
}
}
[/code][/spoiler]
See? Only _Siblings and _Children actually have some logic on their own, so as to iterate over the multiple valid targets. Having just one A_Damage function wouldn't really reduce actual code bloat.