mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 21:11:39 +00:00
Rewrite new quake stuff for correctness
- Quake scaling should be handled for each quake. The former implementation was potentially taking flags from one quake and applying them to another, which is broken. - Remove all the int<->float conversions.
This commit is contained in:
parent
8e0151b4c1
commit
2827c13d0c
3 changed files with 80 additions and 84 deletions
|
@ -45,7 +45,7 @@ DEarthquake::DEarthquake (AActor *center, int intensityX, int intensityY, int in
|
|||
m_IntensityX = intensityX;
|
||||
m_IntensityY = intensityY;
|
||||
m_IntensityZ = intensityZ;
|
||||
m_CountdownStart = (double)duration;
|
||||
m_CountdownStart = duration;
|
||||
m_Countdown = duration;
|
||||
m_Flags = flags;
|
||||
}
|
||||
|
@ -151,6 +151,48 @@ void DEarthquake::Tick ()
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DEarthquake :: GetModIntensity
|
||||
//
|
||||
// Given a base intensity, modify it according to the quake's flags.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
fixed_t DEarthquake::GetModIntensity(int intensity) const
|
||||
{
|
||||
assert(m_CountdownStart >= m_Countdown);
|
||||
intensity += intensity; // always doubled
|
||||
if (m_Flags & (QF_SCALEDOWN | QF_SCALEUP))
|
||||
{
|
||||
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 (m_Flags & QF_FULLINTENSITY)
|
||||
{
|
||||
scalar *= 2;
|
||||
}
|
||||
}
|
||||
else if (m_Flags & QF_SCALEDOWN)
|
||||
{
|
||||
scalar = m_Countdown;
|
||||
}
|
||||
else // QF_SCALEUP
|
||||
{
|
||||
scalar = m_CountdownStart - m_Countdown;
|
||||
}
|
||||
assert(m_CountdownStart > 0);
|
||||
intensity = intensity * (scalar << FRACBITS) / m_CountdownStart;
|
||||
}
|
||||
else
|
||||
{
|
||||
intensity <<= FRACBITS;
|
||||
}
|
||||
return intensity;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DEarthquake::StaticGetQuakeIntensity
|
||||
|
@ -160,14 +202,15 @@ void DEarthquake::Tick ()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int DEarthquake::StaticGetQuakeIntensities(AActor *victim, quakeInfo &qprop)
|
||||
int DEarthquake::StaticGetQuakeIntensities(AActor *victim,
|
||||
fixed_t &intensityX, fixed_t &intensityY, fixed_t &intensityZ,
|
||||
fixed_t &relIntensityX, fixed_t &relIntensityY, fixed_t &relIntensityZ)
|
||||
{
|
||||
if (victim->player != NULL && (victim->player->cheats & CF_NOCLIP))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
qprop.isScalingDown = qprop.isScalingUp = qprop.preferMaximum = qprop.fullIntensity = false;
|
||||
qprop.intensityX = qprop.intensityY = qprop.intensityZ = qprop.relIntensityX = qprop.relIntensityY = qprop.relIntensityZ = 0;
|
||||
intensityX = intensityY = intensityZ = relIntensityX = relIntensityY = relIntensityZ = 0;
|
||||
|
||||
TThinkerIterator<DEarthquake> iterator(STAT_EARTHQUAKE);
|
||||
DEarthquake *quake;
|
||||
|
@ -182,30 +225,20 @@ int DEarthquake::StaticGetQuakeIntensities(AActor *victim, quakeInfo &qprop)
|
|||
if (dist < quake->m_TremorRadius)
|
||||
{
|
||||
++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_RELATIVE)
|
||||
{
|
||||
qprop.relIntensityX = MAX(qprop.relIntensityX, quake->m_IntensityX);
|
||||
qprop.relIntensityY = MAX(qprop.relIntensityY, quake->m_IntensityY);
|
||||
qprop.relIntensityZ = MAX(qprop.relIntensityZ, quake->m_IntensityZ);
|
||||
relIntensityX = MAX(relIntensityX, x);
|
||||
relIntensityY = MAX(relIntensityY, y);
|
||||
relIntensityZ = MAX(relIntensityZ, z);
|
||||
}
|
||||
else
|
||||
{
|
||||
qprop.intensityX = MAX(qprop.intensityX, quake->m_IntensityX);
|
||||
qprop.intensityY = MAX(qprop.intensityY, quake->m_IntensityY);
|
||||
qprop.intensityZ = MAX(qprop.intensityZ, quake->m_IntensityZ);
|
||||
}
|
||||
if (quake->m_Flags)
|
||||
{
|
||||
qprop.scaleDownStart = quake->m_CountdownStart;
|
||||
qprop.scaleDown = quake->m_Countdown;
|
||||
qprop.isScalingDown = (quake->m_Flags & QF_SCALEDOWN) ? true : false;
|
||||
qprop.isScalingUp = (quake->m_Flags & QF_SCALEUP) ? true : false;
|
||||
qprop.preferMaximum = (quake->m_Flags & QF_MAX) ? true : false;
|
||||
qprop.fullIntensity = (quake->m_Flags & QF_FULLINTENSITY) ? true : false;
|
||||
}
|
||||
else
|
||||
{
|
||||
qprop.scaleDownStart = qprop.scaleDown = 0.0;
|
||||
intensityX = MAX(intensityX, x);
|
||||
intensityY = MAX(intensityY, y);
|
||||
intensityZ = MAX(intensityZ, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,13 +140,6 @@ enum
|
|||
QF_FULLINTENSITY = 1 << 4,
|
||||
};
|
||||
|
||||
struct quakeInfo
|
||||
{
|
||||
int intensityX, intensityY, intensityZ, relIntensityX, relIntensityY, relIntensityZ;
|
||||
double scaleDown, scaleDownStart;
|
||||
bool isScalingDown, isScalingUp, preferMaximum, fullIntensity;
|
||||
};
|
||||
|
||||
class DEarthquake : public DThinker
|
||||
{
|
||||
DECLARE_CLASS (DEarthquake, DThinker)
|
||||
|
@ -159,12 +152,16 @@ public:
|
|||
TObjPtr<AActor> m_Spot;
|
||||
fixed_t m_TremorRadius, m_DamageRadius;
|
||||
int m_Countdown;
|
||||
double m_CountdownStart;
|
||||
int m_CountdownStart;
|
||||
FSoundID m_QuakeSFX;
|
||||
int m_Flags;
|
||||
int m_IntensityX, m_IntensityY, m_IntensityZ;
|
||||
|
||||
static int StaticGetQuakeIntensities(AActor *viewer, quakeInfo &qprop);
|
||||
fixed_t GetModIntensity(int intensity) const;
|
||||
|
||||
static int StaticGetQuakeIntensities(AActor *viewer,
|
||||
fixed_t &intensityX, fixed_t &intensityY, fixed_t &intensityZ,
|
||||
fixed_t &relIntensityX, fixed_t &relIntensityY, fixed_t &relIntensityZ);
|
||||
|
||||
private:
|
||||
DEarthquake ();
|
||||
|
|
|
@ -770,45 +770,9 @@ bool R_GetViewInterpolationStatus()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static fixed_t QuakePower(double factor, int intensity, quakeInfo quake)
|
||||
static fixed_t QuakePower(fixed_t factor, fixed_t intensity)
|
||||
{
|
||||
double scaleDownStart = quake.scaleDownStart;
|
||||
double scaleDown = quake.scaleDown;
|
||||
if (intensity == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
double ss = (double)((pr_torchflicker() % (intensity << 2)) - (intensity << 1));
|
||||
double mtp = (quake.fullIntensity) ? 2.0 : 1.0;
|
||||
if (quake.isScalingDown || quake.isScalingUp)
|
||||
{
|
||||
fixed_t result;
|
||||
if (scaleDownStart == 0) scaleDownStart = 1;
|
||||
|
||||
if (quake.isScalingDown && quake.isScalingUp)
|
||||
{
|
||||
if (quake.preferMaximum)
|
||||
result = FLOAT2FIXED((factor * ss) * MAX(((scaleDown*mtp) / scaleDownStart), ((scaleDownStart - scaleDown)*mtp) / scaleDownStart));
|
||||
else
|
||||
result = FLOAT2FIXED((factor * ss) * MIN(((scaleDown*mtp) / scaleDownStart), ((scaleDownStart - scaleDown)*mtp) / scaleDownStart));
|
||||
}
|
||||
else if (quake.isScalingDown)
|
||||
result = FLOAT2FIXED((factor * ss) * (scaleDown / scaleDownStart));
|
||||
else if (quake.isScalingUp)
|
||||
result = FLOAT2FIXED((factor * ss) * ((scaleDownStart - scaleDown) / scaleDownStart));
|
||||
else
|
||||
result = FLOAT2FIXED(factor * ss);
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FLOAT2FIXED(factor * ss);
|
||||
}
|
||||
}
|
||||
|
||||
return FixedMul(factor, pr_torchflicker(intensity * 2) - intensity);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -921,38 +885,40 @@ void R_SetupFrame (AActor *actor)
|
|||
|
||||
if (!paused)
|
||||
{
|
||||
quakeInfo quake;
|
||||
if (DEarthquake::StaticGetQuakeIntensities(camera, quake) > 0)
|
||||
fixed_t intensityX, intensityY, intensityZ, relIntensityX, relIntensityY, relIntensityZ;
|
||||
if (DEarthquake::StaticGetQuakeIntensities(camera,
|
||||
intensityX, intensityY, intensityZ,
|
||||
relIntensityX, relIntensityY, relIntensityZ) > 0)
|
||||
{
|
||||
double quakefactor = r_quakeintensity;
|
||||
fixed_t quakefactor = FLOAT2FIXED(r_quakeintensity);
|
||||
|
||||
if (quake.relIntensityX != 0)
|
||||
if (relIntensityX != 0)
|
||||
{
|
||||
int ang = (camera->angle) >> ANGLETOFINESHIFT;
|
||||
fixed_t power = QuakePower(quakefactor, quake.relIntensityX, quake);
|
||||
fixed_t power = QuakePower(quakefactor, relIntensityX);
|
||||
viewx += FixedMul(finecosine[ang], power);
|
||||
viewy += FixedMul(finesine[ang], power);
|
||||
}
|
||||
if (quake.relIntensityY != 0)
|
||||
if (relIntensityY != 0)
|
||||
{
|
||||
int ang = (camera->angle + ANG90) >> ANGLETOFINESHIFT;
|
||||
fixed_t power = QuakePower(quakefactor, quake.relIntensityY, quake);
|
||||
fixed_t power = QuakePower(quakefactor, relIntensityY);
|
||||
viewx += FixedMul(finecosine[ang], power);
|
||||
viewy += FixedMul(finesine[ang], power);
|
||||
}
|
||||
if (quake.intensityX != 0)
|
||||
if (intensityX != 0)
|
||||
{
|
||||
viewx += QuakePower(quakefactor, quake.intensityX, quake);
|
||||
viewx += QuakePower(quakefactor, intensityX);
|
||||
}
|
||||
if (quake.intensityY != 0)
|
||||
if (intensityY != 0)
|
||||
{
|
||||
viewy += QuakePower(quakefactor, quake.intensityY, quake);
|
||||
viewy += QuakePower(quakefactor, intensityY);
|
||||
}
|
||||
// FIXME: Relative Z is not relative
|
||||
quake.intensityZ = MAX(quake.intensityZ, quake.relIntensityZ);
|
||||
if (quake.intensityZ != 0)
|
||||
intensityZ = MAX(intensityZ, relIntensityZ);
|
||||
if (intensityZ != 0)
|
||||
{
|
||||
viewz += QuakePower(quakefactor, quake.intensityZ, quake);
|
||||
viewz += QuakePower(quakefactor, intensityZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue