mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-08 14:01:32 +00:00
212 lines
6.1 KiB
C++
212 lines
6.1 KiB
C++
#include "actor.h"
|
|
#include "p_enemy.h"
|
|
#include "a_action.h"
|
|
#include "s_sound.h"
|
|
#include "p_local.h"
|
|
|
|
void A_TossGib (AActor *);
|
|
|
|
// Bishop -------------------------------------------------------------------
|
|
|
|
void A_SBishopAttack (AActor *);
|
|
void A_SpawnSpectre2 (AActor *);
|
|
|
|
class AStrifeBishop : public AActor
|
|
{
|
|
DECLARE_ACTOR (AStrifeBishop, AActor)
|
|
public:
|
|
void GetExplodeParms (int &damage, int &dist, bool &hurtSource)
|
|
{
|
|
damage = dist = 64;
|
|
}
|
|
void NoBlockingSet ()
|
|
{
|
|
P_DropItem (this, "CrateOfMissiles", 20, 256);
|
|
}
|
|
};
|
|
|
|
FState AStrifeBishop::States[] =
|
|
{
|
|
#define S_BISHOP_STND 0
|
|
S_NORMAL (MLDR, 'A', 10, A_Look, &States[S_BISHOP_STND]),
|
|
|
|
#define S_BISHOP_RUN (S_BISHOP_STND+1)
|
|
S_NORMAL (MLDR, 'A', 3, A_Chase, &States[S_BISHOP_RUN+1]),
|
|
S_NORMAL (MLDR, 'A', 3, A_Chase, &States[S_BISHOP_RUN+2]),
|
|
S_NORMAL (MLDR, 'B', 3, A_Chase, &States[S_BISHOP_RUN+3]),
|
|
S_NORMAL (MLDR, 'B', 3, A_Chase, &States[S_BISHOP_RUN+4]),
|
|
S_NORMAL (MLDR, 'C', 3, A_Chase, &States[S_BISHOP_RUN+5]),
|
|
S_NORMAL (MLDR, 'C', 3, A_Chase, &States[S_BISHOP_RUN+6]),
|
|
S_NORMAL (MLDR, 'D', 3, A_Chase, &States[S_BISHOP_RUN+7]),
|
|
S_NORMAL (MLDR, 'D', 3, A_Chase, &States[S_BISHOP_RUN]),
|
|
|
|
#define S_BISHOP_ATK (S_BISHOP_RUN+8)
|
|
S_NORMAL (MLDR, 'E', 3, A_FaceTarget, &States[S_BISHOP_ATK+1]),
|
|
S_BRIGHT (MLDR, 'F', 2, A_SBishopAttack, &States[S_BISHOP_RUN]),
|
|
|
|
#define S_BISHOP_PAIN (S_BISHOP_ATK+2)
|
|
S_NORMAL (MLDR, 'D', 1, A_Pain, &States[S_BISHOP_RUN]),
|
|
|
|
#define S_BISHOP_DIE (S_BISHOP_PAIN+1)
|
|
S_BRIGHT (MLDR, 'G', 3, NULL, &States[S_BISHOP_DIE+1]),
|
|
S_BRIGHT (MLDR, 'H', 5, A_Scream, &States[S_BISHOP_DIE+2]),
|
|
S_BRIGHT (MLDR, 'I', 4, A_TossGib, &States[S_BISHOP_DIE+3]),
|
|
S_BRIGHT (MLDR, 'J', 4, A_ExplodeAndAlert, &States[S_BISHOP_DIE+4]),
|
|
S_BRIGHT (MLDR, 'K', 4, NULL, &States[S_BISHOP_DIE+5]),
|
|
S_BRIGHT (MLDR, 'L', 4, NULL, &States[S_BISHOP_DIE+6]),
|
|
S_BRIGHT (MLDR, 'M', 4, A_NoBlocking, &States[S_BISHOP_DIE+7]),
|
|
S_BRIGHT (MLDR, 'N', 4, NULL, &States[S_BISHOP_DIE+8]),
|
|
S_BRIGHT (MLDR, 'O', 4, A_TossGib, &States[S_BISHOP_DIE+9]),
|
|
S_BRIGHT (MLDR, 'P', 4, NULL, &States[S_BISHOP_DIE+10]),
|
|
S_BRIGHT (MLDR, 'Q', 4, A_TossGib, &States[S_BISHOP_DIE+11]),
|
|
S_BRIGHT (MLDR, 'R', 4, NULL, &States[S_BISHOP_DIE+12]),
|
|
S_BRIGHT (MLDR, 'S', 4, A_TossGib, &States[S_BISHOP_DIE+13]),
|
|
S_BRIGHT (MLDR, 'T', 4, NULL, &States[S_BISHOP_DIE+14]),
|
|
S_BRIGHT (MLDR, 'U', 4, A_TossGib, &States[S_BISHOP_DIE+15]),
|
|
S_BRIGHT (MLDR, 'V', 4, A_SpawnSpectre2, NULL),
|
|
};
|
|
|
|
IMPLEMENT_ACTOR (AStrifeBishop, Strife, 187, 0)
|
|
PROP_SpawnState (S_BISHOP_STND)
|
|
PROP_SeeState (S_BISHOP_RUN)
|
|
PROP_PainState (S_BISHOP_PAIN)
|
|
PROP_MissileState (S_BISHOP_ATK)
|
|
PROP_DeathState (S_BISHOP_DIE)
|
|
|
|
PROP_SpawnHealth (500)
|
|
PROP_PainChance (128)
|
|
PROP_SpeedFixed (8)
|
|
PROP_RadiusFixed (40)
|
|
PROP_HeightFixed (56)
|
|
PROP_Mass (500)
|
|
PROP_Flags (MF_SOLID|MF_SHOOTABLE|MF_NOBLOOD|MF_COUNTKILL|MF_NOTDMATCH)
|
|
PROP_Flags2 (MF2_FLOORCLIP|MF2_PASSMOBJ|MF2_PUSHWALL|MF2_MCROSS)
|
|
PROP_Flags4 (MF4_INCOMBAT|MF4_FIRERESIST|MF4_NOICEDEATH)
|
|
PROP_MinMissileChance (150)
|
|
PROP_MaxDropOffHeight (32)
|
|
PROP_StrifeType (64)
|
|
PROP_SeeSound ("bishop/sight")
|
|
PROP_PainSound ("bishop/pain")
|
|
PROP_DeathSound ("bishop/death")
|
|
PROP_ActiveSound ("bishop/active")
|
|
END_DEFAULTS
|
|
|
|
// The Bishop's missile -----------------------------------------------------
|
|
|
|
void A_RocketInFlight (AActor *);
|
|
void A_Tracer2 (AActor *);
|
|
|
|
class ABishopMissile : public AActor
|
|
{
|
|
DECLARE_ACTOR (ABishopMissile, AActor)
|
|
public:
|
|
void PreExplode ()
|
|
{
|
|
RenderStyle = STYLE_Add;
|
|
S_StopSound (this, CHAN_VOICE);
|
|
}
|
|
void GetExplodeParms (int &damage, int &dist, bool &hurtSource)
|
|
{
|
|
damage = dist = 64;
|
|
}
|
|
};
|
|
|
|
FState ABishopMissile::States[] =
|
|
{
|
|
S_BRIGHT (MISS, 'A', 4, A_RocketInFlight, &States[1]),
|
|
S_BRIGHT (MISS, 'B', 3, A_Tracer2, &States[0]),
|
|
|
|
S_BRIGHT (SMIS, 'A', 5, A_ExplodeAndAlert, &States[3]),
|
|
S_BRIGHT (SMIS, 'B', 5, NULL, &States[4]),
|
|
S_BRIGHT (SMIS, 'C', 4, NULL, &States[5]),
|
|
S_BRIGHT (SMIS, 'D', 2, NULL, &States[6]),
|
|
S_BRIGHT (SMIS, 'E', 2, NULL, &States[7]),
|
|
S_BRIGHT (SMIS, 'F', 2, NULL, &States[8]),
|
|
S_BRIGHT (SMIS, 'G', 2, NULL, NULL),
|
|
};
|
|
|
|
IMPLEMENT_ACTOR (ABishopMissile, Strife, -1, 0)
|
|
PROP_SpawnState (0)
|
|
PROP_DeathState (2)
|
|
PROP_SpeedFixed (20)
|
|
PROP_RadiusFixed (10)
|
|
PROP_HeightFixed (14)
|
|
PROP_Damage (10)
|
|
PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE)
|
|
PROP_Flags2 (MF2_NOTELEPORT|MF2_PCROSS|MF2_IMPACT|MF2_SEEKERMISSILE)
|
|
PROP_Flags4 (MF4_STRIFEDAMAGE)
|
|
PROP_MaxStepHeight (4)
|
|
PROP_SeeSound ("bishop/misl")
|
|
PROP_DeathSound ("bishop/mislx")
|
|
END_DEFAULTS
|
|
|
|
void A_SBishopAttack (AActor *self)
|
|
{
|
|
if (self->target != NULL)
|
|
{
|
|
AActor *missile = P_SpawnMissileZ (self, self->z + 64*FRACUNIT, self->target, RUNTIME_CLASS(ABishopMissile));
|
|
|
|
if (missile != NULL)
|
|
{
|
|
missile->tracer = self->target;
|
|
}
|
|
}
|
|
}
|
|
|
|
// In Strife, this number is stored in the data segment, but it doesn't seem to be
|
|
// altered anywhere.
|
|
#define TRACEANGLE (0xe000000)
|
|
|
|
void A_Tracer2 (AActor *self)
|
|
{
|
|
AActor *dest;
|
|
angle_t exact;
|
|
fixed_t dist;
|
|
fixed_t slope;
|
|
|
|
dest = self->tracer;
|
|
|
|
if (dest == NULL || dest->health <= 0)
|
|
return;
|
|
|
|
// change angle
|
|
exact = R_PointToAngle2 (self->x, self->y, dest->x, dest->y);
|
|
|
|
if (exact != self->angle)
|
|
{
|
|
if (exact - self->angle > 0x80000000)
|
|
{
|
|
self->angle -= TRACEANGLE;
|
|
if (exact - self->angle < 0x80000000)
|
|
self->angle = exact;
|
|
}
|
|
else
|
|
{
|
|
self->angle += TRACEANGLE;
|
|
if (exact - self->angle > 0x80000000)
|
|
self->angle = exact;
|
|
}
|
|
}
|
|
|
|
exact = self->angle >> ANGLETOFINESHIFT;
|
|
self->momx = FixedMul (self->Speed, finecosine[exact]);
|
|
self->momy = FixedMul (self->Speed, finesine[exact]);
|
|
|
|
// change slope
|
|
dist = P_AproxDistance (dest->x - self->x, dest->y - self->y);
|
|
dist /= self->Speed;
|
|
|
|
if (dist < 1)
|
|
{
|
|
dist = 1;
|
|
}
|
|
slope = (dest->z + 40*FRACUNIT - self->z) / dist;
|
|
if (slope < self->momz)
|
|
{
|
|
self->momz -= FRACUNIT/8;
|
|
}
|
|
else
|
|
{
|
|
self->momz += FRACUNIT/8;
|
|
}
|
|
}
|