From 0d1fbcf65fdc7b66140277343fba5c43728ea7a2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 23 Mar 2016 14:03:10 +0100 Subject: [PATCH] - flattened the following commits by Major Cooke: * Added falloff parameter to A_QuakeEx. - Treated just like A_Explode's 'fullradiusdamage' parameter, where the quake will fall off from this distance on out to the edge. Default is 0, which means no falloff. - Credits to MaxED and Michaelis for helping. * - Added HighPoint parameter to QuakeEx. - Allows fine tuning of where the quake's maximum or minimum occurs, in tics. This must be a range between [1, duration). - For up or down scaling quakes, this sets the quake to reach maximum sooner or start minimizing later. - For both, this indicates when the strongest will occur. Default is 0, or in the middle. The original commits were nearly impossible to find in the convoluted commit tree, so I think it's preferable to have one clean commit instead. --- src/g_shared/a_quake.cpp | 128 +++++++++++++++++++++++++----- src/g_shared/a_sharedglobal.h | 6 +- src/p_acs.cpp | 4 +- src/p_spec.h | 2 +- src/r_utility.cpp | 19 +++-- src/thingdef/thingdef_codeptr.cpp | 6 +- src/version.h | 2 +- wadsrc/static/actors/actor.txt | 2 +- 8 files changed, 131 insertions(+), 38 deletions(-) diff --git a/src/g_shared/a_quake.cpp b/src/g_shared/a_quake.cpp index 2e1c5fa16..c93c574a3 100644 --- a/src/g_shared/a_quake.cpp +++ b/src/g_shared/a_quake.cpp @@ -37,7 +37,7 @@ DEarthquake::DEarthquake() DEarthquake::DEarthquake (AActor *center, int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, FSoundID quakesound, int flags, - double waveSpeedX, double waveSpeedY, double waveSpeedZ) + double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint) : DThinker(STAT_EARTHQUAKE) { m_QuakeSFX = quakesound; @@ -54,6 +54,9 @@ DEarthquake::DEarthquake (AActor *center, int intensityX, int intensityY, int in m_WaveSpeedX = (float)waveSpeedX; m_WaveSpeedY = (float)waveSpeedY; m_WaveSpeedZ = (float)waveSpeedZ; + m_Falloff = falloff << FRACBITS; + m_Highpoint = highpoint; + m_MiniCount = highpoint; } //========================================================================== @@ -97,6 +100,14 @@ void DEarthquake::Serialize (FArchive &arc) { arc << m_WaveSpeedX << m_WaveSpeedY << m_WaveSpeedZ; } + if (SaveVersion < 4534) + { + m_Falloff = m_Highpoint = m_MiniCount = 0; + } + else + { + arc << m_Falloff << m_Highpoint << m_MiniCount; + } } //========================================================================== @@ -122,6 +133,7 @@ void DEarthquake::Tick () { S_Sound (m_Spot, CHAN_BODY | CHAN_LOOP, m_QuakeSFX, 1, ATTN_NORM); } + if (m_DamageRadius > 0) { for (i = 0; i < MAXPLAYERS; i++) @@ -158,6 +170,8 @@ void DEarthquake::Tick () } } + if (m_MiniCount > 0) + m_MiniCount--; if (--m_Countdown == 0) { if (S_IsActorPlayingSomething(m_Spot, CHAN_BODY, m_QuakeSFX)) @@ -168,12 +182,18 @@ void DEarthquake::Tick () } } +//========================================================================== +// +// DEarthquake :: GetModWave +// +// QF_WAVE converts intensity into amplitude and unlocks a new property, the +// wave length. This is, in short, waves per second. Named waveMultiplier +// because that's as the name implies: adds more waves per second. +// +//========================================================================== + fixed_t DEarthquake::GetModWave(double waveMultiplier) const { - //QF_WAVE converts intensity into amplitude and unlocks a new property, the wave length. - //This is, in short, waves per second (full cycles, mind you, from 0 to 360.) - //Named waveMultiplier because that's as the name implies: adds more waves per second. - double time = m_Countdown - FIXED2DBL(r_TicFrac); return FLOAT2FIXED(sin(waveMultiplier * time * (M_PI * 2 / TICRATE))); } @@ -189,35 +209,96 @@ fixed_t DEarthquake::GetModWave(double waveMultiplier) const fixed_t DEarthquake::GetModIntensity(fixed_t intensity) const { assert(m_CountdownStart >= m_Countdown); + intensity += intensity; // always doubled if (m_Flags & (QF_SCALEDOWN | QF_SCALEUP)) { + // Adjustable maximums must use a range between 1 and m_CountdownStart to constrain between no quake and full quake. + bool check = !!(m_Highpoint > 0 && m_Highpoint < m_CountdownStart); + int divider = (check) ? m_Highpoint : m_CountdownStart; int scalar; + if ((m_Flags & (QF_SCALEDOWN | QF_SCALEUP)) == (QF_SCALEDOWN | QF_SCALEUP)) { - scalar = (m_Flags & QF_MAX) ? MAX(m_Countdown, m_CountdownStart - m_Countdown) - : MIN(m_Countdown, m_CountdownStart - m_Countdown); + if (check) + { + if (m_MiniCount > 0) + scalar = (m_Flags & QF_MAX) ? m_MiniCount : (m_Highpoint - m_MiniCount); + else + { + divider = m_CountdownStart - m_Highpoint; + scalar = (m_Flags & QF_MAX) ? (divider - m_Countdown) : m_Countdown; + } + } + else + { + // Defaults to middle of the road. + divider = m_CountdownStart; + scalar = (m_Flags & QF_MAX) ? MAX(m_Countdown, m_CountdownStart - m_Countdown) + : MIN(m_Countdown, m_CountdownStart - m_Countdown); + } + scalar = (scalar > divider) ? divider : scalar; if (m_Flags & QF_FULLINTENSITY) { scalar *= 2; } } - else if (m_Flags & QF_SCALEDOWN) + else { - scalar = m_Countdown; - } - else // QF_SCALEUP - { - scalar = m_CountdownStart - m_Countdown; - } - assert(m_CountdownStart > 0); - intensity = Scale(intensity, scalar, m_CountdownStart); + if (m_Flags & QF_SCALEDOWN) + { + scalar = m_Countdown; + } + else // QF_SCALEUP + { + scalar = m_CountdownStart - m_Countdown; + if (m_Highpoint > 0) + { + if ((m_Highpoint - m_MiniCount) < divider) + scalar = m_Highpoint - m_MiniCount; + else + scalar = divider; + } + } + scalar = (scalar > divider) ? divider : scalar; + } + assert(divider > 0); + intensity = Scale(intensity, scalar, divider); } return intensity; } +//========================================================================== +// +// DEarthquake :: GetFalloff +// +// Given the distance of the player from the quake, find the multiplier. +// Process everything as doubles, and output again as fixed_t (mainly +// because fixed_t was misbehaving here...) +// +//========================================================================== + +fixed_t DEarthquake::GetFalloff(fixed_t dist) 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. + return FRACUNIT; + } + else if ((dist > m_Falloff) && (dist < m_TremorRadius)) + { //Player inside the radius, and outside the min distance for falloff. + fixed_t tremorsize = m_TremorRadius - m_Falloff; + fixed_t tremordist = dist - m_Falloff; + assert(tremorsize > 0); + return (FRACUNIT - FixedMul(FRACUNIT,tremordist) / tremorsize); + } + else + { //Shouldn't happen. + return FRACUNIT; + } +} + //========================================================================== // // DEarthquake::StaticGetQuakeIntensity @@ -247,12 +328,16 @@ int DEarthquake::StaticGetQuakeIntensities(AActor *victim, FQuakeJiggers &jigger fixed_t dist = quake->m_Spot->AproxDistance (victim, true); if (dist < quake->m_TremorRadius) { + fixed_t falloff = quake->GetFalloff(dist); ++count; fixed_t x = quake->GetModIntensity(quake->m_IntensityX); fixed_t y = quake->GetModIntensity(quake->m_IntensityY); fixed_t z = quake->GetModIntensity(quake->m_IntensityZ); + + if (!(quake->m_Flags & QF_WAVE)) { + jiggers.Falloff = MAX(falloff, jiggers.Falloff); if (quake->m_Flags & QF_RELATIVE) { jiggers.RelIntensityX = MAX(x, jiggers.RelIntensityX); @@ -268,6 +353,7 @@ int DEarthquake::StaticGetQuakeIntensities(AActor *victim, FQuakeJiggers &jigger } else { + jiggers.WFalloff = MAX(falloff, jiggers.WFalloff); fixed_t mx = FixedMul(x, quake->GetModWave(quake->m_WaveSpeedX)); fixed_t my = FixedMul(y, quake->GetModWave(quake->m_WaveSpeedY)); fixed_t mz = FixedMul(z, quake->GetModWave(quake->m_WaveSpeedZ)); @@ -304,7 +390,7 @@ int DEarthquake::StaticGetQuakeIntensities(AActor *victim, FQuakeJiggers &jigger bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, FSoundID quakesfx, int flags, - double waveSpeedX, double waveSpeedY, double waveSpeedZ) + double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint) { AActor *center; bool res = false; @@ -318,7 +404,7 @@ bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY, if (activator != NULL) { new DEarthquake(activator, intensityX, intensityY, intensityZ, duration, damrad, tremrad, - quakesfx, flags, waveSpeedX, waveSpeedY, waveSpeedZ); + quakesfx, flags, waveSpeedX, waveSpeedY, waveSpeedZ, falloff, highpoint); return true; } } @@ -329,7 +415,7 @@ bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY, { res = true; new DEarthquake(center, intensityX, intensityY, intensityZ, duration, damrad, tremrad, - quakesfx, flags, waveSpeedX, waveSpeedY, waveSpeedZ); + quakesfx, flags, waveSpeedX, waveSpeedY, waveSpeedZ, falloff, highpoint); } } @@ -337,6 +423,6 @@ bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY, } bool P_StartQuake(AActor *activator, int tid, int intensity, int duration, int damrad, int tremrad, FSoundID quakesfx) -{ //Maintains original behavior by passing 0 to intensityZ, and flags. - return P_StartQuakeXYZ(activator, tid, intensity, intensity, 0, duration, damrad, tremrad, quakesfx, 0, 0, 0, 0); +{ //Maintains original behavior by passing 0 to intensityZ, flags, and everything else after QSFX. + return P_StartQuakeXYZ(activator, tid, intensity, intensity, 0, duration, damrad, tremrad, quakesfx, 0, 0, 0, 0, 0, 0); } diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index 1e59bf740..1d5fd4ba5 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -157,6 +157,7 @@ struct FQuakeJiggers int RelIntensityX, RelIntensityY, RelIntensityZ; int OffsetX, OffsetY, OffsetZ; int RelOffsetX, RelOffsetY, RelOffsetZ; + int Falloff, WFalloff; }; class DEarthquake : public DThinker @@ -166,7 +167,7 @@ class DEarthquake : public DThinker public: DEarthquake(AActor *center, int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, FSoundID quakesfx, int flags, - double waveSpeedX, double waveSpeedY, double waveSpeedZ); + double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint); void Serialize (FArchive &arc); void Tick (); @@ -178,9 +179,12 @@ public: int m_Flags; fixed_t m_IntensityX, m_IntensityY, m_IntensityZ; float m_WaveSpeedX, m_WaveSpeedY, m_WaveSpeedZ; + fixed_t m_Falloff; + int m_Highpoint, m_MiniCount; fixed_t GetModIntensity(int intensity) const; fixed_t GetModWave(double waveMultiplier) const; + fixed_t GetFalloff(fixed_t dist) const; static int StaticGetQuakeIntensities(AActor *viewer, FQuakeJiggers &jiggers); diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 11b169e6a..fe10921d0 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -5747,7 +5747,9 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) argCount > 8 ? args[8] : 0, argCount > 9 ? FIXED2DBL(args[9]) : 1.0, argCount > 10 ? FIXED2DBL(args[10]) : 1.0, - argCount > 11 ? FIXED2DBL(args[11]) : 1.0 ); + argCount > 11 ? FIXED2DBL(args[11]) : 1.0, + argCount > 12 ? args[12] : 0, + argCount > 13 ? args[13] : 0); } case ACSF_SetLineActivation: diff --git a/src/p_spec.h b/src/p_spec.h index e3b1c05ad..83a50e252 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -944,7 +944,7 @@ void P_DoDeferedScripts (void); // // [RH] p_quake.c // -bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, FSoundID quakesfx, int flags, double waveSpeedX, double waveSpeedY, double waveSpeedZ); +bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, FSoundID quakesfx, int flags, double waveSpeedX, double waveSpeedY, double waveSpeedZ, int falloff, int highpoint); bool P_StartQuake(AActor *activator, int tid, int intensity, int duration, int damrad, int tremrad, FSoundID quakesfx); #endif diff --git a/src/r_utility.cpp b/src/r_utility.cpp index f4bd85a9a..a5a422426 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -896,10 +896,9 @@ void R_AddInterpolationPoint(const fixedvec3a &vec) // //========================================================================== -static fixed_t QuakePower(fixed_t factor, fixed_t intensity, fixed_t offset) +static fixed_t QuakePower(fixed_t factor, fixed_t intensity, fixed_t offset, fixed_t falloff, fixed_t wfalloff) { fixed_t randumb; - if (intensity == 0) { randumb = 0; @@ -908,7 +907,8 @@ static fixed_t QuakePower(fixed_t factor, fixed_t intensity, fixed_t offset) { randumb = pr_torchflicker(intensity * 2) - intensity; } - return FixedMul(factor, randumb + offset); + fixed_t rn2 = (FixedMul(wfalloff,offset) + FixedMul(falloff, randumb)); + return FixedMul(factor, rn2); } //========================================================================== @@ -1050,34 +1050,33 @@ void R_SetupFrame (AActor *actor) if ((jiggers.RelIntensityX | jiggers.RelOffsetX) != 0) { int ang = (camera->angle) >> ANGLETOFINESHIFT; - fixed_t power = QuakePower(quakefactor, jiggers.RelIntensityX, jiggers.RelOffsetX); + fixed_t power = QuakePower(quakefactor, jiggers.RelIntensityX, jiggers.RelOffsetX, jiggers.Falloff, jiggers.WFalloff); viewx += FixedMul(finecosine[ang], power); viewy += FixedMul(finesine[ang], power); } if ((jiggers.RelIntensityY | jiggers.RelOffsetY) != 0) { int ang = (camera->angle + ANG90) >> ANGLETOFINESHIFT; - fixed_t power = QuakePower(quakefactor, jiggers.RelIntensityY, jiggers.RelOffsetY); + fixed_t power = QuakePower(quakefactor, jiggers.RelIntensityY, jiggers.RelOffsetY, jiggers.Falloff, jiggers.WFalloff); viewx += FixedMul(finecosine[ang], power); viewy += FixedMul(finesine[ang], power); } // FIXME: Relative Z is not relative - // [MC]On it! Will be introducing pitch after QF_WAVE. if ((jiggers.RelIntensityZ | jiggers.RelOffsetZ) != 0) { - viewz += QuakePower(quakefactor, jiggers.RelIntensityZ, jiggers.RelOffsetZ); + viewz += QuakePower(quakefactor, jiggers.RelIntensityZ, jiggers.RelOffsetZ, jiggers.Falloff, jiggers.WFalloff); } if ((jiggers.IntensityX | jiggers.OffsetX) != 0) { - viewx += QuakePower(quakefactor, jiggers.IntensityX, jiggers.OffsetX); + viewx += QuakePower(quakefactor, jiggers.IntensityX, jiggers.OffsetX, jiggers.Falloff, jiggers.WFalloff); } if ((jiggers.IntensityY | jiggers.OffsetY) != 0) { - viewy += QuakePower(quakefactor, jiggers.IntensityY, jiggers.OffsetY); + viewy += QuakePower(quakefactor, jiggers.IntensityY, jiggers.OffsetY, jiggers.Falloff, jiggers.WFalloff); } if ((jiggers.IntensityZ | jiggers.OffsetZ) != 0) { - viewz += QuakePower(quakefactor, jiggers.IntensityZ, jiggers.OffsetZ); + viewz += QuakePower(quakefactor, jiggers.IntensityZ, jiggers.OffsetZ, jiggers.Falloff, jiggers.WFalloff); } } } diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index c5081f57a..9a492130b 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -4969,7 +4969,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Quake) // A_QuakeEx // // Extended version of A_Quake. Takes individual axis into account and can -// take a flag. +// take flags. //=========================================================================== DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_QuakeEx) @@ -4986,7 +4986,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_QuakeEx) PARAM_FLOAT_OPT(mulWaveX) { mulWaveX = 1.; } PARAM_FLOAT_OPT(mulWaveY) { mulWaveY = 1.; } PARAM_FLOAT_OPT(mulWaveZ) { mulWaveZ = 1.; } - P_StartQuakeXYZ(self, 0, intensityX, intensityY, intensityZ, duration, damrad, tremrad, sound, flags, mulWaveX, mulWaveY, mulWaveZ); + PARAM_INT_OPT(falloff) { falloff = 0; } + PARAM_INT_OPT(highpoint) { highpoint = 0; } + P_StartQuakeXYZ(self, 0, intensityX, intensityY, intensityZ, duration, damrad, tremrad, sound, flags, mulWaveX, mulWaveY, mulWaveZ, falloff, highpoint); return 0; } diff --git a/src/version.h b/src/version.h index 764675f0b..17fd288b1 100644 --- a/src/version.h +++ b/src/version.h @@ -76,7 +76,7 @@ const char *GetVersionString(); // Use 4500 as the base git save version, since it's higher than the // SVN revision ever got. -#define SAVEVER 4533 +#define SAVEVER 4534 #define SAVEVERSTRINGIFY2(x) #x #define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x) diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index aeeaec813..e4a9b152b 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -277,7 +277,7 @@ ACTOR Actor native //: Thinker action native A_SetUserArray(name varname, int index, int value); action native A_SetSpecial(int spec, int arg0 = 0, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0); action native A_Quake(int intensity, int duration, int damrad, int tremrad, sound sfx = "world/quake"); - action native A_QuakeEx(int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, sound sfx = "world/quake", int flags = 0, float mulWaveX = 1, float mulWaveY = 1, float mulWaveZ = 1); + action native A_QuakeEx(int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, sound sfx = "world/quake", int flags = 0, float mulWaveX = 1, float mulWaveY = 1, float mulWaveZ = 1, int falloff = 0, int highpoint = 0); action native A_SetTics(int tics); action native A_SetDamageType(name damagetype); action native A_DropItem(class item, int dropamount = -1, int chance = 256);