diff --git a/src/playsim/actor.h b/src/playsim/actor.h index 40be0c599..906fe2c1b 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -1524,9 +1524,13 @@ public: { return Z() + Height; } + double CenterOffset() const + { + return Height / 2; + } double Center() const { - return Z() + Height/2; + return Z() + CenterOffset(); } void SetZ(double newz, bool moving = true) { @@ -1603,6 +1607,11 @@ public: Vel.Y += speed * angle.Sin(); } + void Thrust(const DVector3& vel) + { + Vel += vel; + } + void Vel3DFromAngle(DAngle angle, DAngle pitch, double speed) { double cospitch = pitch.Cos(); diff --git a/src/playsim/p_local.h b/src/playsim/p_local.h index cde45f403..6d02d2a56 100644 --- a/src/playsim/p_local.h +++ b/src/playsim/p_local.h @@ -408,7 +408,8 @@ enum RADF_OLDRADIUSDAMAGE = 32, RADF_THRUSTLESS = 64, RADF_NOALLIES = 128, - RADF_CIRCULAR = 256 + RADF_CIRCULAR = 256, + RADF_CIRCULARTHRUST = 512, }; int P_GetRadiusDamage(AActor *self, AActor *thing, int damage, double distance, double fulldmgdistance, bool oldradiusdmg, bool circular); int P_RadiusAttack (AActor *spot, AActor *source, int damage, double distance, diff --git a/src/playsim/p_map.cpp b/src/playsim/p_map.cpp index af8df92a7..589204993 100644 --- a/src/playsim/p_map.cpp +++ b/src/playsim/p_map.cpp @@ -6236,24 +6236,44 @@ int P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, double if (!(thing->flags7 & MF7_DONTTHRUST)) { thrust = points * 0.5 / (double)thing->Mass; + if (bombsource == thing) { thrust *= selfthrustscale; } - vz = (thing->Center() - bombspot->Z()) * thrust; - if (bombsource != thing) + + if (flags & RADF_CIRCULARTHRUST) { - vz *= 0.5; + auto dir = bombspot->Vec3To(thing); + dir.Z += thing->CenterOffset() - bombspot->CenterOffset(); + + if (!dir.isZero()) + { + dir.MakeUnit(); + thing->Thrust(dir * thrust); + } } else { - vz *= 0.8; - } - thing->Thrust(bombspot->AngleTo(thing), thrust); - if (!(flags & RADF_NODAMAGE) || (flags & RADF_THRUSTZ)) - { - if (!(thing->Level->i_compatflags2 & COMPATF2_EXPLODE1) || (flags & RADF_THRUSTZ)) - thing->Vel.Z += vz; // this really doesn't work well + thing->Thrust(bombspot->AngleTo(thing), thrust); + + if (!(flags & RADF_NODAMAGE) || (flags & RADF_THRUSTZ)) + { + if (!(thing->Level->i_compatflags2 & COMPATF2_EXPLODE1) || (flags & RADF_THRUSTZ)) + { + vz = (thing->Center() - bombspot->Z()) * thrust; + if (bombsource != thing) + { + vz *= 0.5; + } + else + { + vz *= 0.8; + } + + thing->Vel.Z += vz; // this really doesn't work well + } + } } } } diff --git a/wadsrc/static/zscript/actors/attacks.zs b/wadsrc/static/zscript/actors/attacks.zs index db9da6f35..1965be0b1 100644 --- a/wadsrc/static/zscript/actors/attacks.zs +++ b/wadsrc/static/zscript/actors/attacks.zs @@ -609,6 +609,7 @@ extend class Actor if (flags & XF_THRUSTLESS) pflags |= RADF_THRUSTLESS; if (flags & XF_NOALLIES) pflags |= RADF_NOALLIES; if (flags & XF_CIRCULAR) pflags |= RADF_CIRCULAR; + if (flags & XF_CIRCULARTHRUST) pflags |= RADF_CIRCULARTHRUST; int count = RadiusAttack (target, damage, distance, damagetype, pflags, fulldamagedistance); if (!(flags & XF_NOSPLASH)) CheckSplash(distance); diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index f22204cbf..641d90a12 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -267,6 +267,7 @@ enum EExplodeFlags XF_THRUSTLESS = 64, XF_NOALLIES = 128, XF_CIRCULAR = 256, + XF_CIRCULARTHRUST = 512, }; // Flags for A_RadiusThrust @@ -276,6 +277,7 @@ enum ERadiusThrustFlags RTF_NOIMPACTDAMAGE = 2, RTF_NOTMISSILE = 4, RTF_THRUSTZ = 16, + RTF_CIRCULARTHRUST = 512, }; // Flags for A_RadiusDamageSelf @@ -1254,7 +1256,8 @@ enum RadiusDamageFlags RADF_OLDRADIUSDAMAGE = 32, RADF_THRUSTLESS = 64, RADF_NOALLIES = 128, - RADF_CIRCULAR = 256 + RADF_CIRCULAR = 256, + RADF_CIRCULARTHRUST = 512, }; enum IntermissionSequenceType