qzdoom-gpl/src/g_hexen/a_bishop.cpp
Christoph Oelckers 1983b5c586 - Changed action function definition so that they have to be defined with a
DEFINE_ACTION_FUNCTION macro. This should make it easier to improve the
  whole system.


SVN r1148 (trunk)
2008-08-10 20:48:55 +00:00

221 lines
5.5 KiB
C++

#include "actor.h"
#include "info.h"
#include "p_local.h"
#include "s_sound.h"
#include "p_enemy.h"
#include "a_action.h"
#include "m_random.h"
#include "a_hexenglobal.h"
#include "thingdef/thingdef.h"
static FRandom pr_boom ("BishopBoom");
static FRandom pr_atk ("BishopAttack");
static FRandom pr_decide ("BishopDecide");
static FRandom pr_doblur ("BishopDoBlur");
static FRandom pr_sblur ("BishopSpawnBlur");
static FRandom pr_pain ("BishopPainBlur");
//============================================================================
//
// A_BishopAttack
//
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_BishopAttack)
{
if (!self->target)
{
return;
}
S_Sound (self, CHAN_BODY, self->AttackSound, 1, ATTN_NORM);
if (self->CheckMeleeRange())
{
int damage = pr_atk.HitDice (4);
P_DamageMobj (self->target, self, self, damage, NAME_Melee);
P_TraceBleed (damage, self->target, self);
return;
}
self->special1 = (pr_atk() & 3) + 5;
}
//============================================================================
//
// A_BishopAttack2
//
// Spawns one of a string of bishop missiles
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_BishopAttack2)
{
AActor *mo;
if (!self->target || !self->special1)
{
self->special1 = 0;
self->SetState (self->SeeState);
return;
}
mo = P_SpawnMissile (self, self->target, PClass::FindClass("BishopFX"));
if (mo != NULL)
{
mo->tracer = self->target;
mo->special2 = 16; // High word == x/y, Low word == z
}
self->special1--;
}
//============================================================================
//
// A_BishopMissileWeave
//
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_BishopMissileWeave)
{
fixed_t newX, newY;
int weaveXY, weaveZ;
int angle;
if (self->special2 == 0) self->special2 = 16;
weaveXY = self->special2 >> 16;
weaveZ = self->special2 & 0xFFFF;
angle = (self->angle + ANG90) >> ANGLETOFINESHIFT;
newX = self->x - FixedMul (finecosine[angle], FloatBobOffsets[weaveXY]<<1);
newY = self->y - FixedMul (finesine[angle], FloatBobOffsets[weaveXY]<<1);
weaveXY = (weaveXY + 2) & 63;
newX += FixedMul (finecosine[angle], FloatBobOffsets[weaveXY]<<1);
newY += FixedMul (finesine[angle], FloatBobOffsets[weaveXY]<<1);
P_TryMove (self, newX, newY, true);
self->z -= FloatBobOffsets[weaveZ];
weaveZ = (weaveZ + 2) & 63;
self->z += FloatBobOffsets[weaveZ];
self->special2 = weaveZ + (weaveXY<<16);
}
//============================================================================
//
// A_BishopDecide
//
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_BishopDecide)
{
if (pr_decide() < 220)
{
return;
}
else
{
self->SetState (self->FindState ("Blur"));
}
}
//============================================================================
//
// A_BishopDoBlur
//
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_BishopDoBlur)
{
self->special1 = (pr_doblur() & 3) + 3; // Random number of blurs
if (pr_doblur() < 120)
{
P_ThrustMobj (self, self->angle + ANG90, 11*FRACUNIT);
}
else if (pr_doblur() > 125)
{
P_ThrustMobj (self, self->angle - ANG90, 11*FRACUNIT);
}
else
{ // Thrust forward
P_ThrustMobj (self, self->angle, 11*FRACUNIT);
}
S_Sound (self, CHAN_BODY, "BishopBlur", 1, ATTN_NORM);
}
//============================================================================
//
// A_BishopSpawnBlur
//
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_BishopSpawnBlur)
{
AActor *mo;
if (!--self->special1)
{
self->momx = 0;
self->momy = 0;
if (pr_sblur() > 96)
{
self->SetState (self->SeeState);
}
else
{
self->SetState (self->MissileState);
}
}
mo = Spawn ("BishopBlur", self->x, self->y, self->z, ALLOW_REPLACE);
if (mo)
{
mo->angle = self->angle;
}
}
//============================================================================
//
// A_BishopChase
//
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_BishopChase)
{
self->z -= FloatBobOffsets[self->special2] >> 1;
self->special2 = (self->special2 + 4) & 63;
self->z += FloatBobOffsets[self->special2] >> 1;
}
//============================================================================
//
// A_BishopPuff
//
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_BishopPuff)
{
AActor *mo;
mo = Spawn ("BishopPuff", self->x, self->y, self->z + 40*FRACUNIT, ALLOW_REPLACE);
if (mo)
{
mo->momz = FRACUNIT/2;
}
}
//============================================================================
//
// A_BishopPainBlur
//
//============================================================================
DEFINE_ACTION_FUNCTION(AActor, A_BishopPainBlur)
{
AActor *mo;
if (pr_pain() < 64)
{
self->SetState (self->FindState ("Blur"));
return;
}
fixed_t x = self->x + (pr_pain.Random2()<<12);
fixed_t y = self->y + (pr_pain.Random2()<<12);
fixed_t z = self->z + (pr_pain.Random2()<<11);
mo = Spawn ("BishopPainBlur", x, y, z, ALLOW_REPLACE);
if (mo)
{
mo->angle = self->angle;
}
}