Added (XF/RADF)_CIRCULAR.

This flag makes explosions use a spherical radius, instead of a cubic one. Only took almost 30 years.
This commit is contained in:
inkoalawetrust 2023-01-07 07:07:14 +02:00 committed by Rachael Alexanderson
parent ca1f3ac580
commit 194f73a94b
6 changed files with 49 additions and 36 deletions

View file

@ -408,9 +408,10 @@ enum
RADF_THRUSTZ = 16, RADF_THRUSTZ = 16,
RADF_OLDRADIUSDAMAGE = 32, RADF_OLDRADIUSDAMAGE = 32,
RADF_THRUSTLESS = 64, RADF_THRUSTLESS = 64,
RADF_NOALLIES = 128 RADF_NOALLIES = 128,
RADF_CIRCULAR = 256
}; };
int P_GetRadiusDamage(AActor *self, AActor *thing, int damage, int distance, int fulldmgdistance, bool oldradiusdmg); int P_GetRadiusDamage(AActor *self, AActor *thing, int damage, int distance, int fulldmgdistance, bool oldradiusdmg, bool circular);
int 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 species = NAME_None); FName damageType, int flags, int fulldamagedistance=0, FName species = NAME_None);

View file

@ -5838,7 +5838,7 @@ int P_UsePuzzleItem(AActor *PuzzleItemUser, int PuzzleItemType)
//========================================================================== //==========================================================================
// //
// RADIUS ATTACK // RADIUS ATTACK
// // Most of the explosion code resides here. Except P_GeometryRadiusAttack().
// //
//========================================================================== //==========================================================================
@ -5864,7 +5864,7 @@ CUSTOM_CVAR(Float, splashfactor, 1.f, CVAR_SERVERINFO)
// Used by anything without OLDRADIUSDMG flag // Used by anything without OLDRADIUSDMG flag
//========================================================================== //==========================================================================
static double GetRadiusDamage(bool fromaction, AActor *bombspot, AActor *thing, int bombdamage, int bombdistance, int fulldamagedistance, bool thingbombsource) static double GetRadiusDamage(bool fromaction, AActor *bombspot, AActor *thing, int bombdamage, int bombdistance, int fulldamagedistance, bool thingbombsource, bool round)
{ {
// [RH] New code. The bounding box only covers the // [RH] New code. The bounding box only covers the
// height of the thing and not the height of the map. // height of the thing and not the height of the map.
@ -5876,6 +5876,8 @@ static double GetRadiusDamage(bool fromaction, AActor *bombspot, AActor *thing,
double bombdistancefloat = 1. / (double)(bombdistance - fulldamagedistance); double bombdistancefloat = 1. / (double)(bombdistance - fulldamagedistance);
double bombdamagefloat = (double)bombdamage; double bombdamagefloat = (double)bombdamage;
if (!round)
{
DVector2 vec = bombspot->Vec2To(thing); DVector2 vec = bombspot->Vec2To(thing);
dx = fabs(vec.X); dx = fabs(vec.X);
dy = fabs(vec.Y); dy = fabs(vec.Y);
@ -5912,6 +5914,12 @@ static double GetRadiusDamage(bool fromaction, AActor *bombspot, AActor *thing,
if (len < 0.f) if (len < 0.f)
len = 0.f; len = 0.f;
} }
}
//[inkoalwetrust]: Round explosions just use the actual distance between the source and victim.
else
{
len = bombspot->Distance3D (thing);
}
len = clamp<double>(len - (double)fulldamagedistance, 0, len); len = clamp<double>(len - (double)fulldamagedistance, 0, len);
points = bombdamagefloat * (1. - len * bombdistancefloat); points = bombdamagefloat * (1. - len * bombdistancefloat);
@ -5985,7 +5993,7 @@ static int GetOldRadiusDamage(bool fromaction, AActor *bombspot, AActor *thing,
// damage and not taking into account any damage reduction. // damage and not taking into account any damage reduction.
//========================================================================== //==========================================================================
int P_GetRadiusDamage(AActor *self, AActor *thing, int damage, int distance, int fulldmgdistance, bool oldradiusdmg) int P_GetRadiusDamage(AActor *self, AActor *thing, int damage, int distance, int fulldmgdistance, bool oldradiusdmg, bool circular)
{ {
if (!thing) if (!thing)
@ -6005,7 +6013,7 @@ int P_GetRadiusDamage(AActor *self, AActor *thing, int damage, int distance, int
const int newdam = oldradiusdmg const int newdam = oldradiusdmg
? GetOldRadiusDamage(true, self, thing, damage, distance, fulldmgdistance) ? GetOldRadiusDamage(true, self, thing, damage, distance, fulldmgdistance)
: int(GetRadiusDamage(true, self, thing, damage, distance, fulldmgdistance, false)); : int(GetRadiusDamage(true, self, thing, damage, distance, fulldmgdistance, false, circular));
return newdam; return newdam;
} }
@ -6075,8 +6083,8 @@ int P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bom
if ((species != NAME_None) && (thing->Species != species)) if ((species != NAME_None) && (thing->Species != species))
continue; continue;
//[inkoalawetrust] Don't harm actors friendly to the explosions' source. //[inkoalawetrust] Don't harm actors friendly to the explosions' source. But do harm the source.
if ((flags & RADF_NOALLIES) && bombsource->IsFriend(thing)) if ((flags & RADF_NOALLIES) && bombsource->IsFriend(thing) && !(thing == bombsource || thing == bombspot))
continue; continue;
if (bombsource && thing != bombsource && bombsource->player && P_ShouldPassThroughPlayer(bombsource, thing)) if (bombsource && thing != bombsource && bombsource->player && P_ShouldPassThroughPlayer(bombsource, thing))
@ -6094,7 +6102,7 @@ int P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bom
if ((flags & RADF_NODAMAGE) || (!((bombspot->flags5 | thing->flags5) & MF5_OLDRADIUSDMG) && if ((flags & RADF_NODAMAGE) || (!((bombspot->flags5 | thing->flags5) & MF5_OLDRADIUSDMG) &&
!(flags & RADF_OLDRADIUSDAMAGE) && !(thing->Level->i_compatflags2 & COMPATF2_EXPLODE2))) !(flags & RADF_OLDRADIUSDAMAGE) && !(thing->Level->i_compatflags2 & COMPATF2_EXPLODE2)))
{ {
double points = GetRadiusDamage(false, bombspot, thing, bombdamage, bombdistance, fulldamagedistance, bombsource == thing); double points = GetRadiusDamage(false, bombspot, thing, bombdamage, bombdistance, fulldamagedistance, bombsource == thing,!!(flags & RADF_CIRCULAR));
double check = int(points) * bombdamage; double check = int(points) * bombdamage;
// points and bombdamage should be the same sign (the double cast of 'points' is needed to prevent overflows and incorrect values slipping through.) // points and bombdamage should be the same sign (the double cast of 'points' is needed to prevent overflows and incorrect values slipping through.)
if ((check > 0 || (check == 0 && bombspot->flags7 & MF7_FORCEZERORADIUSDMG)) && P_CheckSight(thing, bombspot, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY)) if ((check > 0 || (check == 0 && bombspot->flags7 & MF7_FORCEZERORADIUSDMG)) && P_CheckSight(thing, bombspot, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))

View file

@ -1302,7 +1302,8 @@ DEFINE_ACTION_FUNCTION_NATIVE(AActor, GetRadiusDamage, P_GetRadiusDamage)
PARAM_INT(distance); PARAM_INT(distance);
PARAM_INT(fulldmgdistance); PARAM_INT(fulldmgdistance);
PARAM_BOOL(oldradiusdmg); PARAM_BOOL(oldradiusdmg);
ACTION_RETURN_INT(P_GetRadiusDamage(self, thing, damage, distance, fulldmgdistance, oldradiusdmg)); PARAM_BOOL(circular);
ACTION_RETURN_INT(P_GetRadiusDamage(self, thing, damage, distance, fulldmgdistance, oldradiusdmg, circular));
} }
static int RadiusAttack(AActor *self, AActor *bombsource, int bombdamage, int bombdistance, int damagetype, int flags, int fulldamagedistance, int species) static int RadiusAttack(AActor *self, AActor *bombsource, int bombdamage, int bombdistance, int damagetype, int flags, int fulldamagedistance, int species)

View file

@ -1187,7 +1187,7 @@ class Actor : Thinker native
native void A_CustomComboAttack(class<Actor> missiletype, double spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true); native void A_CustomComboAttack(class<Actor> missiletype, double spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true);
native void A_Burst(class<Actor> chunktype); native void A_Burst(class<Actor> chunktype);
native void A_RadiusDamageSelf(int damage = 128, double distance = 128, int flags = 0, class<Actor> flashtype = null); native void A_RadiusDamageSelf(int damage = 128, double distance = 128, int flags = 0, class<Actor> flashtype = null);
native int GetRadiusDamage(Actor thing, int damage, int distance, int fulldmgdistance = 0, bool oldradiusdmg = false); native int GetRadiusDamage(Actor thing, int damage, int distance, int fulldmgdistance = 0, bool oldradiusdmg = false, bool circular = false);
native int RadiusAttack(Actor bombsource, int bombdamage, int bombdistance, Name bombmod = 'none', int flags = RADF_HURTSOURCE, int fulldamagedistance = 0, name species = "None"); native int RadiusAttack(Actor bombsource, int bombdamage, int bombdistance, Name bombmod = 'none', int flags = RADF_HURTSOURCE, int fulldamagedistance = 0, name species = "None");
native void A_Respawn(int flags = 1); native void A_Respawn(int flags = 1);

View file

@ -608,6 +608,7 @@ extend class Actor
if (flags & XF_THRUSTZ) pflags |= RADF_THRUSTZ; if (flags & XF_THRUSTZ) pflags |= RADF_THRUSTZ;
if (flags & XF_THRUSTLESS) pflags |= RADF_THRUSTLESS; if (flags & XF_THRUSTLESS) pflags |= RADF_THRUSTLESS;
if (flags & XF_NOALLIES) pflags |= RADF_NOALLIES; if (flags & XF_NOALLIES) pflags |= RADF_NOALLIES;
if (flags & XF_CIRCULAR) pflags |= RADF_CIRCULAR;
int count = RadiusAttack (target, damage, distance, damagetype, pflags, fulldamagedistance); int count = RadiusAttack (target, damage, distance, damagetype, pflags, fulldamagedistance);
if (!(flags & XF_NOSPLASH)) CheckSplash(distance); if (!(flags & XF_NOSPLASH)) CheckSplash(distance);

View file

@ -263,6 +263,7 @@ enum EExplodeFlags
XF_THRUSTZ = 32, XF_THRUSTZ = 32,
XF_THRUSTLESS = 64, XF_THRUSTLESS = 64,
XF_NOALLIES = 128, XF_NOALLIES = 128,
XF_CIRCULAR = 256,
}; };
// Flags for A_RadiusThrust // Flags for A_RadiusThrust
@ -1230,7 +1231,8 @@ enum RadiusDamageFlags
RADF_THRUSTZ = 16, RADF_THRUSTZ = 16,
RADF_OLDRADIUSDAMAGE = 32, RADF_OLDRADIUSDAMAGE = 32,
RADF_THRUSTLESS = 64, RADF_THRUSTLESS = 64,
RADF_NOALLIES = 128 RADF_NOALLIES = 128,
RADF_CIRCULAR = 256
}; };
enum IntermissionSequenceType enum IntermissionSequenceType