- 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.
This commit is contained in:
Christoph Oelckers 2016-03-23 14:03:10 +01:00
parent f38dbc5055
commit 0d1fbcf65f
8 changed files with 131 additions and 38 deletions

View file

@ -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);
}

View file

@ -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);

View file

@ -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:

View file

@ -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

View file

@ -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);
}
}
}

View file

@ -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;
}

View file

@ -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)

View file

@ -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<Actor> item, int dropamount = -1, int chance = 256);