2006-02-24 04:48:15 +00:00
|
|
|
#include "templates.h"
|
|
|
|
#include "doomtype.h"
|
|
|
|
#include "doomstat.h"
|
|
|
|
#include "p_local.h"
|
|
|
|
#include "actor.h"
|
|
|
|
#include "m_bbox.h"
|
|
|
|
#include "m_random.h"
|
|
|
|
#include "s_sound.h"
|
2006-07-01 00:21:36 +00:00
|
|
|
#include "a_sharedglobal.h"
|
|
|
|
#include "statnums.h"
|
2011-07-06 14:20:54 +00:00
|
|
|
#include "farchive.h"
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
static FRandom pr_quake ("Quake");
|
|
|
|
|
|
|
|
IMPLEMENT_POINTY_CLASS (DEarthquake)
|
|
|
|
DECLARE_POINTER (m_Spot)
|
|
|
|
END_POINTERS
|
|
|
|
|
2006-07-01 00:21:36 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// DEarthquake :: DEarthquake private constructor
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
DEarthquake::DEarthquake()
|
|
|
|
: DThinker(STAT_EARTHQUAKE)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// DEarthquake :: DEarthquake public constructor
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2015-02-14 21:58:39 +00:00
|
|
|
DEarthquake::DEarthquake (AActor *center, int intensityX, int intensityY, int intensityZ, int duration,
|
|
|
|
int damrad, int tremrad, FSoundID quakesound, int flags)
|
2006-07-01 00:21:36 +00:00
|
|
|
: DThinker(STAT_EARTHQUAKE)
|
|
|
|
{
|
2009-10-15 08:25:07 +00:00
|
|
|
m_QuakeSFX = quakesound;
|
2006-07-01 00:21:36 +00:00
|
|
|
m_Spot = center;
|
|
|
|
// Radii are specified in tile units (64 pixels)
|
2009-10-15 08:25:07 +00:00
|
|
|
m_DamageRadius = damrad << (FRACBITS);
|
|
|
|
m_TremorRadius = tremrad << (FRACBITS);
|
2015-02-18 20:48:52 +00:00
|
|
|
m_IntensityX = intensityX;
|
|
|
|
m_IntensityY = intensityY;
|
|
|
|
m_IntensityZ = intensityZ;
|
2015-02-20 07:33:30 +00:00
|
|
|
m_CountdownStart = (double)duration;
|
2006-07-01 00:21:36 +00:00
|
|
|
m_Countdown = duration;
|
2015-02-14 21:58:39 +00:00
|
|
|
m_Flags = flags;
|
2006-07-01 00:21:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// DEarthquake :: Serialize
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
void DEarthquake::Serialize (FArchive &arc)
|
|
|
|
{
|
2015-02-18 20:48:52 +00:00
|
|
|
Super::Serialize (arc);
|
|
|
|
arc << m_Spot << m_IntensityX << m_Countdown
|
2010-12-12 15:43:35 +00:00
|
|
|
<< m_TremorRadius << m_DamageRadius
|
2015-02-18 20:48:52 +00:00
|
|
|
<< m_QuakeSFX;
|
|
|
|
if (SaveVersion < 4519)
|
|
|
|
{
|
|
|
|
m_IntensityY = m_IntensityX;
|
|
|
|
m_IntensityZ = 0;
|
|
|
|
m_Flags = 0;
|
|
|
|
}
|
2015-02-20 07:41:59 +00:00
|
|
|
if (SaveVersion < 4520)
|
|
|
|
m_CountdownStart = 0;
|
2015-02-18 20:48:52 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
arc << m_IntensityY << m_IntensityZ << m_Flags;
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2006-07-01 00:21:36 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// DEarthquake :: Tick
|
|
|
|
//
|
|
|
|
// Deals damage to any players near the earthquake and makes sure it's
|
|
|
|
// making noise.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
void DEarthquake::Tick ()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (m_Spot == NULL)
|
|
|
|
{
|
|
|
|
Destroy ();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-12-24 23:08:49 +00:00
|
|
|
if (!S_IsActorPlayingSomething (m_Spot, CHAN_BODY, m_QuakeSFX))
|
2008-04-18 03:26:48 +00:00
|
|
|
{
|
2008-06-15 02:25:09 +00:00
|
|
|
S_Sound (m_Spot, CHAN_BODY | CHAN_LOOP, m_QuakeSFX, 1, ATTN_NORM);
|
2008-04-18 03:26:48 +00:00
|
|
|
}
|
2006-07-01 00:21:36 +00:00
|
|
|
if (m_DamageRadius > 0)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-07-01 00:21:36 +00:00
|
|
|
for (i = 0; i < MAXPLAYERS; i++)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-07-01 00:21:36 +00:00
|
|
|
if (playeringame[i] && !(players[i].cheats & CF_NOCLIP))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-07-01 00:21:36 +00:00
|
|
|
AActor *victim = players[i].mo;
|
|
|
|
fixed_t dist;
|
|
|
|
|
|
|
|
dist = P_AproxDistance (victim->x - m_Spot->x, victim->y - m_Spot->y);
|
|
|
|
// Check if in damage radius
|
|
|
|
if (dist < m_DamageRadius && victim->z <= victim->floorz)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-07-01 00:21:36 +00:00
|
|
|
if (pr_quake() < 50)
|
|
|
|
{
|
2006-10-31 14:53:21 +00:00
|
|
|
P_DamageMobj (victim, NULL, NULL, pr_quake.HitDice (1), NAME_None);
|
2006-07-01 00:21:36 +00:00
|
|
|
}
|
|
|
|
// Thrust player around
|
|
|
|
angle_t an = victim->angle + ANGLE_1*pr_quake();
|
2015-02-18 20:48:52 +00:00
|
|
|
if (m_IntensityX == m_IntensityY)
|
|
|
|
{ // Thrust in a circle
|
|
|
|
P_ThrustMobj (victim, an, m_IntensityX << (FRACBITS-1));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // Thrust in an ellipse
|
|
|
|
an >>= ANGLETOFINESHIFT;
|
|
|
|
// So this is actually completely wrong, but it ought to be good
|
|
|
|
// enough. Otherwise, I'd have to use tangents and square roots.
|
|
|
|
victim->velx += FixedMul(m_IntensityX << (FRACBITS-1), finecosine[an]);
|
|
|
|
victim->vely += FixedMul(m_IntensityY << (FRACBITS-1), finesine[an]);
|
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (--m_Countdown == 0)
|
|
|
|
{
|
2008-04-18 03:26:48 +00:00
|
|
|
if (S_IsActorPlayingSomething(m_Spot, CHAN_BODY, m_QuakeSFX))
|
|
|
|
{
|
|
|
|
S_StopSound(m_Spot, CHAN_BODY);
|
|
|
|
}
|
|
|
|
Destroy();
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-07-01 00:21:36 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// DEarthquake::StaticGetQuakeIntensity
|
|
|
|
//
|
|
|
|
// Searches for all quakes near the victim and returns their combined
|
|
|
|
// intensity.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2015-02-18 20:48:52 +00:00
|
|
|
int DEarthquake::StaticGetQuakeIntensities(AActor *victim,
|
2015-02-20 07:33:30 +00:00
|
|
|
int &x, int &y, int &z, int &relx, int &rely, int &relz, double &scaleDown, double &scaleDownStart)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-07-01 00:21:36 +00:00
|
|
|
if (victim->player != NULL && (victim->player->cheats & CF_NOCLIP))
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-02-19 22:30:00 +00:00
|
|
|
x = y = z = relx = rely = relz = 0;
|
2015-02-18 20:48:52 +00:00
|
|
|
|
|
|
|
TThinkerIterator<DEarthquake> iterator(STAT_EARTHQUAKE);
|
|
|
|
DEarthquake *quake;
|
|
|
|
int count = 0;
|
|
|
|
|
2006-07-01 00:21:36 +00:00
|
|
|
while ( (quake = iterator.Next()) != NULL)
|
|
|
|
{
|
2006-07-11 00:20:45 +00:00
|
|
|
if (quake->m_Spot != NULL)
|
2006-07-01 00:21:36 +00:00
|
|
|
{
|
2006-07-11 00:20:45 +00:00
|
|
|
fixed_t dist = P_AproxDistance (victim->x - quake->m_Spot->x,
|
|
|
|
victim->y - quake->m_Spot->y);
|
|
|
|
if (dist < quake->m_TremorRadius)
|
|
|
|
{
|
2015-02-18 20:48:52 +00:00
|
|
|
++count;
|
|
|
|
if (quake->m_Flags & QF_RELATIVE)
|
2015-02-14 21:58:39 +00:00
|
|
|
{
|
2015-02-18 20:48:52 +00:00
|
|
|
relx = MAX(relx, quake->m_IntensityX);
|
|
|
|
rely = MAX(rely, quake->m_IntensityY);
|
|
|
|
relz = MAX(relz, quake->m_IntensityZ);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
x = MAX(x, quake->m_IntensityX);
|
|
|
|
y = MAX(y, quake->m_IntensityY);
|
|
|
|
z = MAX(z, quake->m_IntensityZ);
|
2015-02-14 21:58:39 +00:00
|
|
|
}
|
2015-02-20 03:42:32 +00:00
|
|
|
if (quake->m_Flags & QF_SCALEDOWN)
|
|
|
|
{
|
2015-02-20 07:33:30 +00:00
|
|
|
scaleDownStart = quake->m_CountdownStart;
|
2015-02-20 05:19:24 +00:00
|
|
|
scaleDown = (double)quake->m_Countdown;
|
2015-02-20 03:42:32 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-02-20 07:33:30 +00:00
|
|
|
scaleDownStart = scaleDown = 0.0;
|
2015-02-20 03:42:32 +00:00
|
|
|
}
|
2006-07-11 00:20:45 +00:00
|
|
|
}
|
2006-07-01 00:21:36 +00:00
|
|
|
}
|
|
|
|
}
|
2015-02-18 20:48:52 +00:00
|
|
|
return count;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
2006-07-01 00:21:36 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// P_StartQuake
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2015-02-14 21:58:39 +00:00
|
|
|
bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, FSoundID quakesfx, int flags)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
AActor *center;
|
|
|
|
bool res = false;
|
|
|
|
|
2015-02-14 21:58:39 +00:00
|
|
|
if (intensityX) intensityX = clamp(intensityX, 1, 9);
|
|
|
|
if (intensityY) intensityY = clamp(intensityY, 1, 9);
|
|
|
|
if (intensityZ) intensityZ = clamp(intensityZ, 1, 9);
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2006-07-30 08:31:26 +00:00
|
|
|
if (tid == 0)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2006-07-30 08:31:26 +00:00
|
|
|
if (activator != NULL)
|
|
|
|
{
|
2015-02-14 21:58:39 +00:00
|
|
|
new DEarthquake(activator, intensityX, intensityY, intensityZ, duration, damrad, tremrad, quakesfx, flags);
|
2006-07-30 08:31:26 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FActorIterator iterator (tid);
|
|
|
|
while ( (center = iterator.Next ()) )
|
|
|
|
{
|
|
|
|
res = true;
|
2015-02-14 21:58:39 +00:00
|
|
|
new DEarthquake(center, intensityX, intensityY, intensityZ, duration, damrad, tremrad, quakesfx, flags);
|
2006-07-30 08:31:26 +00:00
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
2015-02-14 21:58:39 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|