2006-02-24 04:48:15 +00:00
|
|
|
#include "actor.h"
|
|
|
|
#include "gi.h"
|
|
|
|
#include "m_random.h"
|
|
|
|
#include "s_sound.h"
|
|
|
|
#include "d_player.h"
|
|
|
|
#include "a_action.h"
|
|
|
|
#include "p_local.h"
|
|
|
|
#include "p_enemy.h"
|
|
|
|
#include "a_action.h"
|
|
|
|
#include "p_pspr.h"
|
|
|
|
#include "gstrings.h"
|
|
|
|
#include "a_hexenglobal.h"
|
2008-08-10 20:48:55 +00:00
|
|
|
#include "thingdef/thingdef.h"
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
static FRandom pr_staffcheck ("CStaffCheck");
|
|
|
|
static FRandom pr_blink ("CStaffBlink");
|
|
|
|
|
|
|
|
// Serpent Staff Missile ----------------------------------------------------
|
|
|
|
|
|
|
|
class ACStaffMissile : public AActor
|
|
|
|
{
|
2008-08-05 16:04:37 +00:00
|
|
|
DECLARE_CLASS (ACStaffMissile, AActor)
|
2006-02-24 04:48:15 +00:00
|
|
|
public:
|
|
|
|
int DoSpecialDamage (AActor *target, int damage);
|
|
|
|
};
|
|
|
|
|
2008-08-05 16:04:37 +00:00
|
|
|
IMPLEMENT_CLASS (ACStaffMissile)
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
int ACStaffMissile::DoSpecialDamage (AActor *target, int damage)
|
|
|
|
{
|
|
|
|
// Cleric Serpent Staff does poison damage
|
|
|
|
if (target->player)
|
|
|
|
{
|
|
|
|
P_PoisonPlayer (target->player, this, this->target, 20);
|
|
|
|
damage >>= 1;
|
|
|
|
}
|
|
|
|
return damage;
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_CStaffCheck
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
AActor *pmo;
|
|
|
|
int damage;
|
|
|
|
int newLife;
|
|
|
|
angle_t angle;
|
|
|
|
int slope;
|
|
|
|
int i;
|
|
|
|
player_t *player;
|
2008-04-10 14:38:43 +00:00
|
|
|
AActor *linetarget;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
if (NULL == (player = self->player))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2008-08-10 20:48:55 +00:00
|
|
|
AWeapon *weapon = self->player->ReadyWeapon;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
pmo = player->mo;
|
|
|
|
damage = 20+(pr_staffcheck()&15);
|
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
angle = pmo->angle+i*(ANG45/16);
|
2008-04-10 14:38:43 +00:00
|
|
|
slope = P_AimLineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), &linetarget);
|
2006-02-24 04:48:15 +00:00
|
|
|
if (linetarget)
|
|
|
|
{
|
2008-08-05 16:04:37 +00:00
|
|
|
P_LineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, PClass::FindClass ("CStaffPuff"));
|
2006-02-24 04:48:15 +00:00
|
|
|
pmo->angle = R_PointToAngle2 (pmo->x, pmo->y,
|
|
|
|
linetarget->x, linetarget->y);
|
|
|
|
if ((linetarget->player || linetarget->flags3&MF3_ISMONSTER)
|
|
|
|
&& (!(linetarget->flags2&(MF2_DORMANT+MF2_INVULNERABLE))))
|
|
|
|
{
|
|
|
|
newLife = player->health+(damage>>3);
|
|
|
|
newLife = newLife > 100 ? 100 : newLife;
|
|
|
|
if (newLife > player->health)
|
|
|
|
{
|
|
|
|
pmo->health = player->health = newLife;
|
|
|
|
}
|
2008-08-05 16:04:37 +00:00
|
|
|
P_SetPsprite (player, ps_weapon, weapon->FindState ("Drain"));
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
if (weapon != NULL)
|
|
|
|
{
|
|
|
|
weapon->DepleteAmmo (weapon->bAltFire, false);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
angle = pmo->angle-i*(ANG45/16);
|
2008-04-10 14:38:43 +00:00
|
|
|
slope = P_AimLineAttack (player->mo, angle, fixed_t(1.5*MELEERANGE), &linetarget);
|
2006-02-24 04:48:15 +00:00
|
|
|
if (linetarget)
|
|
|
|
{
|
2008-08-05 16:04:37 +00:00
|
|
|
P_LineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, PClass::FindClass ("CStaffPuff"));
|
2006-02-24 04:48:15 +00:00
|
|
|
pmo->angle = R_PointToAngle2 (pmo->x, pmo->y,
|
|
|
|
linetarget->x, linetarget->y);
|
|
|
|
if (linetarget->player || linetarget->flags3&MF3_ISMONSTER)
|
|
|
|
{
|
|
|
|
newLife = player->health+(damage>>4);
|
|
|
|
newLife = newLife > 100 ? 100 : newLife;
|
|
|
|
pmo->health = player->health = newLife;
|
2008-08-05 16:04:37 +00:00
|
|
|
P_SetPsprite (player, ps_weapon, weapon->FindState ("Drain"));
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
weapon->DepleteAmmo (weapon->bAltFire, false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_CStaffAttack
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_CStaffAttack)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
AActor *mo;
|
|
|
|
player_t *player;
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
if (NULL == (player = self->player))
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
AWeapon *weapon = self->player->ReadyWeapon;
|
2006-02-24 04:48:15 +00:00
|
|
|
if (weapon != NULL)
|
|
|
|
{
|
|
|
|
if (!weapon->DepleteAmmo (weapon->bAltFire))
|
|
|
|
return;
|
|
|
|
}
|
2008-08-10 20:48:55 +00:00
|
|
|
mo = P_SpawnPlayerMissile (self, RUNTIME_CLASS(ACStaffMissile), self->angle-(ANG45/15));
|
2006-02-24 04:48:15 +00:00
|
|
|
if (mo)
|
|
|
|
{
|
|
|
|
mo->special2 = 32;
|
|
|
|
}
|
2008-08-10 20:48:55 +00:00
|
|
|
mo = P_SpawnPlayerMissile (self, RUNTIME_CLASS(ACStaffMissile), self->angle+(ANG45/15));
|
2006-02-24 04:48:15 +00:00
|
|
|
if (mo)
|
|
|
|
{
|
|
|
|
mo->special2 = 0;
|
|
|
|
}
|
2008-08-10 20:48:55 +00:00
|
|
|
S_Sound (self, CHAN_WEAPON, "ClericCStaffFire", 1, ATTN_NORM);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_CStaffMissileSlither
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_CStaffMissileSlither)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
|
|
|
fixed_t newX, newY;
|
|
|
|
int weaveXY;
|
|
|
|
int angle;
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
weaveXY = self->special2;
|
|
|
|
angle = (self->angle+ANG90)>>ANGLETOFINESHIFT;
|
|
|
|
newX = self->x-FixedMul(finecosine[angle], FloatBobOffsets[weaveXY]);
|
|
|
|
newY = self->y-FixedMul(finesine[angle], FloatBobOffsets[weaveXY]);
|
2006-02-24 04:48:15 +00:00
|
|
|
weaveXY = (weaveXY+3)&63;
|
|
|
|
newX += FixedMul(finecosine[angle], FloatBobOffsets[weaveXY]);
|
|
|
|
newY += FixedMul(finesine[angle], FloatBobOffsets[weaveXY]);
|
2008-08-10 20:48:55 +00:00
|
|
|
P_TryMove (self, newX, newY, true);
|
|
|
|
self->special2 = weaveXY;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_CStaffInitBlink
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_CStaffInitBlink)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2008-08-10 20:48:55 +00:00
|
|
|
self->special1 = (pr_blink()>>1)+20;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_CStaffCheckBlink
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheckBlink)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2008-08-10 20:48:55 +00:00
|
|
|
if (!--self->special1)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2008-08-10 20:48:55 +00:00
|
|
|
P_SetPsprite (self->player, ps_weapon, self->FindState ("Blink"));
|
|
|
|
self->special1 = (pr_blink()+50)>>2;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2006-04-10 21:54:50 +00:00
|
|
|
else
|
|
|
|
{
|
2008-08-10 22:48:37 +00:00
|
|
|
CALL_ACTION(A_WeaponReady, self);
|
2006-04-10 21:54:50 +00:00
|
|
|
}
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|