A_Explode now returns the number of actors damaged and can be used in expressions.

- Enemies that do not take damage in any way are not counted.
This commit is contained in:
Major Cooke 2016-08-08 13:01:43 -05:00 committed by Christoph Oelckers
parent ee7d933ed6
commit ec14dd94a7
5 changed files with 29 additions and 18 deletions

View file

@ -948,7 +948,8 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
bool forcedPain = false; bool forcedPain = false;
int fakeDamage = 0; int fakeDamage = 0;
int holdDamage = 0; int holdDamage = 0;
const int rawdamage = damage; const int rawdamage = damage;
const bool telefragDamage = (rawdamage >= TELEFRAG_DAMAGE);
if (damage < 0) damage = 0; if (damage < 0) damage = 0;
@ -962,7 +963,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
forcedPain = (MustForcePain(target, inflictor)); forcedPain = (MustForcePain(target, inflictor));
// Spectral targets only take damage from spectral projectiles. // Spectral targets only take damage from spectral projectiles.
if (target->flags4 & MF4_SPECTRAL && damage < TELEFRAG_DAMAGE) if (target->flags4 & MF4_SPECTRAL && !telefragDamage)
{ {
if (inflictor == NULL || !(inflictor->flags4 & MF4_SPECTRAL)) if (inflictor == NULL || !(inflictor->flags4 & MF4_SPECTRAL))
{ {
@ -987,7 +988,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
// different here. At any rate, invulnerable is being checked before type factoring, which is then being // different here. At any rate, invulnerable is being checked before type factoring, which is then being
// checked by player cheats/invul/buddha followed by monster buddha. This is inconsistent. Don't let the // checked by player cheats/invul/buddha followed by monster buddha. This is inconsistent. Don't let the
// original telefrag damage CHECK (rawdamage) be influenced by outside factors when looking at cheats/invul. // original telefrag damage CHECK (rawdamage) be influenced by outside factors when looking at cheats/invul.
if ((target->flags2 & MF2_INVULNERABLE) && (rawdamage < TELEFRAG_DAMAGE) && (!(flags & DMG_FORCED))) if ((target->flags2 & MF2_INVULNERABLE) && !telefragDamage && (!(flags & DMG_FORCED)))
{ // actor is invulnerable { // actor is invulnerable
if (target->player == NULL) if (target->player == NULL)
{ {
@ -1046,7 +1047,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
return -1; return -1;
} }
if ((rawdamage < TELEFRAG_DAMAGE) || (target->flags7 & MF7_LAXTELEFRAGDMG)) // TELEFRAG_DAMAGE may only be reduced with LAXTELEFRAGDMG or it may not guarantee its effect. if (!telefragDamage || (target->flags7 & MF7_LAXTELEFRAGDMG)) // TELEFRAG_DAMAGE may only be reduced with LAXTELEFRAGDMG or it may not guarantee its effect.
{ {
if (player && damage > 1) if (player && damage > 1)
{ {
@ -1214,19 +1215,19 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
target->IsTeammate (source)) target->IsTeammate (source))
{ {
//Use the original damage to check for telefrag amount. Don't let the now-amplified damagetypes do it. //Use the original damage to check for telefrag amount. Don't let the now-amplified damagetypes do it.
if (rawdamage < TELEFRAG_DAMAGE || (target->flags7 & MF7_LAXTELEFRAGDMG)) if (!telefragDamage || (target->flags7 & MF7_LAXTELEFRAGDMG))
{ // Still allow telefragging :-( { // Still allow telefragging :-(
damage = (int)(damage * level.teamdamage); damage = (int)(damage * level.teamdamage);
if (damage < 0) if (damage < 0)
{ {
return damage; return damage;
} }
else if (damage == 0) else if (damage == 0)
{ {
if (forcedPain) if (forcedPain)
{ {
goto dopain; goto dopain;
} }
else if (fakedPain) else if (fakedPain)
{ {
goto fakepain; goto fakepain;
@ -1256,7 +1257,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
if (!(flags & DMG_FORCED)) if (!(flags & DMG_FORCED))
{ {
// check the real player, not a voodoo doll here for invulnerability effects // check the real player, not a voodoo doll here for invulnerability effects
if ((rawdamage < TELEFRAG_DAMAGE && ((player->mo->flags2 & MF2_INVULNERABLE) || if ((!telefragDamage && ((player->mo->flags2 & MF2_INVULNERABLE) ||
(player->cheats & CF_GODMODE))) || (player->cheats & CF_GODMODE))) ||
(player->cheats & CF_GODMODE2) || (player->mo->flags5 & MF5_NODAMAGE)) (player->cheats & CF_GODMODE2) || (player->mo->flags5 & MF5_NODAMAGE))
//Absolutely no hurting if NODAMAGE is involved. Same for GODMODE2. //Absolutely no hurting if NODAMAGE is involved. Same for GODMODE2.
@ -1281,7 +1282,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
{ {
player->mo->Inventory->AbsorbDamage(damage, mod, newdam); player->mo->Inventory->AbsorbDamage(damage, mod, newdam);
} }
if ((rawdamage < TELEFRAG_DAMAGE) || (player->mo->flags7 & MF7_LAXTELEFRAGDMG)) //rawdamage is never modified. if (!telefragDamage || (player->mo->flags7 & MF7_LAXTELEFRAGDMG)) //rawdamage is never modified.
{ {
// if we are telefragging don't let the damage value go below that magic value. Some further checks would fail otherwise. // if we are telefragging don't let the damage value go below that magic value. Some further checks would fail otherwise.
damage = newdam; damage = newdam;
@ -1306,7 +1307,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
} }
} }
if (damage >= player->health && rawdamage < TELEFRAG_DAMAGE if (damage >= player->health && !telefragDamage
&& (G_SkillProperty(SKILLP_AutoUseHealth) || deathmatch) && (G_SkillProperty(SKILLP_AutoUseHealth) || deathmatch)
&& !player->morphTics) && !player->morphTics)
{ // Try to use some inventory health { // Try to use some inventory health
@ -1330,7 +1331,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
// but telefragging should still do enough damage to kill the player) // but telefragging should still do enough damage to kill the player)
// Ignore players that are already dead. // Ignore players that are already dead.
// [MC]Buddha2 absorbs telefrag damage, and anything else thrown their way. // [MC]Buddha2 absorbs telefrag damage, and anything else thrown their way.
if (!(flags & DMG_FORCED) && (((player->cheats & CF_BUDDHA2) || (((player->cheats & CF_BUDDHA) || (player->mo->flags7 & MF7_BUDDHA)) && (rawdamage < TELEFRAG_DAMAGE))) && (player->playerstate != PST_DEAD))) if (!(flags & DMG_FORCED) && (((player->cheats & CF_BUDDHA2) || (((player->cheats & CF_BUDDHA) || (player->mo->flags7 & MF7_BUDDHA)) && !telefragDamage)) && (player->playerstate != PST_DEAD)))
{ {
// If this is a voodoo doll we need to handle the real player as well. // If this is a voodoo doll we need to handle the real player as well.
player->mo->health = target->health = player->health = 1; player->mo->health = target->health = player->health = 1;
@ -1395,7 +1396,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
if (target->health <= 0) if (target->health <= 0)
{ {
//[MC]Buddha flag for monsters. //[MC]Buddha flag for monsters.
if (!(flags & DMG_FORCED) && ((target->flags7 & MF7_BUDDHA) && (rawdamage < TELEFRAG_DAMAGE) && ((inflictor == NULL || !(inflictor->flags7 & MF7_FOILBUDDHA)) && !(flags & DMG_FOILBUDDHA)))) if (!(flags & DMG_FORCED) && ((target->flags7 & MF7_BUDDHA) && !telefragDamage && ((inflictor == NULL || !(inflictor->flags7 & MF7_FOILBUDDHA)) && !(flags & DMG_FOILBUDDHA))))
{ //FOILBUDDHA or Telefrag damage must kill it. { //FOILBUDDHA or Telefrag damage must kill it.
target->health = 1; target->health = 1;
} }

View file

@ -392,7 +392,7 @@ enum
RADF_NODAMAGE = 8, RADF_NODAMAGE = 8,
RADF_THRUSTZ = 16, RADF_THRUSTZ = 16,
}; };
void P_RadiusAttack (AActor *spot, AActor *source, int damage, int distance, int P_RadiusAttack (AActor *spot, AActor *source, int damage, int distance,
FName damageType, int flags, int fulldamagedistance=0); FName damageType, int flags, int fulldamagedistance=0);
void P_DelSector_List(); void P_DelSector_List();

View file

@ -5245,11 +5245,11 @@ CUSTOM_CVAR(Float, splashfactor, 1.f, CVAR_SERVERINFO)
// //
//========================================================================== //==========================================================================
void P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bombdistance, FName bombmod, int P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bombdistance, FName bombmod,
int flags, int fulldamagedistance) int flags, int fulldamagedistance)
{ {
if (bombdistance <= 0) if (bombdistance <= 0)
return; return 0;
fulldamagedistance = clamp<int>(fulldamagedistance, 0, bombdistance - 1); fulldamagedistance = clamp<int>(fulldamagedistance, 0, bombdistance - 1);
double bombdistancefloat = 1. / (double)(bombdistance - fulldamagedistance); double bombdistancefloat = 1. / (double)(bombdistance - fulldamagedistance);
@ -5264,6 +5264,7 @@ void P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bo
bombsource = bombspot; bombsource = bombspot;
} }
int count = 0;
while ((it.Next(&cres))) while ((it.Next(&cres)))
{ {
AActor *thing = cres.thing; AActor *thing = cres.thing;
@ -5359,7 +5360,12 @@ void P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bo
int newdam = damage; int newdam = damage;
if (!(flags & RADF_NODAMAGE)) if (!(flags & RADF_NODAMAGE))
{
//[MC] Don't count actors saved by buddha if already at 1 health.
int prehealth = thing->health;
newdam = P_DamageMobj(thing, bombspot, bombsource, damage, bombmod); newdam = P_DamageMobj(thing, bombspot, bombsource, damage, bombmod);
if (thing->health < prehealth) count++;
}
else if (thing->player == NULL && (!(flags & RADF_NOIMPACTDAMAGE) && !(thing->flags7 & MF7_DONTTHRUST))) else if (thing->player == NULL && (!(flags & RADF_NOIMPACTDAMAGE) && !(thing->flags7 & MF7_DONTTHRUST)))
thing->flags2 |= MF2_BLASTED; thing->flags2 |= MF2_BLASTED;
@ -5425,12 +5431,16 @@ void P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bo
damage = int(damage * factor); damage = int(damage * factor);
if (damage > 0) if (damage > 0)
{ {
//[MC] Don't count actors saved by buddha if already at 1 health.
int prehealth = thing->health;
int newdam = P_DamageMobj(thing, bombspot, bombsource, damage, bombmod); int newdam = P_DamageMobj(thing, bombspot, bombsource, damage, bombmod);
P_TraceBleed(newdam > 0 ? newdam : damage, thing, bombspot); P_TraceBleed(newdam > 0 ? newdam : damage, thing, bombspot);
if (thing->health < prehealth) count++;
} }
} }
} }
} }
return count;
} }
//========================================================================== //==========================================================================

View file

@ -1414,13 +1414,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode)
} }
} }
P_RadiusAttack (self, self->target, damage, distance, self->DamageType, flags, fulldmgdistance); int count = P_RadiusAttack (self, self->target, damage, distance, self->DamageType, flags, fulldmgdistance);
P_CheckSplash(self, distance); P_CheckSplash(self, distance);
if (alert && self->target != NULL && self->target->player != NULL) if (alert && self->target != NULL && self->target->player != NULL)
{ {
P_NoiseAlert(self->target, self); P_NoiseAlert(self->target, self);
} }
return 0; ACTION_RETURN_INT(count);
} }
//========================================================================== //==========================================================================

View file

@ -253,7 +253,7 @@ ACTOR Actor native //: Thinker
action native A_Blast(int flags = 0, float strength = 255, float radius = 255, float speed = 20, class<Actor> blasteffect = "BlastEffect", sound blastsound = "BlastRadius"); action native A_Blast(int flags = 0, float strength = 255, float radius = 255, float speed = 20, class<Actor> blasteffect = "BlastEffect", sound blastsound = "BlastRadius");
action native A_RadiusThrust(int force = 128, int distance = -1, int flags = RTF_AFFECTSOURCE, int fullthrustdistance = 0); action native A_RadiusThrust(int force = 128, int distance = -1, int flags = RTF_AFFECTSOURCE, int fullthrustdistance = 0);
action native A_RadiusDamageSelf(int damage = 128, float distance = 128, int flags = 0, class<Actor> flashtype = "None"); action native A_RadiusDamageSelf(int damage = 128, float distance = 128, int flags = 0, class<Actor> flashtype = "None");
action native A_Explode(int damage = -1, int distance = -1, int flags = XF_HURTSOURCE, bool alert = false, int fulldamagedistance = 0, int nails = 0, int naildamage = 10, class<Actor> pufftype = "BulletPuff"); action native int A_Explode(int damage = -1, int distance = -1, int flags = XF_HURTSOURCE, bool alert = false, int fulldamagedistance = 0, int nails = 0, int naildamage = 10, class<Actor> pufftype = "BulletPuff");
action native A_Stop(); action native A_Stop();
action native A_Respawn(int flags = 1); action native A_Respawn(int flags = 1);
action native A_BarrelDestroy(); action native A_BarrelDestroy();