mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-12 15:44:24 +00:00
218 lines
5.5 KiB
C++
218 lines
5.5 KiB
C++
#include "actor.h"
|
|
#include "info.h"
|
|
#include "gi.h"
|
|
#include "m_random.h"
|
|
|
|
static FRandom pr_orbit ("Orbit");
|
|
|
|
void A_BridgeOrbit (AActor *);
|
|
void A_BridgeInit (AActor *);
|
|
|
|
// The Hexen (and Heretic) version of the bridge spawns extra floating
|
|
// "balls" orbiting the bridge. The Doom version only shows the bridge
|
|
// itself.
|
|
|
|
// Bridge ball -------------------------------------------------------------
|
|
|
|
class ABridgeBall : public AActor
|
|
{
|
|
DECLARE_ACTOR (ABridgeBall, AActor)
|
|
};
|
|
|
|
FState ABridgeBall::States[] =
|
|
{
|
|
S_NORMAL (TLGL, 'A', 2, NULL , &States[1]),
|
|
S_NORMAL (TLGL, 'A', 1, A_BridgeOrbit , &States[1])
|
|
};
|
|
|
|
IMPLEMENT_ACTOR (ABridgeBall, Any, -1, 0)
|
|
PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY)
|
|
PROP_Flags2 (MF2_NOTELEPORT)
|
|
PROP_SpawnState (0)
|
|
END_DEFAULTS
|
|
|
|
// The bridge itself -------------------------------------------------------
|
|
|
|
class ABridge : public AActor
|
|
{
|
|
DECLARE_ACTOR (ABridge, AActor)
|
|
};
|
|
|
|
FState ABridge::States[] =
|
|
{
|
|
#define S_DBRIDGE 0
|
|
S_BRIGHT (TLGL, 'A', 4, NULL , &States[S_DBRIDGE+1]),
|
|
S_BRIGHT (TLGL, 'B', 4, NULL , &States[S_DBRIDGE+2]),
|
|
S_BRIGHT (TLGL, 'C', 4, NULL , &States[S_DBRIDGE+3]),
|
|
S_BRIGHT (TLGL, 'D', 4, NULL , &States[S_DBRIDGE+4]),
|
|
S_BRIGHT (TLGL, 'E', 4, NULL , &States[S_DBRIDGE+0]),
|
|
|
|
#define S_BRIDGE (S_DBRIDGE+5)
|
|
S_NORMAL (TLGL, 'A', 2, NULL , &States[S_BRIDGE+1]),
|
|
S_NORMAL (TLGL, 'A', 2, A_BridgeInit , &States[S_BRIDGE+2]),
|
|
S_NORMAL (TLGL, 'A', -1, NULL , NULL),
|
|
|
|
#define S_FREE_BRIDGE (S_BRIDGE+3)
|
|
S_NORMAL (TLGL, 'A', 2, NULL , &States[S_FREE_BRIDGE+1]),
|
|
S_NORMAL (TLGL, 'A', 300, NULL , NULL)
|
|
};
|
|
|
|
IMPLEMENT_ACTOR (ABridge, Any, 118, 21)
|
|
PROP_Flags (MF_SOLID|MF_NOGRAVITY|MF_NOLIFTDROP)
|
|
END_DEFAULTS
|
|
|
|
AT_GAME_SET (Bridge)
|
|
{
|
|
ABridge *def = GetDefault<ABridge> ();
|
|
|
|
if (gameinfo.gametype == GAME_Doom)
|
|
{
|
|
def->SpawnState = &ABridge::States[S_DBRIDGE];
|
|
def->radius = 36 * FRACUNIT;
|
|
def->height = 4 * FRACUNIT;
|
|
def->RenderStyle = STYLE_Normal;
|
|
}
|
|
else
|
|
{
|
|
def->SpawnState = &ABridge::States[S_BRIDGE];
|
|
def->radius = 32 * FRACUNIT;
|
|
def->height = 2 * FRACUNIT;
|
|
def->RenderStyle = STYLE_None;
|
|
}
|
|
}
|
|
|
|
// Action functions for the non-Doom bridge --------------------------------
|
|
|
|
#define ORBIT_RADIUS 15
|
|
|
|
// New bridge stuff
|
|
// Parent
|
|
// special1 true == removing from world
|
|
//
|
|
// Child
|
|
// target pointer to center mobj
|
|
// angle angle of ball
|
|
|
|
void A_BridgeOrbit (AActor *self)
|
|
{
|
|
if (self->target == NULL)
|
|
{ // Don't crash if somebody spawned this into the world
|
|
// independantly of a Bridge actor.
|
|
return;
|
|
}
|
|
if (self->target->special1)
|
|
{
|
|
self->SetState (NULL);
|
|
}
|
|
// Every five tics, Hexen moved the ball 3/256th of a revolution.
|
|
self->angle += ANGLE_45/32*3/5;
|
|
self->x = self->target->x + ORBIT_RADIUS * finecosine[self->angle >> ANGLETOFINESHIFT];
|
|
self->y = self->target->y + ORBIT_RADIUS * finesine[self->angle >> ANGLETOFINESHIFT];
|
|
self->z = self->target->z;
|
|
}
|
|
|
|
void A_BridgeInit (AActor *self)
|
|
{
|
|
angle_t startangle;
|
|
AActor *ball1, *ball2, *ball3;
|
|
fixed_t cx, cy, cz;
|
|
|
|
cx = self->x;
|
|
cy = self->y;
|
|
cz = self->z;
|
|
startangle = pr_orbit() << 24;
|
|
self->special1 = 0;
|
|
|
|
// Spawn triad into world
|
|
ball1 = Spawn<ABridgeBall> (cx, cy, cz, ALLOW_REPLACE);
|
|
ball1->angle = startangle;
|
|
ball1->target = self;
|
|
|
|
ball2 = Spawn<ABridgeBall> (cx, cy, cz, ALLOW_REPLACE);
|
|
ball2->angle = startangle + ANGLE_45/32*85;
|
|
ball2->target = self;
|
|
|
|
ball3 = Spawn<ABridgeBall> (cx, cy, cz, ALLOW_REPLACE);
|
|
ball3->angle = startangle + (angle_t)ANGLE_45/32*170;
|
|
ball3->target = self;
|
|
|
|
A_BridgeOrbit (ball1);
|
|
A_BridgeOrbit (ball2);
|
|
A_BridgeOrbit (ball3);
|
|
}
|
|
|
|
void A_BridgeRemove (AActor *self)
|
|
{
|
|
self->special1 = true; // Removing the bridge
|
|
self->flags &= ~MF_SOLID;
|
|
self->SetState (&ABridge::States[S_FREE_BRIDGE]);
|
|
}
|
|
|
|
// Invisible bridge --------------------------------------------------------
|
|
|
|
class AInvisibleBridge : public ABridge
|
|
{
|
|
DECLARE_ACTOR (AInvisibleBridge, ABridge)
|
|
public:
|
|
void BeginPlay ();
|
|
void Tick ()
|
|
{
|
|
Super::Tick ();
|
|
}
|
|
};
|
|
|
|
FState AInvisibleBridge::States[] =
|
|
{
|
|
S_NORMAL (TNT1, 'A', -1, NULL, NULL)
|
|
};
|
|
|
|
IMPLEMENT_ACTOR (AInvisibleBridge, Any, 9990, 0)
|
|
PROP_RenderStyle (STYLE_None)
|
|
PROP_SpawnState (0)
|
|
PROP_RadiusFixed (32)
|
|
PROP_HeightFixed (4)
|
|
PROP_Flags4 (MF4_ACTLIKEBRIDGE)
|
|
END_DEFAULTS
|
|
|
|
void AInvisibleBridge::BeginPlay ()
|
|
{
|
|
Super::BeginPlay ();
|
|
if (args[0])
|
|
radius = args[0] << FRACBITS;
|
|
if (args[1])
|
|
height = args[1] << FRACBITS;
|
|
}
|
|
|
|
// And some invisible bridges from Skull Tag -------------------------------
|
|
|
|
class AInvisibleBridge32 : public AInvisibleBridge
|
|
{
|
|
DECLARE_STATELESS_ACTOR (AInvisibleBridge32, AInvisibleBridge)
|
|
};
|
|
|
|
IMPLEMENT_STATELESS_ACTOR (AInvisibleBridge32, Any, 5061, 0)
|
|
PROP_RadiusFixed (32)
|
|
PROP_HeightFixed (8)
|
|
END_DEFAULTS
|
|
|
|
|
|
class AInvisibleBridge16 : public AInvisibleBridge
|
|
{
|
|
DECLARE_STATELESS_ACTOR (AInvisibleBridge16, AInvisibleBridge)
|
|
};
|
|
|
|
IMPLEMENT_STATELESS_ACTOR (AInvisibleBridge16, Any, 5064, 0)
|
|
PROP_RadiusFixed (16)
|
|
PROP_HeightFixed (8)
|
|
END_DEFAULTS
|
|
|
|
|
|
class AInvisibleBridge8 : public AInvisibleBridge
|
|
{
|
|
DECLARE_STATELESS_ACTOR (AInvisibleBridge8, AInvisibleBridge)
|
|
};
|
|
|
|
IMPLEMENT_STATELESS_ACTOR (AInvisibleBridge8, Any, 5065, 0)
|
|
PROP_RadiusFixed (8)
|
|
PROP_HeightFixed (8)
|
|
END_DEFAULTS
|