mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 23:02:08 +00:00
- scriptified Chicken and Pig - not tested yet, because other things have priority.
This commit is contained in:
parent
3db712cd73
commit
bbb0778fd4
16 changed files with 309 additions and 357 deletions
|
@ -867,7 +867,6 @@ set( NOT_COMPILED_SOURCE_FILES
|
|||
sc_man_scanner.h
|
||||
sc_man_scanner.re
|
||||
g_doom/a_painelemental.cpp
|
||||
g_heretic/a_chicken.cpp
|
||||
g_heretic/a_dsparil.cpp
|
||||
g_heretic/a_hereticartifacts.cpp
|
||||
g_heretic/a_hereticweaps.cpp
|
||||
|
@ -892,7 +891,6 @@ set( NOT_COMPILED_SOURCE_FILES
|
|||
g_hexen/a_magecone.cpp
|
||||
g_hexen/a_magelightning.cpp
|
||||
g_hexen/a_magestaff.cpp
|
||||
g_hexen/a_pig.cpp
|
||||
g_hexen/a_serpent.cpp
|
||||
g_hexen/a_spike.cpp
|
||||
g_hexen/a_summon.cpp
|
||||
|
|
|
@ -100,6 +100,7 @@ FString GetPrintableDisplayName(PClassPlayerPawn *cls);
|
|||
class APlayerPawn : public AActor
|
||||
{
|
||||
DECLARE_CLASS_WITH_META(APlayerPawn, AActor, PClassPlayerPawn)
|
||||
HAS_FIELDS
|
||||
HAS_OBJECT_POINTERS
|
||||
public:
|
||||
|
||||
|
@ -116,7 +117,7 @@ public:
|
|||
virtual void PlayRunning ();
|
||||
virtual void ThrowPoisonBag ();
|
||||
virtual void TweakSpeeds (double &forwardmove, double &sidemove);
|
||||
virtual void MorphPlayerThink ();
|
||||
void MorphPlayerThink ();
|
||||
virtual void ActivateMorphWeapon ();
|
||||
AWeapon *PickNewWeapon (PClassAmmo *ammotype);
|
||||
AWeapon *BestWeapon (PClassAmmo *ammotype);
|
||||
|
|
|
@ -1,233 +0,0 @@
|
|||
/*
|
||||
#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_sharedglobal.h"
|
||||
#include "p_enemy.h"
|
||||
#include "d_event.h"
|
||||
#include "gstrings.h"
|
||||
#include "vm.h"
|
||||
*/
|
||||
|
||||
void P_UpdateBeak (AActor *actor);
|
||||
|
||||
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
|
||||
{
|
||||
DECLARE_CLASS (AChickenPlayer, APlayerPawn)
|
||||
public:
|
||||
void MorphPlayerThink ();
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(AChickenPlayer, false, false, false, false)
|
||||
|
||||
void AChickenPlayer::MorphPlayerThink ()
|
||||
{
|
||||
if (health > 0)
|
||||
{ // Handle beak movement
|
||||
P_UpdateBeak (this);
|
||||
}
|
||||
if (player->morphTics & 15)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (Vel.X == 0 && Vel.Y == 0 && pr_chickenplayerthink () < 160)
|
||||
{ // Twitch view angle
|
||||
Angles.Yaw += pr_chickenplayerthink.Random2() * (360. / 256. / 32.);
|
||||
}
|
||||
if ((Z() <= floorz) && (pr_chickenplayerthink() < 32))
|
||||
{ // Jump and noise
|
||||
Vel.Z += JumpZ;
|
||||
|
||||
FState * painstate = FindState(NAME_Pain);
|
||||
if (painstate != NULL) SetState (painstate);
|
||||
}
|
||||
if (pr_chickenplayerthink () < 48)
|
||||
{ // Just noise
|
||||
S_Sound (this, CHAN_VOICE, "chicken/active", 1, ATTN_NORM);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_ChicAttack
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_ChicAttack)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
if (!self->target)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (self->CheckMeleeRange())
|
||||
{
|
||||
int damage = 1 + (pr_chicattack() & 1);
|
||||
int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
||||
P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_Feathers
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_Feathers)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
int i;
|
||||
int count;
|
||||
AActor *mo;
|
||||
|
||||
if (self->health > 0)
|
||||
{ // Pain
|
||||
count = pr_feathers() < 32 ? 2 : 1;
|
||||
}
|
||||
else
|
||||
{ // Death
|
||||
count = 5 + (pr_feathers()&3);
|
||||
}
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
mo = Spawn("Feather", self->PosPlusZ(20.), NO_REPLACE);
|
||||
mo->target = self;
|
||||
mo->Vel.X = pr_feathers.Random2() / 256.;
|
||||
mo->Vel.Y = pr_feathers.Random2() / 256.;
|
||||
mo->Vel.Z = 1. + pr_feathers() / 128.;
|
||||
mo->SetState (mo->SpawnState + (pr_feathers()&7));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC P_UpdateBeak
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void P_UpdateBeak (AActor *self)
|
||||
{
|
||||
DPSprite *pspr;
|
||||
if (self->player != nullptr && (pspr = self->player->FindPSprite(PSP_WEAPON)) != nullptr)
|
||||
{
|
||||
pspr->y = WEAPONTOP + self->player->chickenPeck / 2;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_BeakRaise
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BeakRaise)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
|
||||
player_t *player;
|
||||
|
||||
if (nullptr == (player = self->player))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
player->GetPSprite(PSP_WEAPON)->y = WEAPONTOP;
|
||||
P_SetPsprite(player, PSP_WEAPON, player->ReadyWeapon->GetReadyState());
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC P_PlayPeck
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void P_PlayPeck (AActor *chicken)
|
||||
{
|
||||
S_Sound (chicken, CHAN_VOICE, "chicken/peck", 1, ATTN_NORM);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_BeakAttackPL1
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL1)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
|
||||
DAngle angle;
|
||||
int damage;
|
||||
DAngle slope;
|
||||
player_t *player;
|
||||
FTranslatedLineTarget t;
|
||||
|
||||
if (NULL == (player = self->player))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
damage = 1 + (pr_beakatkpl1()&3);
|
||||
angle = player->mo->Angles.Yaw;
|
||||
slope = P_AimLineAttack (player->mo, angle, MELEERANGE);
|
||||
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true, &t);
|
||||
if (t.linetarget)
|
||||
{
|
||||
player->mo->Angles.Yaw = t.angleFromSource;
|
||||
}
|
||||
P_PlayPeck (player->mo);
|
||||
player->chickenPeck = 12;
|
||||
player->GetPSprite(PSP_WEAPON)->Tics -= pr_beakatkpl1() & 7;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_BeakAttackPL2
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL2)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
|
||||
DAngle angle;
|
||||
int damage;
|
||||
DAngle slope;
|
||||
player_t *player;
|
||||
FTranslatedLineTarget t;
|
||||
|
||||
if (NULL == (player = self->player))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
damage = pr_beakatkpl2.HitDice (4);
|
||||
angle = player->mo->Angles.Yaw;
|
||||
slope = P_AimLineAttack (player->mo, angle, MELEERANGE);
|
||||
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true, &t);
|
||||
if (t.linetarget)
|
||||
{
|
||||
player->mo->Angles.Yaw = t.angleFromSource;
|
||||
}
|
||||
P_PlayPeck (player->mo);
|
||||
player->chickenPeck = 12;
|
||||
player->GetPSprite(PSP_WEAPON)->Tics -= pr_beakatkpl2()&3;
|
||||
return 0;
|
||||
}
|
|
@ -19,7 +19,6 @@
|
|||
#include "serializer.h"
|
||||
|
||||
// Include all the other Heretic stuff here to reduce compile time
|
||||
#include "a_chicken.cpp"
|
||||
#include "a_dsparil.cpp"
|
||||
#include "a_hereticartifacts.cpp"
|
||||
#include "a_hereticweaps.cpp"
|
||||
|
|
|
@ -49,6 +49,13 @@ void AdjustPlayerAngle (AActor *pmo, FTranslatedLineTarget *t)
|
|||
}
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, AdjustPlayerAngle)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_POINTER(t, FTranslatedLineTarget);
|
||||
AdjustPlayerAngle(self, t);
|
||||
return 0;
|
||||
}
|
||||
//============================================================================
|
||||
//
|
||||
// TryPunch
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
#include "a_magecone.cpp"
|
||||
#include "a_magelightning.cpp"
|
||||
#include "a_magestaff.cpp"
|
||||
#include "a_pig.cpp"
|
||||
#include "a_serpent.cpp"
|
||||
#include "a_spike.cpp"
|
||||
#include "a_summon.cpp"
|
||||
|
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
#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_sharedglobal.h"
|
||||
#include "p_enemy.h"
|
||||
#include "d_event.h"
|
||||
#include "gstrings.h"
|
||||
#include "vm.h"
|
||||
*/
|
||||
|
||||
static FRandom pr_snoutattack ("SnoutAttack");
|
||||
static FRandom pr_pigattack ("PigAttack");
|
||||
static FRandom pr_pigplayerthink ("PigPlayerThink");
|
||||
|
||||
// Pig player ---------------------------------------------------------------
|
||||
|
||||
class APigPlayer : public APlayerPawn
|
||||
{
|
||||
DECLARE_CLASS (APigPlayer, APlayerPawn)
|
||||
public:
|
||||
void MorphPlayerThink ();
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(APigPlayer, false, false, false, false)
|
||||
|
||||
void APigPlayer::MorphPlayerThink ()
|
||||
{
|
||||
if (player->morphTics & 15)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(Vel.X == 0 && Vel.Y == 0 && pr_pigplayerthink() < 64)
|
||||
{ // Snout sniff
|
||||
if (player->ReadyWeapon != nullptr)
|
||||
{
|
||||
P_SetPsprite(player, PSP_WEAPON, player->ReadyWeapon->FindState("Grunt"));
|
||||
}
|
||||
S_Sound (this, CHAN_VOICE, "PigActive1", 1, ATTN_NORM); // snort
|
||||
return;
|
||||
}
|
||||
if (pr_pigplayerthink() < 48)
|
||||
{
|
||||
S_Sound (this, CHAN_VOICE, "PigActive", 1, ATTN_NORM);
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_SnoutAttack
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SnoutAttack)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE(AActor);
|
||||
|
||||
DAngle angle;
|
||||
int damage;
|
||||
DAngle slope;
|
||||
player_t *player;
|
||||
AActor *puff;
|
||||
FTranslatedLineTarget t;
|
||||
|
||||
if (NULL == (player = self->player))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
damage = 3+(pr_snoutattack()&3);
|
||||
angle = player->mo->Angles.Yaw;
|
||||
slope = P_AimLineAttack(player->mo, angle, MELEERANGE);
|
||||
puff = P_LineAttack(player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "SnoutPuff", true, &t);
|
||||
S_Sound(player->mo, CHAN_VOICE, "PigActive", 1, ATTN_NORM);
|
||||
if(t.linetarget)
|
||||
{
|
||||
AdjustPlayerAngle(player->mo, &t);
|
||||
if(puff != NULL)
|
||||
{ // Bit something
|
||||
S_Sound(player->mo, CHAN_VOICE, "PigAttack", 1, ATTN_NORM);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_PigPain
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_PigPain)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
CALL_ACTION(A_Pain, self);
|
||||
if (self->Z() <= self->floorz)
|
||||
{
|
||||
self->Vel.Z = 3.5;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -109,8 +109,29 @@ IMPLEMENT_POINTERS_END
|
|||
void DPSprite::InitNativeFields()
|
||||
{
|
||||
auto meta = RUNTIME_CLASS(DPSprite);
|
||||
PType *TypeActor = NewPointer(RUNTIME_CLASS(AActor));
|
||||
PType *TypePSP = NewPointer(RUNTIME_CLASS(DPSprite));
|
||||
PType *TypePlayer = NewPointer(NewNativeStruct("Player", nullptr));
|
||||
|
||||
meta->AddNativeField("State", TypeState, myoffsetof(DPSprite, State), VARF_ReadOnly);
|
||||
meta->AddNativeField("Caller", TypeActor, myoffsetof(DPSprite, Caller), VARF_ReadOnly);
|
||||
meta->AddNativeField("Next", TypePSP, myoffsetof(DPSprite, Next), VARF_ReadOnly);
|
||||
meta->AddNativeField("Owner", TypePlayer, myoffsetof(DPSprite, Owner), VARF_ReadOnly);
|
||||
meta->AddNativeField("Sprite", TypeSpriteID, myoffsetof(DPSprite, Sprite));
|
||||
meta->AddNativeField("Frame", TypeSInt32, myoffsetof(DPSprite, Frame));
|
||||
meta->AddNativeField("ID", TypePlayer, myoffsetof(DPSprite, ID), VARF_ReadOnly);
|
||||
meta->AddNativeField("processPending", TypeBool, myoffsetof(DPSprite, processPending));
|
||||
meta->AddNativeField("x", TypeFloat64, myoffsetof(DPSprite, x));
|
||||
meta->AddNativeField("y", TypeFloat64, myoffsetof(DPSprite, y));
|
||||
meta->AddNativeField("oldx", TypeFloat64, myoffsetof(DPSprite, oldx));
|
||||
meta->AddNativeField("oldy", TypeFloat64, myoffsetof(DPSprite, oldy));
|
||||
meta->AddNativeField("firstTic", TypeBool, myoffsetof(DPSprite, firstTic));
|
||||
meta->AddNativeField("Tics", TypeSInt32, myoffsetof(DPSprite, Tics));
|
||||
meta->AddNativeField("bAddWeapon", TypeSInt32, myoffsetof(DPSprite, Flags), 0, PSPF_ADDWEAPON);
|
||||
meta->AddNativeField("bAddBob", TypeSInt32, myoffsetof(DPSprite, Flags), 0, PSPF_ADDBOB);
|
||||
meta->AddNativeField("bPowDouble", TypeSInt32, myoffsetof(DPSprite, Flags), 0, PSPF_POWDOUBLE);
|
||||
meta->AddNativeField("bCVarFast", TypeSInt32, myoffsetof(DPSprite, Flags), 0, PSPF_CVARFAST);
|
||||
meta->AddNativeField("bFlip", TypeSInt32, myoffsetof(DPSprite, Flags), 0, PSPF_FLIP);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
@ -179,6 +200,14 @@ DPSprite *player_t::FindPSprite(int layer)
|
|||
return pspr;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(_Player, FindPSprite) // the underscore is needed to get past the name mangler which removes the first clas name character to match the class representation (needs to be fixed in a later commit)
|
||||
{
|
||||
PARAM_SELF_STRUCT_PROLOGUE(player_t);
|
||||
PARAM_INT(id);
|
||||
ACTION_RETURN_OBJECT(self->FindPSprite((PSPLayers)id));
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
|
|
|
@ -161,6 +161,12 @@ bool ValidatePlayerClass(PClassActor *ti, const char *name)
|
|||
return true;
|
||||
}
|
||||
|
||||
void APlayerPawn::InitNativeFields()
|
||||
{
|
||||
auto meta = RUNTIME_CLASS(APlayerPawn);
|
||||
meta->AddNativeField("JumpZ", TypeFloat64, myoffsetof(APlayerPawn, JumpZ));
|
||||
}
|
||||
|
||||
void SetupPlayerClasses ()
|
||||
{
|
||||
FPlayerClass newclass;
|
||||
|
@ -622,7 +628,7 @@ void player_t::SendPitchLimits() const
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
IMPLEMENT_CLASS(APlayerPawn, false, true, false, true)
|
||||
IMPLEMENT_CLASS(APlayerPawn, false, true, true, true)
|
||||
|
||||
IMPLEMENT_POINTERS_START(APlayerPawn)
|
||||
IMPLEMENT_POINTER(InvFirst)
|
||||
|
@ -1381,6 +1387,10 @@ void APlayerPawn::GiveDefaultInventory ()
|
|||
|
||||
void APlayerPawn::MorphPlayerThink ()
|
||||
{
|
||||
VINDEX(APlayerPawn, MorphPlayerThink);
|
||||
VMValue params[1] = { (DObject*)this };
|
||||
VMFrameStack stack;
|
||||
stack.Call(VFUNC, params, 1, nullptr, 0, nullptr);
|
||||
}
|
||||
|
||||
void APlayerPawn::ActivateMorphWeapon ()
|
||||
|
|
|
@ -2543,7 +2543,15 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (left->IsVector() && right->IsVector())
|
||||
if (left->ValueType == TypeState && right->IsInteger() && Operator == '+' && !left->isConstant())
|
||||
{
|
||||
// This is the only special case of pointer addition that will be accepted - because it is used quite often in the existing game code.
|
||||
ValueType = TypeState;
|
||||
right = new FxMulDiv('*', right, new FxConstant((int)sizeof(FState), ScriptPosition)); // multiply by size here, so that constants can be better optimized.
|
||||
right = right->Resolve(ctx);
|
||||
ABORT(right);
|
||||
}
|
||||
else if (left->IsVector() && right->IsVector())
|
||||
{
|
||||
// a vector2 can be added to or subtracted from a vector 3 but it needs to be the right operand.
|
||||
if (left->ValueType == right->ValueType || (left->ValueType == TypeVector3 && right->ValueType == TypeVector2))
|
||||
|
@ -2616,6 +2624,16 @@ ExpEmit FxAddSub::Emit(VMFunctionBuilder *build)
|
|||
ExpEmit op2 = right->Emit(build);
|
||||
if (Operator == '+')
|
||||
{
|
||||
if (op1.RegType == REGT_POINTER)
|
||||
{
|
||||
assert(!op1.Konst);
|
||||
assert(op2.RegType == REGT_INT);
|
||||
op1.Free(build);
|
||||
op2.Free(build);
|
||||
ExpEmit opout(build, REGT_POINTER);
|
||||
build->Emit(op2.Konst? OP_ADDA_RK : OP_ADDA_RR, opout.RegNum, op1.RegNum, op2.RegNum);
|
||||
return opout;
|
||||
}
|
||||
// Since addition is commutative, only the second operand may be a constant.
|
||||
if (op1.Konst)
|
||||
{
|
||||
|
|
|
@ -67,6 +67,7 @@ class Actor : Thinker native
|
|||
virtual native void Activate(Actor activator);
|
||||
virtual native void Deactivate(Actor activator);
|
||||
|
||||
native void AdjustPlayerAngle(FTranslatedLineTarget t);
|
||||
native static readonly<Actor> GetDefaultByType(class<Actor> cls);
|
||||
native static double deltaangle(double ang1, double ang2);
|
||||
native static double absangle(double ang1, double ang2);
|
||||
|
@ -467,7 +468,6 @@ class Actor : Thinker native
|
|||
native void A_DeQueueCorpse();
|
||||
native void A_ClearLastHeard();
|
||||
native bool A_SelectWeapon(class<Weapon> whichweapon, int flags = 0);
|
||||
native void A_Feathers();
|
||||
native void A_ClassBossHealth();
|
||||
native void A_ShootGun();
|
||||
native void A_RocketInFlight();
|
||||
|
@ -476,7 +476,6 @@ class Actor : Thinker native
|
|||
native void A_GiveQuestItem(int itemno);
|
||||
native void A_RemoveForcefield();
|
||||
native void A_DropWeaponPieces(class<Actor> p1, class<Actor> p2, class<Actor> p3);
|
||||
native void A_PigPain ();
|
||||
native void A_SetAngle(double angle = 0, int flags = 0, int ptr = AAPTR_DEFAULT);
|
||||
native void A_SetPitch(double pitch, int flags = 0, int ptr = AAPTR_DEFAULT);
|
||||
native void A_SetRoll(double roll, int flags = 0, int ptr = AAPTR_DEFAULT);
|
||||
|
|
|
@ -948,3 +948,8 @@ enum EFSkillProperty // floating point properties
|
|||
SKILLP_FriendlyHealth,
|
||||
};
|
||||
|
||||
enum EWeaponPos
|
||||
{
|
||||
WEAPONBOTTOM = 128,
|
||||
WEAPONTOP = 32
|
||||
}
|
|
@ -26,8 +26,6 @@ class Beak : Weapon
|
|||
Weapon.SisterWeapon "BeakPowered";
|
||||
}
|
||||
|
||||
action native void A_BeakRaise ();
|
||||
action native void A_BeakAttackPL1();
|
||||
|
||||
States
|
||||
{
|
||||
|
@ -44,9 +42,56 @@ class Beak : Weapon
|
|||
BEAK A 18 A_BeakAttackPL1;
|
||||
Goto Ready;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_BeakRaise
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
action void A_BeakRaise ()
|
||||
{
|
||||
|
||||
if (player == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
player.GetPSprite(PSP_WEAPON).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, MELEERANGE);
|
||||
LineAttack (ang, MELEERANGE, slope, damage, 'Melee', "BeakPuff", true, t);
|
||||
if (t.linetarget)
|
||||
{
|
||||
angle = t.angleFromSource;
|
||||
}
|
||||
A_PlaySound ("chicken/peck", CHAN_VOICE);
|
||||
player.chickenPeck = 12;
|
||||
player.GetPSprite(PSP_WEAPON).Tics -= random[BeakAtk](0,7);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// BeakPowered ---------------------------------------------------------------------
|
||||
|
||||
class BeakPowered : Beak
|
||||
{
|
||||
Default
|
||||
|
@ -55,7 +100,6 @@ class BeakPowered : Beak
|
|||
Weapon.SisterWeapon "Beak";
|
||||
}
|
||||
|
||||
action native void A_BeakAttackPL2();
|
||||
|
||||
States
|
||||
{
|
||||
|
@ -63,11 +107,40 @@ class BeakPowered : Beak
|
|||
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, MELEERANGE);
|
||||
LineAttack (ang, MELEERANGE, slope, damage, 'Melee', "BeakPuff", true, t);
|
||||
if (t.linetarget)
|
||||
{
|
||||
angle = t.angleFromSource;
|
||||
}
|
||||
A_PlaySound ("chicken/peck", CHAN_VOICE);
|
||||
player.chickenPeck = 12;
|
||||
player.GetPSprite(PSP_WEAPON).Tics -= random[BeakAtk](0,3);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Chicken player -----------------------------------------------------------
|
||||
|
||||
class ChickenPlayer : PlayerPawn native
|
||||
class ChickenPlayer : PlayerPawn
|
||||
{
|
||||
Default
|
||||
{
|
||||
|
@ -118,6 +191,44 @@ class ChickenPlayer : PlayerPawn native
|
|||
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_PlaySound ("chicken/active", CHAN_VOICE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -199,3 +310,37 @@ class Feather : Actor
|
|||
}
|
||||
}
|
||||
|
||||
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]()&3);
|
||||
}
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Actor mo = Spawn("Feather", pos + (0, 0, 20), NO_REPLACE);
|
||||
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]()&7));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -34,8 +34,6 @@ class Snout : Weapon
|
|||
Weapon.YAdjust 10;
|
||||
}
|
||||
|
||||
action native void A_SnoutAttack ();
|
||||
|
||||
States
|
||||
{
|
||||
Ready:
|
||||
|
@ -54,12 +52,43 @@ class Snout : Weapon
|
|||
WPIG B 8;
|
||||
Goto Ready;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_SnoutAttack
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
action void A_SnoutAttack ()
|
||||
{
|
||||
FTranslatedLineTarget t;
|
||||
|
||||
if (player == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int damage = random[SnoutAttack](3, 6);
|
||||
double ang = angle;
|
||||
double slope = AimLineAttack(ang, MELEERANGE);
|
||||
Actor puff = LineAttack(ang, MELEERANGE, slope, damage, 'Melee', "SnoutPuff", true, t);
|
||||
A_PlaySound("PigActive", CHAN_VOICE);
|
||||
if(t.linetarget)
|
||||
{
|
||||
AdjustPlayerAngle(t);
|
||||
if(puff != null)
|
||||
{ // Bit something
|
||||
A_PlaySound("PigAttack", CHAN_VOICE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Pig player ---------------------------------------------------------------
|
||||
|
||||
class PigPlayer : PlayerPawn native
|
||||
class PigPlayer : PlayerPawn
|
||||
{
|
||||
Default
|
||||
{
|
||||
|
@ -112,6 +141,30 @@ class PigPlayer : PlayerPawn native
|
|||
PIGY M 1 A_FreezeDeathChunks;
|
||||
Wait;
|
||||
}
|
||||
|
||||
|
||||
override void MorphPlayerThink ()
|
||||
{
|
||||
if (player.morphTics & 15)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(Vel.X == 0 && Vel.Y == 0 && random[PigPlayerThink]() < 64)
|
||||
{ // Snout sniff
|
||||
if (player.ReadyWeapon != null)
|
||||
{
|
||||
player.SetPsprite(PSP_WEAPON, player.ReadyWeapon.FindState('Grunt'));
|
||||
}
|
||||
A_PlaySound ("PigActive1", CHAN_VOICE); // snort
|
||||
return;
|
||||
}
|
||||
if (random[PigPlayerThink]() < 48)
|
||||
{
|
||||
A_PlaySound ("PigActive", CHAN_VOICE); // snort
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -168,3 +221,21 @@ class Pig : MorphedMonster
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
extend class Actor
|
||||
{
|
||||
//============================================================================
|
||||
//
|
||||
// A_PigPain
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void A_PigPain ()
|
||||
{
|
||||
A_Pain();
|
||||
if (pos.z <= floorz)
|
||||
{
|
||||
Vel.Z = 3.5;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -457,6 +457,12 @@ class Weapon : StateProvider native
|
|||
|
||||
native bool DepleteAmmo(bool altFire, bool checkEnough = true, int ammouse = -1);
|
||||
|
||||
virtual State GetReadyState ()
|
||||
{
|
||||
return FindState('Ready');
|
||||
}
|
||||
|
||||
|
||||
native action void A_ZoomFactor(double scale = 1, int flags = 0);
|
||||
native action void A_SetCrosshair(int xhair);
|
||||
const ZOOM_INSTANT = 1;
|
||||
|
|
|
@ -49,6 +49,10 @@ class PlayerPawn : Actor native
|
|||
if (MeleeState != null) SetState (MeleeState);
|
||||
}
|
||||
|
||||
virtual void MorphPlayerThink()
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PlayerChunk : PlayerPawn native
|
||||
|
@ -78,4 +82,5 @@ struct Player native
|
|||
native void SetPsprite(int id, State stat, bool pending = false);
|
||||
native void SetSafeFlash(Weapon weap, State flashstate, int index);
|
||||
native PSprite GetPSprite(int id);
|
||||
}
|
||||
native PSprite FindPSprite(int id);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue