diff --git a/src/playsim/a_sharedglobal.h b/src/playsim/a_sharedglobal.h index 3c86aa109..466ec5c60 100644 --- a/src/playsim/a_sharedglobal.h +++ b/src/playsim/a_sharedglobal.h @@ -116,6 +116,7 @@ enum QF_GROUNDONLY = 1 << 7, QF_AFFECTACTORS = 1 << 8, QF_SHAKEONLY = 1 << 9, + QF_DAMAGEFALLOFF = 1 << 10, }; struct FQuakeJiggers @@ -134,8 +135,8 @@ class DEarthquake : public DThinker public: static const int DEFAULT_STAT = STAT_EARTHQUAKE; void Construct(AActor *center, double intensityX, double intensityY, double intensityZ, int duration, - int damrad, int tremrad, FSoundID quakesfx, int flags, - double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint, double rollIntensity, double rollWave); + int damrad, int tremrad, FSoundID quakesfx, int flags, + double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint, double rollIntensity, double rollWave, double damageMultiplier, double thrustMultiplier, int damage); void Serialize(FSerializer &arc); void Tick (); @@ -150,11 +151,13 @@ public: double m_Falloff; int m_Highpoint, m_MiniCount; double m_RollIntensity, m_RollWave; + double m_DamageMultiplier, m_ThrustMultiplier; + int m_Damage; double GetModIntensity(double intensity, bool fake = false) const; double GetModWave(double ticFrac, double waveMultiplier) const; - double GetFalloff(double dist) const; - void DoQuakeDamage(DEarthquake *quake, AActor *victim) const; + double GetFalloff(double dist, double radius) const; + void DoQuakeDamage(DEarthquake *quake, AActor *victim, bool falloff) const; static int StaticGetQuakeIntensities(double ticFrac, AActor *viewer, FQuakeJiggers &jiggers); }; diff --git a/src/playsim/mapthinkers/a_quake.cpp b/src/playsim/mapthinkers/a_quake.cpp index 35e979a49..34c750f7a 100644 --- a/src/playsim/mapthinkers/a_quake.cpp +++ b/src/playsim/mapthinkers/a_quake.cpp @@ -33,6 +33,7 @@ #include "d_player.h" #include "r_utility.h" #include "g_levellocals.h" +#include static FRandom pr_quake ("Quake"); @@ -51,7 +52,7 @@ IMPLEMENT_POINTERS_END void DEarthquake::Construct(AActor *center, double intensityX, double intensityY, double intensityZ, int duration, int damrad, int tremrad, FSoundID quakesound, int flags, double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint, - double rollIntensity, double rollWave) + double rollIntensity, double rollWave, double damageMultiplier, double thrustMultiplier, int damage) { m_QuakeSFX = quakesound; m_Spot = center; @@ -68,6 +69,9 @@ void DEarthquake::Construct(AActor *center, double intensityX, double intensityY m_MiniCount = highpoint; m_RollIntensity = rollIntensity; m_RollWave = rollWave; + m_DamageMultiplier = damageMultiplier; + m_ThrustMultiplier = thrustMultiplier; + m_Damage = damage; } //========================================================================== @@ -93,13 +97,16 @@ void DEarthquake::Serialize(FSerializer &arc) ("minicount", m_MiniCount) ("rollintensity", m_RollIntensity) ("rollwave", m_RollWave); + ("damagemultiplier", m_DamageMultiplier); + ("thrustmultiplier", m_ThrustMultiplier); + ("damage", m_Damage); } //========================================================================== // // DEarthquake :: Tick // -// Deals damage to any players near the earthquake and makes sure it's +// Deals damage to any actors near the earthquake and makes sure it's // making noise. // //========================================================================== @@ -123,16 +130,17 @@ void DEarthquake::Tick () { if (m_Flags & QF_AFFECTACTORS) { - auto iterator = m_Spot->Level->GetThinkerIterator(); - AActor* mo = nullptr; + FPortalGroupArray check(FPortalGroupArray::PGA_Full3d); + FMultiBlockThingsIterator it(check,m_Spot,m_DamageRadius,false); + FMultiBlockThingsIterator::CheckResult cres; - while ((mo = iterator.Next()) != NULL) + while (it.Next(&cres)) { - if (mo == m_Spot) //Ignore the earthquake origin. + AActor *mo = cres.thing; + if (mo == nullptr || mo == m_Spot) //Ignore null references and the earthquake origin. continue; - - DoQuakeDamage(this, mo); + DoQuakeDamage(this, mo, !!(m_Flags & QF_DAMAGEFALLOFF)); } } else @@ -142,7 +150,7 @@ void DEarthquake::Tick () if (Level->PlayerInGame(i) && !(Level->Players[i]->cheats & CF_NOCLIP)) { AActor* victim = Level->Players[i]->mo; - DoQuakeDamage(this, victim); + DoQuakeDamage(this, victim, !!(m_Flags & QF_DAMAGEFALLOFF)); } } } @@ -168,26 +176,37 @@ void DEarthquake::Tick () // //========================================================================== -void DEarthquake::DoQuakeDamage(DEarthquake *quake, AActor *victim) const +void DEarthquake::DoQuakeDamage(DEarthquake *quake, AActor *victim, bool falloff) const { double dist; + double thrustfalloff; + int damage; if (!quake || !victim) return; dist = quake->m_Spot->Distance2D(victim, true); + thrustfalloff = falloff ? GetFalloff(dist, m_DamageRadius) : 1.0; // Check if in damage radius if (dist < m_DamageRadius && victim->Z() <= victim->floorz) { if (!(quake->m_Flags & QF_SHAKEONLY) && pr_quake() < 50) { - P_DamageMobj(victim, NULL, NULL, pr_quake.HitDice(1), NAME_Quake); + if (m_Damage < 1) + damage = falloff ? pr_quake.HitDice(1) * GetFalloff(dist, m_DamageRadius) * m_DamageMultiplier : pr_quake.HitDice(1) * m_DamageMultiplier; + //[inkoalawetrust] Do the exact specified damage. + else + damage = falloff ? m_Damage * GetFalloff(dist, m_DamageRadius) * m_DamageMultiplier : m_Damage * m_DamageMultiplier; + + damage = damage < 1 ? 1 : damage; //Do at least a tiny bit of damage when in radius. + + P_DamageMobj(victim, NULL, NULL, damage, NAME_Quake); } - // Thrust player or thrustable actor around - if (victim->player || !(victim->flags7 & MF7_DONTTHRUST)) + // Thrust pushable actor around + if (!(victim->flags7 & MF7_DONTTHRUST) && m_ThrustMultiplier > 0) { DAngle an = victim->Angles.Yaw + DAngle::fromDeg(pr_quake()); - victim->Vel.X += m_Intensity.X * an.Cos() * 0.5; - victim->Vel.Y += m_Intensity.Y * an.Sin() * 0.5; + victim->Vel.X += m_Intensity.X * an.Cos() * m_ThrustMultiplier * thrustfalloff; + victim->Vel.Y += m_Intensity.Y * an.Sin() * m_ThrustMultiplier * thrustfalloff; } } return; @@ -285,19 +304,19 @@ double DEarthquake::GetModIntensity(double intensity, bool fake) const // // DEarthquake :: GetFalloff // -// Given the distance of the player from the quake, find the multiplier. +// Given the distance of the actor from the quake, find the multiplier. // //========================================================================== -double DEarthquake::GetFalloff(double dist) const +double DEarthquake::GetFalloff(double dist, double radius) const { - if ((dist < m_Falloff) || (m_Falloff >= m_TremorRadius) || (m_Falloff <= 0) || (m_TremorRadius - m_Falloff <= 0)) - { //Player inside the minimum falloff range, or safety check kicked in. + if ((dist < m_Falloff) || (m_Falloff >= radius) || (m_Falloff <= 0) || (radius - m_Falloff <= 0)) + { //Actor inside the minimum falloff range, or safety check kicked in. return 1.; } - else if ((dist > m_Falloff) && (dist < m_TremorRadius)) - { //Player inside the radius, and outside the min distance for falloff. - double tremorsize = m_TremorRadius - m_Falloff; + else if ((dist > m_Falloff) && (dist < radius)) + { //Actor inside the radius, and outside the min distance for falloff. + double tremorsize = radius - m_Falloff; assert(tremorsize > 0); return (1. - ((dist - m_Falloff) / tremorsize)); } @@ -341,7 +360,7 @@ int DEarthquake::StaticGetQuakeIntensities(double ticFrac, AActor *victim, FQuak if (dist < quake->m_TremorRadius) { ++count; - const double falloff = quake->GetFalloff(dist); + const double falloff = quake->GetFalloff(dist, quake->m_TremorRadius); const double r = quake->GetModIntensity(quake->m_RollIntensity); const double strength = quake->GetModIntensity(1.0, true); DVector3 intensity; @@ -411,7 +430,7 @@ int DEarthquake::StaticGetQuakeIntensities(double ticFrac, AActor *victim, FQuak bool P_StartQuakeXYZ(FLevelLocals *Level, AActor *activator, int tid, double intensityX, double intensityY, double intensityZ, int duration, int damrad, int tremrad, FSoundID quakesfx, int flags, double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint, - double rollIntensity, double rollWave) + double rollIntensity, double rollWave, double damageMultiplier, double thrustMultiplier, int damage) { AActor *center; bool res = false; @@ -425,7 +444,7 @@ bool P_StartQuakeXYZ(FLevelLocals *Level, AActor *activator, int tid, double int if (activator != NULL) { Level->CreateThinker(activator, intensityX, intensityY, intensityZ, duration, damrad, tremrad, - quakesfx, flags, waveSpeedX, waveSpeedY, waveSpeedZ, falloff, highpoint, rollIntensity, rollWave); + quakesfx, flags, waveSpeedX, waveSpeedY, waveSpeedZ, falloff, highpoint, rollIntensity, rollWave, damageMultiplier, thrustMultiplier, damage); return true; } } @@ -436,14 +455,14 @@ bool P_StartQuakeXYZ(FLevelLocals *Level, AActor *activator, int tid, double int { res = true; Level->CreateThinker(center, intensityX, intensityY, intensityZ, duration, damrad, tremrad, - quakesfx, flags, waveSpeedX, waveSpeedY, waveSpeedZ, falloff, highpoint, rollIntensity, rollWave); + quakesfx, flags, waveSpeedX, waveSpeedY, waveSpeedZ, falloff, highpoint, rollIntensity, rollWave, damageMultiplier, thrustMultiplier, damage); } } return res; } -bool P_StartQuake(FLevelLocals *Level, AActor *activator, int tid, double intensity, int duration, int damrad, int tremrad, FSoundID quakesfx) +bool P_StartQuake(FLevelLocals * Level, AActor * activator, int tid, double intensity, int duration, int damrad, int tremrad, FSoundID quakesfx) { //Maintains original behavior by passing 0 to intensityZ, flags, and everything else after QSFX. - return P_StartQuakeXYZ(Level, activator, tid, intensity, intensity, 0, duration, damrad, tremrad, quakesfx, 0, 0, 0, 0, 0, 0, 0, 0); + return P_StartQuakeXYZ(Level, activator, tid, intensity, intensity, 0, duration, damrad, tremrad, quakesfx, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, 0.5, 0); } diff --git a/src/playsim/p_acs.cpp b/src/playsim/p_acs.cpp index ff97c7484..429fe1b69 100644 --- a/src/playsim/p_acs.cpp +++ b/src/playsim/p_acs.cpp @@ -6243,7 +6243,10 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) argCount > 12 ? args[12] : 0, argCount > 13 ? args[13] : 0, argCount > 14 ? ACSToDouble(args[14]) : 0, - argCount > 15 ? ACSToDouble(args[15]) : 0); + argCount > 15 ? ACSToDouble(args[15]) : 0, + argCount > 16 ? ACSToDouble(args[16]) : 1.0, + argCount > 17 ? ACSToDouble(args[17]) : 0.5, + argCount > 18 ? args[18] : 0); } case ACSF_SetLineActivation: diff --git a/src/playsim/p_actionfunctions.cpp b/src/playsim/p_actionfunctions.cpp index 690cbfcc1..6fb1a6768 100644 --- a/src/playsim/p_actionfunctions.cpp +++ b/src/playsim/p_actionfunctions.cpp @@ -3367,8 +3367,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_QuakeEx) PARAM_INT(highpoint); PARAM_FLOAT(rollIntensity); PARAM_FLOAT(rollWave); + PARAM_FLOAT(damageMultiplier); + PARAM_FLOAT(thrustMultiplier); + PARAM_INT(damage); P_StartQuakeXYZ(self->Level, self, 0, intensityX, intensityY, intensityZ, duration, damrad, tremrad, sound, flags, mulWaveX, mulWaveY, mulWaveZ, falloff, highpoint, - rollIntensity, rollWave); + rollIntensity, rollWave, damageMultiplier, thrustMultiplier, damage); return 0; } diff --git a/src/playsim/p_spec.h b/src/playsim/p_spec.h index a0918da91..ff0095eea 100644 --- a/src/playsim/p_spec.h +++ b/src/playsim/p_spec.h @@ -164,7 +164,7 @@ void P_TerminateScript (FLevelLocals *Level, int script, const char *map); // // [RH] p_quake.c // -bool P_StartQuakeXYZ(FLevelLocals *Level, AActor *activator, int tid, double intensityX, double intensityY, double intensityZ, int duration, int damrad, int tremrad, FSoundID quakesfx, int flags, double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint, double rollIntensity, double rollWave); +bool P_StartQuakeXYZ(FLevelLocals *Level, AActor *activator, int tid, double intensityX, double intensityY, double intensityZ, int duration, int damrad, int tremrad, FSoundID quakesfx, int flags, double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint, double rollIntensity, double rollWave, double damageMultiplier, double thrustMultiplier, int damage); bool P_StartQuake(FLevelLocals *Level, AActor *activator, int tid, double intensity, int duration, int damrad, int tremrad, FSoundID quakesfx); #endif diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index e2336a727..4e8e5977c 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -1222,7 +1222,7 @@ class Actor : Thinker native deprecated("2.3", "User variables are deprecated in ZScript. Actor variables are directly accessible") native void A_SetUserVarFloat(name varname, double value); deprecated("2.3", "User variables are deprecated in ZScript. Actor variables are directly accessible") native void A_SetUserArrayFloat(name varname, int index, double value); native void A_Quake(double intensity, int duration, int damrad, int tremrad, sound sfx = "world/quake"); - native void A_QuakeEx(double intensityX, double intensityY, double intensityZ, int duration, int damrad, int tremrad, sound sfx = "world/quake", int flags = 0, double mulWaveX = 1, double mulWaveY = 1, double mulWaveZ = 1, int falloff = 0, int highpoint = 0, double rollIntensity = 0, double rollWave = 0); + native void A_QuakeEx(double intensityX, double intensityY, double intensityZ, int duration, int damrad, int tremrad, sound sfx = "world/quake", int flags = 0, double mulWaveX = 1, double mulWaveY = 1, double mulWaveZ = 1, int falloff = 0, int highpoint = 0, double rollIntensity = 0, double rollWave = 0, double damageMultiplier = 1, double thrustMultiplier = 0.5, int damage = 0); action native void A_SetTics(int tics); native void A_DamageSelf(int amount, name damagetype = "none", int flags = 0, class filter = null, name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); native void A_DamageTarget(int amount, name damagetype = "none", int flags = 0, class filter = null, name species = "None", int src = AAPTR_DEFAULT, int inflict = AAPTR_DEFAULT); diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index bb2c8bd10..36eb8457e 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -655,6 +655,7 @@ enum EQuakeFlags QF_GROUNDONLY = 1 << 7, QF_AFFECTACTORS = 1 << 8, QF_SHAKEONLY = 1 << 9, + QF_DAMAGEFALLOFF = 1 << 10, }; // A_CheckProximity flags