mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-12-15 06:51:36 +00:00
a638cfbd6e
As a consequence it must return null in the failure case instead of asserting and all calls to this function must check for the failure case.
362 lines
6.5 KiB
Text
362 lines
6.5 KiB
Text
|
|
// Beak puff ----------------------------------------------------------------
|
|
|
|
class BeakPuff : StaffPuff
|
|
{
|
|
Default
|
|
{
|
|
Mass 5;
|
|
Renderstyle "Translucent";
|
|
Alpha 0.4;
|
|
AttackSound "chicken/attack";
|
|
VSpeed 1;
|
|
}
|
|
}
|
|
|
|
// Beak ---------------------------------------------------------------------
|
|
|
|
class Beak : Weapon
|
|
{
|
|
Default
|
|
{
|
|
Weapon.SelectionOrder 10000;
|
|
+WEAPON.DONTBOB
|
|
+WEAPON.MELEEWEAPON
|
|
Weapon.YAdjust 15;
|
|
Weapon.SisterWeapon "BeakPowered";
|
|
}
|
|
|
|
|
|
States
|
|
{
|
|
Ready:
|
|
BEAK A 1 A_WeaponReady;
|
|
Loop;
|
|
Deselect:
|
|
BEAK A 1 A_Lower;
|
|
Loop;
|
|
Select:
|
|
BEAK A 1 A_BeakRaise;
|
|
Loop;
|
|
Fire:
|
|
BEAK A 18 A_BeakAttackPL1;
|
|
Goto Ready;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// PROC A_BeakRaise
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
action void A_BeakRaise ()
|
|
{
|
|
|
|
if (player == null)
|
|
{
|
|
return;
|
|
}
|
|
let psp = player.GetPSprite(PSP_WEAPON);
|
|
if (psp)
|
|
{
|
|
psp.y = WEAPONTOP;
|
|
}
|
|
player.SetPsprite(PSP_WEAPON, player.ReadyWeapon.GetReadyState());
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// PROC A_BeakAttackPL1
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
action void A_BeakAttackPL1()
|
|
{
|
|
FTranslatedLineTarget t;
|
|
|
|
if (player == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int damage = random[BeakAtk](1,3);
|
|
double ang = angle;
|
|
double slope = AimLineAttack (ang, DEFMELEERANGE);
|
|
LineAttack (ang, DEFMELEERANGE, slope, damage, 'Melee', "BeakPuff", true, t);
|
|
if (t.linetarget)
|
|
{
|
|
angle = t.angleFromSource;
|
|
}
|
|
A_StartSound ("chicken/peck", CHAN_VOICE);
|
|
player.chickenPeck = 12;
|
|
let psp = player.GetPSprite(PSP_WEAPON);
|
|
if (psp)
|
|
{
|
|
psp.Tics -= random[BeakAtk](0,7);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// BeakPowered ---------------------------------------------------------------------
|
|
|
|
class BeakPowered : Beak
|
|
{
|
|
Default
|
|
{
|
|
+WEAPON.POWERED_UP
|
|
Weapon.SisterWeapon "Beak";
|
|
}
|
|
|
|
|
|
States
|
|
{
|
|
Fire:
|
|
BEAK A 12 A_BeakAttackPL2;
|
|
Goto Ready;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// PROC A_BeakAttackPL2
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
action void A_BeakAttackPL2()
|
|
{
|
|
FTranslatedLineTarget t;
|
|
|
|
if (player == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int damage = random[BeakAtk](1,8) * 4;
|
|
double ang = angle;
|
|
double slope = AimLineAttack (ang, DEFMELEERANGE);
|
|
LineAttack (ang, DEFMELEERANGE, slope, damage, 'Melee', "BeakPuff", true, t);
|
|
if (t.linetarget)
|
|
{
|
|
angle = t.angleFromSource;
|
|
}
|
|
A_StartSound ("chicken/peck", CHAN_VOICE);
|
|
player.chickenPeck = 12;
|
|
let psp = player.GetPSprite(PSP_WEAPON);
|
|
if (psp)
|
|
{
|
|
psp.Tics -= random[BeakAtk](0,3);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// Chicken player -----------------------------------------------------------
|
|
|
|
class ChickenPlayer : PlayerPawn
|
|
{
|
|
Default
|
|
{
|
|
Health 30;
|
|
ReactionTime 0;
|
|
PainChance 255;
|
|
Radius 16;
|
|
Height 24;
|
|
Speed 1;
|
|
Gravity 0.125;
|
|
+NOSKIN
|
|
+PLAYERPAWN.CANSUPERMORPH
|
|
PainSound "chicken/pain";
|
|
DeathSound "chicken/death";
|
|
Player.JumpZ 1;
|
|
Player.Viewheight 21;
|
|
Player.ForwardMove 1.22, 1.22;
|
|
Player.SideMove 1.22, 1.22;
|
|
Player.SpawnClass "Chicken";
|
|
Player.SoundClass "Chicken";
|
|
Player.DisplayName "Chicken";
|
|
Player.MorphWeapon "Beak";
|
|
-PICKUP
|
|
}
|
|
|
|
States
|
|
{
|
|
Spawn:
|
|
CHKN A -1;
|
|
Stop;
|
|
See:
|
|
CHKN ABAB 3;
|
|
Loop;
|
|
Melee:
|
|
Missile:
|
|
CHKN C 12;
|
|
Goto Spawn;
|
|
Pain:
|
|
CHKN D 4 A_Feathers;
|
|
CHKN C 4 A_Pain;
|
|
Goto Spawn;
|
|
Death:
|
|
CHKN E 6 A_Scream;
|
|
CHKN F 6 A_Feathers;
|
|
CHKN G 6;
|
|
CHKN H 6 A_NoBlocking;
|
|
CHKN IJK 6;
|
|
CHKN L -1;
|
|
Stop;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// PROC P_UpdateBeak
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
override void MorphPlayerThink ()
|
|
{
|
|
if (health > 0)
|
|
{ // Handle beak movement
|
|
PSprite pspr;
|
|
if (player != null && (pspr = player.FindPSprite(PSP_WEAPON)) != null)
|
|
{
|
|
pspr.y = WEAPONTOP + player.chickenPeck / 2;
|
|
}
|
|
}
|
|
if (player.morphTics & 15)
|
|
{
|
|
return;
|
|
}
|
|
if (Vel.X == 0 && Vel.Y == 0 && random[ChickenPlayerThink]() < 160)
|
|
{ // Twitch view ang
|
|
angle += Random2[ChickenPlayerThink]() * (360. / 256. / 32.);
|
|
}
|
|
if ((pos.z <= floorz) && (random[ChickenPlayerThink]() < 32))
|
|
{ // Jump and noise
|
|
Vel.Z += JumpZ;
|
|
|
|
State painstate = FindState('Pain');
|
|
if (painstate != null) SetState (painstate);
|
|
}
|
|
if (random[ChickenPlayerThink]() < 48)
|
|
{ // Just noise
|
|
A_StartSound ("chicken/active", CHAN_VOICE);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Chicken (non-player) -----------------------------------------------------
|
|
|
|
class Chicken : MorphedMonster
|
|
{
|
|
Default
|
|
{
|
|
Health 10;
|
|
Radius 9;
|
|
Height 22;
|
|
Mass 40;
|
|
Speed 4;
|
|
Painchance 200;
|
|
Monster;
|
|
-COUNTKILL
|
|
+WINDTHRUST
|
|
+DONTMORPH
|
|
+FLOORCLIP
|
|
SeeSound "chicken/pain";
|
|
AttackSound "chicken/attack";
|
|
PainSound "chicken/pain";
|
|
DeathSound "chicken/death";
|
|
ActiveSound "chicken/active";
|
|
Obituary "$OB_CHICKEN";
|
|
Tag "$FN_CHICKEN";
|
|
}
|
|
States
|
|
{
|
|
Spawn:
|
|
CHKN AB 10 A_Look;
|
|
Loop;
|
|
See:
|
|
CHKN AB 3 A_Chase;
|
|
Loop;
|
|
Pain:
|
|
CHKN D 5 A_Feathers;
|
|
CHKN C 5 A_Pain;
|
|
Goto See;
|
|
Melee:
|
|
CHKN A 8 A_FaceTarget;
|
|
CHKN C 10 A_CustomMeleeAttack(random[ChicAttack](1,2));
|
|
Goto See;
|
|
Death:
|
|
CHKN E 6 A_Scream;
|
|
CHKN F 6 A_Feathers;
|
|
CHKN G 6;
|
|
CHKN H 6 A_NoBlocking;
|
|
CHKN IJK 6;
|
|
CHKN L -1;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
|
|
// Feather ------------------------------------------------------------------
|
|
|
|
class Feather : Actor
|
|
{
|
|
Default
|
|
{
|
|
Radius 2;
|
|
Height 4;
|
|
+MISSILE +DROPOFF
|
|
+NOTELEPORT +CANNOTPUSH
|
|
+WINDTHRUST +DONTSPLASH
|
|
Gravity 0.125;
|
|
}
|
|
|
|
States
|
|
{
|
|
Spawn:
|
|
CHKN MNOPQPON 3;
|
|
Loop;
|
|
Death:
|
|
CHKN N 6;
|
|
Stop;
|
|
}
|
|
}
|
|
|
|
extend class Actor
|
|
{
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// PROC A_Feathers
|
|
// This is used by both the chicken player and monster and must be in the
|
|
// common base class to be accessible by both
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void A_Feathers()
|
|
{
|
|
int count;
|
|
|
|
if (health > 0)
|
|
{ // Pain
|
|
count = random[Feathers]() < 32 ? 2 : 1;
|
|
}
|
|
else
|
|
{ // Death
|
|
count = 5 + (random[Feathers](0, 3));
|
|
}
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
Actor mo = Spawn("Feather", pos + (0, 0, 20), NO_REPLACE);
|
|
if (mo != null)
|
|
{
|
|
mo.target = self;
|
|
mo.Vel.X = Random2[Feathers]() / 256.;
|
|
mo.Vel.Y = Random2[Feathers]() / 256.;
|
|
mo.Vel.Z = 1. + random[Feathers]() / 128.;
|
|
mo.SetState (mo.SpawnState + (random[Feathers](0, 7)));
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|