2016-03-01 15:47:10 +00:00
|
|
|
/*
|
|
|
|
#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 "thingdef/thingdef.h"
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define FIREDEMON_ATTACK_RANGE 64*8*FRACUNIT
|
|
|
|
|
|
|
|
static FRandom pr_firedemonrock ("FireDemonRock");
|
|
|
|
static FRandom pr_smbounce ("SMBounce");
|
|
|
|
static FRandom pr_firedemonchase ("FiredChase");
|
|
|
|
static FRandom pr_firedemonsplotch ("FiredSplotch");
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
// Fire Demon AI
|
|
|
|
//
|
|
|
|
// special1 index into floatbob
|
|
|
|
// special2 whether strafing or not
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_FiredSpawnRock
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
void A_FiredSpawnRock (AActor *actor)
|
|
|
|
{
|
|
|
|
AActor *mo;
|
|
|
|
PClassActor *rtype;
|
|
|
|
|
|
|
|
switch (pr_firedemonrock() % 5)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
rtype = PClass::FindActor("FireDemonRock1");
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
rtype = PClass::FindActor("FireDemonRock2");
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
rtype = PClass::FindActor("FireDemonRock3");
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
rtype = PClass::FindActor("FireDemonRock4");
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
default:
|
|
|
|
rtype = PClass::FindActor("FireDemonRock5");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
fixed_t xo = ((pr_firedemonrock() - 128) << 12);
|
|
|
|
fixed_t yo = ((pr_firedemonrock() - 128) << 12);
|
|
|
|
fixed_t zo = (pr_firedemonrock() << 11);
|
|
|
|
mo = Spawn (rtype, actor->Vec3Offset(xo, yo, zo), ALLOW_REPLACE);
|
|
|
|
if (mo)
|
|
|
|
{
|
|
|
|
mo->target = actor;
|
2016-03-19 23:54:18 +00:00
|
|
|
mo->Vel.X = (pr_firedemonrock() - 128) / 64.;
|
|
|
|
mo->Vel.Y = (pr_firedemonrock() - 128) / 64.;
|
|
|
|
mo->Vel.Z = (pr_firedemonrock() / 64.);
|
2016-03-01 15:47:10 +00:00
|
|
|
mo->special1 = 2; // Number bounces
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize fire demon
|
|
|
|
actor->special2 = 0;
|
|
|
|
actor->flags &= ~MF_JUSTATTACKED;
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_FiredRocks
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_FiredRocks)
|
|
|
|
{
|
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
|
|
|
|
A_FiredSpawnRock (self);
|
|
|
|
A_FiredSpawnRock (self);
|
|
|
|
A_FiredSpawnRock (self);
|
|
|
|
A_FiredSpawnRock (self);
|
|
|
|
A_FiredSpawnRock (self);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_SmBounce
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_SmBounce)
|
|
|
|
{
|
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
|
|
|
|
// give some more velocity (x,y,&z)
|
2016-03-19 23:54:18 +00:00
|
|
|
self->_f_SetZ(self->floorz + FRACUNIT);
|
|
|
|
self->Vel.Z = 2. + pr_smbounce() / 64.;
|
|
|
|
self->Vel.X = pr_smbounce() % 3;
|
|
|
|
self->Vel.Y = pr_smbounce() % 3;
|
2016-03-01 15:47:10 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_FiredAttack
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_FiredAttack)
|
|
|
|
{
|
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
|
|
|
|
if (self->target == NULL)
|
|
|
|
return 0;
|
|
|
|
AActor *mo = P_SpawnMissile (self, self->target, PClass::FindActor("FireDemonMissile"));
|
|
|
|
if (mo) S_Sound (self, CHAN_BODY, "FireDemonAttack", 1, ATTN_NORM);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_FiredChase
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_FiredChase)
|
|
|
|
{
|
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
|
|
|
|
int weaveindex = self->special1;
|
|
|
|
AActor *target = self->target;
|
2016-03-19 23:54:18 +00:00
|
|
|
DAngle ang;
|
2016-03-01 15:47:10 +00:00
|
|
|
fixed_t dist;
|
|
|
|
|
|
|
|
if (self->reactiontime) self->reactiontime--;
|
|
|
|
if (self->threshold) self->threshold--;
|
|
|
|
|
|
|
|
// Float up and down
|
2016-03-19 23:54:18 +00:00
|
|
|
self->_f_AddZ(finesine[weaveindex << BOBTOFINESHIFT] * 8);
|
2016-03-01 15:47:10 +00:00
|
|
|
self->special1 = (weaveindex + 2) & 63;
|
|
|
|
|
|
|
|
// Ensure it stays above certain height
|
2016-03-19 23:54:18 +00:00
|
|
|
if (self->_f_Z() < self->floorz + (64*FRACUNIT))
|
2016-03-01 15:47:10 +00:00
|
|
|
{
|
2016-03-19 23:54:18 +00:00
|
|
|
self->_f_AddZ(2*FRACUNIT);
|
2016-03-01 15:47:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(!self->target || !(self->target->flags&MF_SHOOTABLE))
|
|
|
|
{ // Invalid target
|
|
|
|
P_LookForPlayers (self,true, NULL);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Strafe
|
|
|
|
if (self->special2 > 0)
|
|
|
|
{
|
|
|
|
self->special2--;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
self->special2 = 0;
|
2016-03-19 23:54:18 +00:00
|
|
|
self->Vel.X = self->Vel.Y = 0;
|
2016-03-01 15:47:10 +00:00
|
|
|
dist = self->AproxDistance (target);
|
|
|
|
if (dist < FIREDEMON_ATTACK_RANGE)
|
|
|
|
{
|
|
|
|
if (pr_firedemonchase() < 30)
|
|
|
|
{
|
2016-03-19 23:54:18 +00:00
|
|
|
ang = self->AngleTo(target);
|
2016-03-01 15:47:10 +00:00
|
|
|
if (pr_firedemonchase() < 128)
|
2016-03-19 23:54:18 +00:00
|
|
|
ang += 90;
|
2016-03-01 15:47:10 +00:00
|
|
|
else
|
2016-03-19 23:54:18 +00:00
|
|
|
ang -= 90;
|
|
|
|
self->Thrust(ang, 8);
|
2016-03-01 15:47:10 +00:00
|
|
|
self->special2 = 3; // strafe time
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FaceMovementDirection (self);
|
|
|
|
|
|
|
|
// Normal movement
|
|
|
|
if (!self->special2)
|
|
|
|
{
|
|
|
|
if (--self->movecount<0 || !P_Move (self))
|
|
|
|
{
|
|
|
|
P_NewChaseDir (self);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do missile attack
|
|
|
|
if (!(self->flags & MF_JUSTATTACKED))
|
|
|
|
{
|
|
|
|
if (P_CheckMissileRange (self) && (pr_firedemonchase() < 20))
|
|
|
|
{
|
|
|
|
self->SetState (self->MissileState);
|
|
|
|
self->flags |= MF_JUSTATTACKED;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
self->flags &= ~MF_JUSTATTACKED;
|
|
|
|
}
|
|
|
|
|
|
|
|
// make active sound
|
|
|
|
if (pr_firedemonchase() < 3)
|
|
|
|
{
|
|
|
|
self->PlayActiveSound ();
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_FiredSplotch
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_FiredSplotch)
|
|
|
|
{
|
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
|
|
|
|
AActor *mo;
|
|
|
|
|
|
|
|
mo = Spawn ("FireDemonSplotch1", self->Pos(), ALLOW_REPLACE);
|
|
|
|
if (mo)
|
|
|
|
{
|
2016-03-19 23:54:18 +00:00
|
|
|
mo->Vel.X = (pr_firedemonsplotch() - 128) / 32.;
|
|
|
|
mo->Vel.Y = (pr_firedemonsplotch() - 128) / 32.;
|
|
|
|
mo->Vel.Z = (pr_firedemonsplotch() / 64.) + 3;
|
2016-03-01 15:47:10 +00:00
|
|
|
}
|
|
|
|
mo = Spawn ("FireDemonSplotch2", self->Pos(), ALLOW_REPLACE);
|
|
|
|
if (mo)
|
|
|
|
{
|
2016-03-19 23:54:18 +00:00
|
|
|
mo->Vel.X = (pr_firedemonsplotch() - 128) / 32.;
|
|
|
|
mo->Vel.Y = (pr_firedemonsplotch() - 128) / 32.;
|
|
|
|
mo->Vel.Z = (pr_firedemonsplotch() / 64.) + 3;
|
2016-03-01 15:47:10 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|