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 "a_pickups.h"
|
|
|
|
#include "p_local.h"
|
|
|
|
#include "a_hereticglobal.h"
|
|
|
|
#include "a_sharedglobal.h"
|
|
|
|
#include "p_enemy.h"
|
|
|
|
#include "d_event.h"
|
|
|
|
#include "gstrings.h"
|
|
|
|
|
2008-07-21 17:03:30 +00:00
|
|
|
void P_UpdateBeak (AActor *actor);
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
static FRandom pr_chickenplayerthink ("ChickenPlayerThink");
|
|
|
|
static FRandom pr_chicattack ("ChicAttack");
|
|
|
|
static FRandom pr_feathers ("Feathers");
|
|
|
|
static FRandom pr_beakatkpl1 ("BeakAtkPL1");
|
|
|
|
static FRandom pr_beakatkpl2 ("BeakAtkPL2");
|
|
|
|
|
|
|
|
class AChickenPlayer : public APlayerPawn
|
|
|
|
{
|
2008-07-21 17:03:30 +00:00
|
|
|
DECLARE_CLASS (AChickenPlayer, APlayerPawn)
|
2006-02-24 04:48:15 +00:00
|
|
|
public:
|
|
|
|
void MorphPlayerThink ();
|
|
|
|
};
|
|
|
|
|
2008-07-21 17:03:30 +00:00
|
|
|
IMPLEMENT_CLASS(AChickenPlayer)
|
2008-02-05 23:32:49 +00:00
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
void AChickenPlayer::MorphPlayerThink ()
|
|
|
|
{
|
|
|
|
if (health > 0)
|
|
|
|
{ // Handle beak movement
|
|
|
|
P_UpdateBeak (this);
|
|
|
|
}
|
|
|
|
if (player->morphTics & 15)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!(momx | momy) && pr_chickenplayerthink () < 160)
|
|
|
|
{ // Twitch view angle
|
|
|
|
angle += pr_chickenplayerthink.Random2 () << 19;
|
|
|
|
}
|
|
|
|
if ((z <= floorz) && (pr_chickenplayerthink() < 32))
|
|
|
|
{ // Jump and noise
|
2006-07-13 10:17:56 +00:00
|
|
|
momz += JumpZ;
|
2006-10-31 14:53:21 +00:00
|
|
|
|
|
|
|
FState * painstate = FindState(NAME_Pain);
|
|
|
|
if (painstate != NULL) SetState (painstate);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
if (pr_chickenplayerthink () < 48)
|
|
|
|
{ // Just noise
|
|
|
|
S_Sound (this, CHAN_VOICE, "chicken/active", 1, ATTN_NORM);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// PROC A_ChicAttack
|
|
|
|
//
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void A_ChicAttack (AActor *actor)
|
|
|
|
{
|
|
|
|
if (!actor->target)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (actor->CheckMeleeRange())
|
|
|
|
{
|
|
|
|
int damage = 1 + (pr_chicattack() & 1);
|
2006-10-31 14:53:21 +00:00
|
|
|
P_DamageMobj (actor->target, actor, actor, damage, NAME_Melee);
|
2006-02-24 04:48:15 +00:00
|
|
|
P_TraceBleed (damage, actor->target, actor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// PROC A_Feathers
|
|
|
|
//
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void A_Feathers (AActor *actor)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int count;
|
|
|
|
AActor *mo;
|
|
|
|
|
|
|
|
if (actor->health > 0)
|
|
|
|
{ // Pain
|
|
|
|
count = pr_feathers() < 32 ? 2 : 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // Death
|
|
|
|
count = 5 + (pr_feathers()&3);
|
|
|
|
}
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
2008-07-21 17:03:30 +00:00
|
|
|
mo = Spawn("Feather", actor->x, actor->y, actor->z+20*FRACUNIT, NO_REPLACE);
|
2006-02-24 04:48:15 +00:00
|
|
|
mo->target = actor;
|
|
|
|
mo->momx = pr_feathers.Random2() << 8;
|
|
|
|
mo->momy = pr_feathers.Random2() << 8;
|
|
|
|
mo->momz = FRACUNIT + (pr_feathers() << 9);
|
2008-07-21 17:03:30 +00:00
|
|
|
mo->SetState (mo->SpawnState + (pr_feathers()&7));
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// PROC P_UpdateBeak
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void P_UpdateBeak (AActor *actor)
|
|
|
|
{
|
|
|
|
if (actor->player != NULL)
|
|
|
|
{
|
|
|
|
actor->player->psprites[ps_weapon].sy = WEAPONTOP +
|
|
|
|
(actor->player->chickenPeck << (FRACBITS-1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// PROC A_BeakRaise
|
|
|
|
//
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void A_BeakRaise (AActor *actor)
|
|
|
|
{
|
|
|
|
player_t *player;
|
|
|
|
|
|
|
|
if (NULL == (player = actor->player))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
player->psprites[ps_weapon].sy = WEAPONTOP;
|
|
|
|
P_SetPsprite (player, ps_weapon, player->ReadyWeapon->GetReadyState());
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// PROC P_PlayPeck
|
|
|
|
//
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void P_PlayPeck (AActor *chicken)
|
|
|
|
{
|
|
|
|
S_Sound (chicken, CHAN_VOICE, "chicken/peck", 1, ATTN_NORM);
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// PROC A_BeakAttackPL1
|
|
|
|
//
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void A_BeakAttackPL1 (AActor *actor)
|
|
|
|
{
|
|
|
|
angle_t angle;
|
|
|
|
int damage;
|
|
|
|
int slope;
|
|
|
|
player_t *player;
|
2008-04-10 14:38:43 +00:00
|
|
|
AActor *linetarget;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
if (NULL == (player = actor->player))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
damage = 1 + (pr_beakatkpl1()&3);
|
|
|
|
angle = player->mo->angle;
|
2008-04-10 14:38:43 +00:00
|
|
|
slope = P_AimLineAttack (player->mo, angle, MELEERANGE, &linetarget);
|
2008-07-21 17:03:30 +00:00
|
|
|
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true);
|
2006-02-24 04:48:15 +00:00
|
|
|
if (linetarget)
|
|
|
|
{
|
|
|
|
player->mo->angle = R_PointToAngle2 (player->mo->x,
|
|
|
|
player->mo->y, linetarget->x, linetarget->y);
|
|
|
|
}
|
|
|
|
P_PlayPeck (player->mo);
|
|
|
|
player->chickenPeck = 12;
|
|
|
|
player->psprites[ps_weapon].tics -= pr_beakatkpl1() & 7;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// PROC A_BeakAttackPL2
|
|
|
|
//
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void A_BeakAttackPL2 (AActor *actor)
|
|
|
|
{
|
|
|
|
angle_t angle;
|
|
|
|
int damage;
|
|
|
|
int slope;
|
|
|
|
player_t *player;
|
2008-04-10 14:38:43 +00:00
|
|
|
AActor *linetarget;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
if (NULL == (player = actor->player))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
damage = pr_beakatkpl2.HitDice (4);
|
|
|
|
angle = player->mo->angle;
|
2008-04-10 14:38:43 +00:00
|
|
|
slope = P_AimLineAttack (player->mo, angle, MELEERANGE, &linetarget);
|
2008-07-21 17:03:30 +00:00
|
|
|
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true);
|
2006-02-24 04:48:15 +00:00
|
|
|
if (linetarget)
|
|
|
|
{
|
|
|
|
player->mo->angle = R_PointToAngle2 (player->mo->x,
|
|
|
|
player->mo->y, linetarget->x, linetarget->y);
|
|
|
|
}
|
|
|
|
P_PlayPeck (player->mo);
|
|
|
|
player->chickenPeck = 12;
|
|
|
|
player->psprites[ps_weapon].tics -= pr_beakatkpl2()&3;
|
|
|
|
}
|