mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-08 05:51:26 +00:00
320 lines
8.6 KiB
C++
320 lines
8.6 KiB
C++
|
#include "actor.h"
|
||
|
#include "info.h"
|
||
|
#include "m_random.h"
|
||
|
#include "p_enemy.h"
|
||
|
#include "p_local.h"
|
||
|
#include "a_sharedglobal.h"
|
||
|
#include "s_sound.h"
|
||
|
|
||
|
static FRandom pr_thrustraise ("ThrustRaise");
|
||
|
|
||
|
// Dirt clump (spawned by spike) --------------------------------------------
|
||
|
|
||
|
class ADirtClump : public AActor
|
||
|
{
|
||
|
DECLARE_ACTOR (ADirtClump, AActor)
|
||
|
};
|
||
|
|
||
|
FState ADirtClump::States[] =
|
||
|
{
|
||
|
S_NORMAL (TSPK, 'C', 20, NULL, &States[0])
|
||
|
};
|
||
|
|
||
|
IMPLEMENT_ACTOR (ADirtClump, Hexen, -1, 0)
|
||
|
PROP_Flags (MF_NOBLOCKMAP)
|
||
|
PROP_Flags2 (MF2_NOTELEPORT)
|
||
|
PROP_SpawnState (0)
|
||
|
END_DEFAULTS
|
||
|
|
||
|
// Spike (thrust floor) -----------------------------------------------------
|
||
|
|
||
|
void A_ThrustInitUp (AActor *);
|
||
|
void A_ThrustInitDn (AActor *);
|
||
|
void A_ThrustRaise (AActor *);
|
||
|
void A_ThrustLower (AActor *);
|
||
|
void A_ThrustBlock (AActor *);
|
||
|
void A_ThrustImpale (AActor *);
|
||
|
|
||
|
AActor *tsthing;
|
||
|
|
||
|
BOOL PIT_ThrustStompThing (AActor *thing)
|
||
|
{
|
||
|
fixed_t blockdist;
|
||
|
|
||
|
if (!(thing->flags & MF_SHOOTABLE) )
|
||
|
return true;
|
||
|
|
||
|
blockdist = thing->radius + tsthing->radius;
|
||
|
if ( abs(thing->x - tsthing->x) >= blockdist ||
|
||
|
abs(thing->y - tsthing->y) >= blockdist ||
|
||
|
(thing->z > tsthing->z+tsthing->height) )
|
||
|
return true; // didn't hit it
|
||
|
|
||
|
if (thing == tsthing)
|
||
|
return true; // don't clip against self
|
||
|
|
||
|
P_DamageMobj (thing, tsthing, tsthing, 10001, MOD_CRUSH);
|
||
|
P_TraceBleed (10001, thing);
|
||
|
tsthing->args[1] = 1; // Mark thrust thing as bloody
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void P_ThrustSpike (AActor *actor)
|
||
|
{
|
||
|
static TArray<AActor *> spikebt;
|
||
|
|
||
|
int xl,xh,yl,yh,bx,by;
|
||
|
int x0,x2,y0,y2;
|
||
|
|
||
|
tsthing = actor;
|
||
|
|
||
|
x0 = actor->x - actor->radius;
|
||
|
x2 = actor->x + actor->radius;
|
||
|
y0 = actor->y - actor->radius;
|
||
|
y2 = actor->y + actor->radius;
|
||
|
|
||
|
xl = (x0 - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
|
||
|
xh = (x2 - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
|
||
|
yl = (y0 - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
|
||
|
yh = (y2 - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
|
||
|
|
||
|
spikebt.Clear();
|
||
|
|
||
|
// stomp on any things contacted
|
||
|
for (bx = xl; bx <= xh; bx++)
|
||
|
for (by = yl; by <= yh; by++)
|
||
|
P_BlockThingsIterator (bx, by, PIT_ThrustStompThing, spikebt);
|
||
|
}
|
||
|
|
||
|
// AThrustFloor is just a container for all the spike states.
|
||
|
// All the real spikes subclass it.
|
||
|
|
||
|
class AThrustFloor : public AActor
|
||
|
{
|
||
|
DECLARE_ACTOR (AThrustFloor, AActor)
|
||
|
HAS_OBJECT_POINTERS
|
||
|
public:
|
||
|
void Serialize (FArchive &arc);
|
||
|
|
||
|
fixed_t GetSinkSpeed () { return 6*FRACUNIT; }
|
||
|
fixed_t GetRaiseSpeed () { return special2*FRACUNIT; }
|
||
|
|
||
|
void Activate (AActor *activator);
|
||
|
void Deactivate (AActor *activator);
|
||
|
|
||
|
ADirtClump *DirtClump;
|
||
|
};
|
||
|
|
||
|
IMPLEMENT_POINTY_CLASS (AThrustFloor)
|
||
|
DECLARE_POINTER (DirtClump)
|
||
|
END_POINTERS
|
||
|
|
||
|
void AThrustFloor::Serialize (FArchive &arc)
|
||
|
{
|
||
|
Super::Serialize (arc);
|
||
|
arc << DirtClump;
|
||
|
}
|
||
|
|
||
|
FState AThrustFloor::States[] =
|
||
|
{
|
||
|
#define S_THRUSTRAISING 0
|
||
|
S_NORMAL (TSPK, 'A', 2, A_ThrustRaise , &States[S_THRUSTRAISING]),
|
||
|
|
||
|
#define S_BTHRUSTRAISING (S_THRUSTRAISING+1)
|
||
|
S_NORMAL (TSPK, 'B', 2, A_ThrustRaise , &States[S_BTHRUSTRAISING]),
|
||
|
|
||
|
#define S_THRUSTIMPALE (S_BTHRUSTRAISING+1)
|
||
|
S_NORMAL (TSPK, 'A', 2, A_ThrustImpale , &States[S_THRUSTRAISING]),
|
||
|
|
||
|
#define S_BTHRUSTIMPALE (S_THRUSTIMPALE+1)
|
||
|
S_NORMAL (TSPK, 'B', 2, A_ThrustImpale , &States[S_BTHRUSTRAISING]),
|
||
|
|
||
|
#define S_THRUSTBLOCK (S_BTHRUSTIMPALE+1)
|
||
|
S_NORMAL (TSPK, 'A', 10, NULL , &States[S_THRUSTBLOCK]),
|
||
|
|
||
|
#define S_BTHRUSTBLOCK (S_THRUSTBLOCK+1)
|
||
|
S_NORMAL (TSPK, 'B', 10, NULL , &States[S_BTHRUSTBLOCK]),
|
||
|
|
||
|
#define S_THRUSTLOWER (S_BTHRUSTBLOCK+1)
|
||
|
S_NORMAL (TSPK, 'A', 2, A_ThrustLower , &States[S_THRUSTLOWER]),
|
||
|
|
||
|
#define S_BTHRUSTLOWER (S_THRUSTLOWER+1)
|
||
|
S_NORMAL (TSPK, 'B', 2, A_ThrustLower , &States[S_BTHRUSTLOWER]),
|
||
|
|
||
|
#define S_THRUSTSTAY (S_BTHRUSTLOWER+1)
|
||
|
S_NORMAL (TSPK, 'A', -1, NULL , &States[S_THRUSTSTAY]),
|
||
|
|
||
|
#define S_BTHRUSTSTAY (S_THRUSTSTAY+1)
|
||
|
S_NORMAL (TSPK, 'B', -1, NULL , &States[S_BTHRUSTSTAY]),
|
||
|
|
||
|
#define S_THRUSTINIT2 (S_BTHRUSTSTAY+1)
|
||
|
S_NORMAL (TSPK, 'A', 3, NULL , &States[S_THRUSTINIT2+1]),
|
||
|
S_NORMAL (TSPK, 'A', 4, A_ThrustInitUp , &States[S_THRUSTBLOCK]),
|
||
|
|
||
|
#define S_BTHRUSTINIT2 (S_THRUSTINIT2+2)
|
||
|
S_NORMAL (TSPK, 'B', 3, NULL , &States[S_BTHRUSTINIT2+1]),
|
||
|
S_NORMAL (TSPK, 'B', 4, A_ThrustInitUp , &States[S_BTHRUSTBLOCK]),
|
||
|
|
||
|
#define S_THRUSTINIT1 (S_BTHRUSTINIT2+2)
|
||
|
S_NORMAL (TSPK, 'A', 3, NULL , &States[S_THRUSTINIT1+1]),
|
||
|
S_NORMAL (TSPK, 'A', 4, A_ThrustInitDn , &States[S_THRUSTSTAY]),
|
||
|
|
||
|
#define S_BTHRUSTINIT1 (S_THRUSTINIT1+2)
|
||
|
S_NORMAL (TSPK, 'B', 3, NULL , &States[S_BTHRUSTINIT1+1]),
|
||
|
S_NORMAL (TSPK, 'B', 4, A_ThrustInitDn , &States[S_BTHRUSTSTAY]),
|
||
|
|
||
|
#define S_THRUSTRAISE (S_BTHRUSTINIT1+2)
|
||
|
S_NORMAL (TSPK, 'A', 8, A_ThrustRaise , &States[S_THRUSTRAISE+1]),
|
||
|
S_NORMAL (TSPK, 'A', 6, A_ThrustRaise , &States[S_THRUSTRAISE+2]),
|
||
|
S_NORMAL (TSPK, 'A', 4, A_ThrustRaise , &States[S_THRUSTRAISE+3]),
|
||
|
S_NORMAL (TSPK, 'A', 3, A_ThrustBlock , &States[S_THRUSTIMPALE]),
|
||
|
|
||
|
#define S_BTHRUSTRAISE (S_THRUSTRAISE+4)
|
||
|
S_NORMAL (TSPK, 'B', 8, A_ThrustRaise , &States[S_BTHRUSTRAISE+1]),
|
||
|
S_NORMAL (TSPK, 'B', 6, A_ThrustRaise , &States[S_BTHRUSTRAISE+2]),
|
||
|
S_NORMAL (TSPK, 'B', 4, A_ThrustRaise , &States[S_BTHRUSTRAISE+3]),
|
||
|
S_NORMAL (TSPK, 'B', 3, A_ThrustBlock , &States[S_BTHRUSTIMPALE]),
|
||
|
|
||
|
};
|
||
|
|
||
|
BEGIN_DEFAULTS (AThrustFloor, Hexen, -1, 0)
|
||
|
PROP_RadiusFixed (20)
|
||
|
PROP_HeightFixed (128)
|
||
|
END_DEFAULTS
|
||
|
|
||
|
void AThrustFloor::Activate (AActor *activator)
|
||
|
{
|
||
|
if (args[0] == 0)
|
||
|
{
|
||
|
S_Sound (this, CHAN_BODY, "ThrustSpikeLower", 1, ATTN_NORM);
|
||
|
renderflags &= ~RF_INVISIBLE;
|
||
|
if (args[1])
|
||
|
SetState (&States[S_BTHRUSTRAISE]);
|
||
|
else
|
||
|
SetState (&States[S_THRUSTRAISE]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void AThrustFloor::Deactivate (AActor *activator)
|
||
|
{
|
||
|
if (args[0] == 1)
|
||
|
{
|
||
|
S_Sound (this, CHAN_BODY, "ThrustSpikeRaise", 1, ATTN_NORM);
|
||
|
if (args[1])
|
||
|
SetState (&States[S_BTHRUSTLOWER]);
|
||
|
else
|
||
|
SetState (&States[S_THRUSTLOWER]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Spike up -----------------------------------------------------------------
|
||
|
|
||
|
class AThrustFloorUp : public AThrustFloor
|
||
|
{
|
||
|
DECLARE_STATELESS_ACTOR (AThrustFloorUp, AThrustFloor)
|
||
|
};
|
||
|
|
||
|
IMPLEMENT_STATELESS_ACTOR (AThrustFloorUp, Hexen, 10091, 104)
|
||
|
PROP_Flags (MF_SOLID)
|
||
|
PROP_Flags2 (MF2_NOTELEPORT|MF2_FLOORCLIP)
|
||
|
PROP_SpawnState (S_THRUSTINIT2)
|
||
|
END_DEFAULTS
|
||
|
|
||
|
// Spike down ---------------------------------------------------------------
|
||
|
|
||
|
class AThrustFloorDown : public AThrustFloor
|
||
|
{
|
||
|
DECLARE_STATELESS_ACTOR (AThrustFloorDown, AThrustFloor)
|
||
|
};
|
||
|
|
||
|
IMPLEMENT_STATELESS_ACTOR (AThrustFloorDown, Hexen, 10090, 105)
|
||
|
PROP_Flags2 (MF2_NOTELEPORT|MF2_FLOORCLIP)
|
||
|
PROP_RenderFlags (RF_INVISIBLE)
|
||
|
PROP_SpawnState (S_THRUSTINIT1)
|
||
|
END_DEFAULTS
|
||
|
|
||
|
//===========================================================================
|
||
|
//
|
||
|
// Thrust floor stuff
|
||
|
//
|
||
|
// Thrust Spike Variables
|
||
|
// DirtClump pointer to dirt clump actor
|
||
|
// special2 speed of raise
|
||
|
// args[0] 0 = lowered, 1 = raised
|
||
|
// args[1] 0 = normal, 1 = bloody
|
||
|
//===========================================================================
|
||
|
|
||
|
void A_ThrustInitUp (AActor *actor)
|
||
|
{
|
||
|
actor->special2 = 5; // Raise speed
|
||
|
actor->args[0] = 1; // Mark as up
|
||
|
actor->floorclip = 0;
|
||
|
actor->flags = MF_SOLID;
|
||
|
actor->flags2 = MF2_NOTELEPORT|MF2_FLOORCLIP;
|
||
|
actor->special1 = 0L;
|
||
|
}
|
||
|
|
||
|
void A_ThrustInitDn (AActor *actor)
|
||
|
{
|
||
|
actor->special2 = 5; // Raise speed
|
||
|
actor->args[0] = 0; // Mark as down
|
||
|
actor->floorclip = actor->GetDefault()->height;
|
||
|
actor->flags = 0;
|
||
|
actor->flags2 = MF2_NOTELEPORT|MF2_FLOORCLIP;
|
||
|
actor->renderflags = RF_INVISIBLE;
|
||
|
static_cast<AThrustFloor *>(actor)->DirtClump =
|
||
|
Spawn<ADirtClump> (actor->x, actor->y, actor->z);
|
||
|
}
|
||
|
|
||
|
|
||
|
void A_ThrustRaise (AActor *self)
|
||
|
{
|
||
|
AThrustFloor *actor = static_cast<AThrustFloor *>(self);
|
||
|
|
||
|
if (A_RaiseMobj (actor))
|
||
|
{ // Reached it's target height
|
||
|
actor->args[0] = 1;
|
||
|
if (actor->args[1])
|
||
|
actor->SetStateNF (&AThrustFloor::States[S_BTHRUSTINIT2]);
|
||
|
else
|
||
|
actor->SetStateNF (&AThrustFloor::States[S_THRUSTINIT2]);
|
||
|
}
|
||
|
|
||
|
// Lose the dirt clump
|
||
|
if ((actor->floorclip < actor->height) && actor->DirtClump)
|
||
|
{
|
||
|
actor->DirtClump->Destroy ();
|
||
|
actor->DirtClump = NULL;
|
||
|
}
|
||
|
|
||
|
// Spawn some dirt
|
||
|
if (pr_thrustraise()<40)
|
||
|
P_SpawnDirt (actor, actor->radius);
|
||
|
actor->special2++; // Increase raise speed
|
||
|
}
|
||
|
|
||
|
void A_ThrustLower (AActor *actor)
|
||
|
{
|
||
|
if (A_SinkMobj (actor))
|
||
|
{
|
||
|
actor->args[0] = 0;
|
||
|
if (actor->args[1])
|
||
|
actor->SetStateNF (&AThrustFloor::States[S_BTHRUSTINIT1]);
|
||
|
else
|
||
|
actor->SetStateNF (&AThrustFloor::States[S_THRUSTINIT1]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void A_ThrustBlock (AActor *actor)
|
||
|
{
|
||
|
actor->flags |= MF_SOLID;
|
||
|
}
|
||
|
|
||
|
void A_ThrustImpale (AActor *actor)
|
||
|
{
|
||
|
// Impale all shootables in radius
|
||
|
P_ThrustSpike (actor);
|
||
|
}
|
||
|
|