gzdoom/src/g_hexen/a_pig.cpp
Randy Heit 6af5665575 - Fixed: Morphed pig and chicken players made normal human *usefail sounds.
- G_DoSaveGame() now receives the filename and description from its arguments
  rather than global variables, so autosaves and manual saves can be done
  in close proximity to each other without overwriting the parameters for
  one of them.
- Fixed potential buffer overrun in G_SaveGame() and added a check so that
  you can't interfere with saves that are still pending.
- Fixed: P_LineAttack() creates temporary puffs to get damage types, but this
  had the side effect of creating particles for the puff.
- Fixed: The Heretic status bar tried to use the graphic "SELECTBOX" for the
  inventory selector. The correct name is "SELECTBO".
- Fixed: Using allowrespawn for a single-player map would fire off enter
  scripts instead of respawn script because the player wasn't assigned the
  state PST_REBORN.
- Fixed: P_CheckMissileSpawn() now passes the BlockingMobj to
  P_ExplodeMissile() so that it can select the appropriate death state.
- Added the manifest to MinGW-compiled builds of updaterevision so you can
  build under Vista with MinGW without needing administrative privileges.
  (But I still want to know why Vista thinks it needs elevated privileges
  without a manifest telling it otherwise.)
- Using four 0xFF bytes for the final note of an IMF song should signal the
  end of the song.


SVN r733 (trunk)
2008-02-05 23:32:49 +00:00

316 lines
9.3 KiB
C++

#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"
static FRandom pr_snoutattack ("SnoutAttack");
static FRandom pr_pigattack ("PigAttack");
static FRandom pr_pigplayerthink ("PigPlayerThink");
extern void AdjustPlayerAngle (AActor *);
void A_SnoutAttack (AActor *actor);
void A_PigPain (AActor *);
void A_PigAttack (AActor *);
// Snout puff ---------------------------------------------------------------
class ASnoutPuff : public AActor
{
DECLARE_ACTOR (ASnoutPuff, AActor)
};
FState ASnoutPuff::States[] =
{
S_NORMAL (FHFX, 'S', 4, NULL , &States[1]),
S_NORMAL (FHFX, 'T', 4, NULL , &States[2]),
S_NORMAL (FHFX, 'U', 4, NULL , &States[3]),
S_NORMAL (FHFX, 'V', 4, NULL , &States[4]),
S_NORMAL (FHFX, 'W', 4, NULL , NULL)
};
IMPLEMENT_ACTOR (ASnoutPuff, Hexen, -1, 0)
PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY)
PROP_RenderStyle (STYLE_Translucent)
PROP_Alpha (HX_SHADOW)
PROP_SpawnState (0)
END_DEFAULTS
// Snout --------------------------------------------------------------------
class ASnout : public AWeapon
{
DECLARE_ACTOR (ASnout, AWeapon)
};
FState ASnout::States[] =
{
#define S_SNOUTREADY 0
S_NORMAL (WPIG, 'A', 1, A_WeaponReady , &States[S_SNOUTREADY]),
#define S_SNOUTDOWN 1
S_NORMAL (WPIG, 'A', 1, A_Lower , &States[S_SNOUTDOWN]),
#define S_SNOUTUP 2
S_NORMAL (WPIG, 'A', 1, A_Raise , &States[S_SNOUTUP]),
#define S_SNOUTATK 3
S_NORMAL (WPIG, 'A', 4, A_SnoutAttack , &States[S_SNOUTATK+1]),
S_NORMAL (WPIG, 'B', 8, A_SnoutAttack , &States[S_SNOUTREADY])
};
IMPLEMENT_ACTOR (ASnout, Hexen, -1, 0)
PROP_Weapon_SelectionOrder (10000)
PROP_Weapon_Flags (WIF_DONTBOB|WIF_BOT_MELEE)
PROP_Weapon_UpState (S_SNOUTUP)
PROP_Weapon_DownState (S_SNOUTDOWN)
PROP_Weapon_ReadyState (S_SNOUTREADY)
PROP_Weapon_AtkState (S_SNOUTATK)
PROP_Weapon_FlashState (S_SNOUTATK+1) // Not really - but it will do until this gets exported from the EXE
PROP_Weapon_Kickback (150)
PROP_Weapon_YAdjust (10)
END_DEFAULTS
// Pig player ---------------------------------------------------------------
class APigPlayer : public APlayerPawn
{
DECLARE_ACTOR (APigPlayer, APlayerPawn)
public:
void MorphPlayerThink ();
};
FState APigPlayer::States[] =
{
#define S_PIGPLAY 0
S_NORMAL (PIGY, 'A', -1, NULL , NULL),
#define S_PIGPLAY_RUN1 (S_PIGPLAY+1)
S_NORMAL (PIGY, 'A', 3, NULL , &States[S_PIGPLAY_RUN1+1]),
S_NORMAL (PIGY, 'B', 3, NULL , &States[S_PIGPLAY_RUN1+2]),
S_NORMAL (PIGY, 'C', 3, NULL , &States[S_PIGPLAY_RUN1+3]),
S_NORMAL (PIGY, 'D', 3, NULL , &States[S_PIGPLAY_RUN1]),
#define S_PIGPLAY_PAIN (S_PIGPLAY_RUN1+4)
S_NORMAL (PIGY, 'D', 4, A_PigPain , &States[S_PIGPLAY]),
#define S_PIGPLAY_ATK1 (S_PIGPLAY_PAIN+1)
S_NORMAL (PIGY, 'A', 12, NULL , &States[S_PIGPLAY]),
#define S_PIGPLAY_DIE1 (S_PIGPLAY_ATK1+1)
S_NORMAL (PIGY, 'E', 4, A_Scream , &States[S_PIGPLAY_DIE1+1]),
S_NORMAL (PIGY, 'F', 3, A_NoBlocking , &States[S_PIGPLAY_DIE1+2]),
S_NORMAL (PIGY, 'G', 4, NULL , &States[S_PIGPLAY_DIE1+3]),
S_NORMAL (PIGY, 'H', 3, NULL , &States[S_PIGPLAY_DIE1+4]),
S_NORMAL (PIGY, 'I', 4, NULL , &States[S_PIGPLAY_DIE1+5]),
S_NORMAL (PIGY, 'J', 4, NULL , &States[S_PIGPLAY_DIE1+6]),
S_NORMAL (PIGY, 'K', 4, NULL , &States[S_PIGPLAY_DIE1+7]),
S_NORMAL (PIGY, 'L', -1, NULL , NULL),
#define S_PIGPLAY_ICE (S_PIGPLAY_DIE1+8)
S_NORMAL (PIGY, 'M', 5, A_FreezeDeath , &States[S_PIGPLAY_ICE+1]),
S_NORMAL (PIGY, 'M', 1, A_FreezeDeathChunks , &States[S_PIGPLAY_ICE+1]),
};
IMPLEMENT_ACTOR (APigPlayer, Hexen, -1, 0)
PROP_SpawnHealth (30)
PROP_ReactionTime (0)
PROP_PainChance (255)
PROP_RadiusFixed (16)
PROP_HeightFixed (24)
PROP_SpeedFixed (1)
PROP_Flags (MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_NOTDMATCH|MF_FRIENDLY)
PROP_Flags2 (MF2_WINDTHRUST|MF2_FLOORCLIP|MF2_SLIDE|MF2_PASSMOBJ|MF2_TELESTOMP|MF2_PUSHWALL)
PROP_Flags3 (MF3_NOBLOCKMONST)
PROP_Flags4 (MF4_NOSKIN)
PROP_SpawnState (S_PIGPLAY)
PROP_SeeState (S_PIGPLAY_RUN1)
PROP_PainState (S_PIGPLAY_PAIN)
PROP_MissileState (S_PIGPLAY_ATK1)
PROP_MeleeState (S_PIGPLAY_ATK1)
PROP_DeathState (S_PIGPLAY_DIE1)
PROP_IDeathState (S_PIGPLAY_ICE)
// [GRB]
PROP_PlayerPawn_JumpZ (6*FRACUNIT)
PROP_PlayerPawn_ViewHeight (28*FRACUNIT)
PROP_PlayerPawn_ForwardMove1 (FRACUNIT * 0x18 / 0x19) // Yes, the pig is faster than a mage.
PROP_PlayerPawn_ForwardMove2 (FRACUNIT * 0x31 / 0x32)
PROP_PlayerPawn_SideMove1 (FRACUNIT * 0x17 / 0x18)
PROP_PlayerPawn_SideMove2 (FRACUNIT * 0x27 / 0x28)
PROP_PlayerPawn_MorphWeapon ("Snout")
PROP_PainSound ("PigPain")
PROP_DeathSound ("PigDeath")
END_DEFAULTS
AT_GAME_SET(PigPlayer)
{
RUNTIME_CLASS(APigPlayer)->Meta.SetMetaString(APMETA_SoundClass, "pig");
}
void APigPlayer::MorphPlayerThink ()
{
if (player->morphTics&15)
{
return;
}
if(!(momx | momy) && pr_pigplayerthink() < 64)
{ // Snout sniff
if (player->ReadyWeapon != NULL)
{
P_SetPspriteNF(player, ps_weapon, player->ReadyWeapon->FindState(NAME_Flash));
}
S_Sound (this, CHAN_VOICE, "PigActive1", 1, ATTN_NORM); // snort
return;
}
if (pr_pigplayerthink() < 48)
{
S_Sound (this, CHAN_VOICE, "PigActive", 1, ATTN_NORM);
}
}
// Pig (non-player) ---------------------------------------------------------
class APig : public AMorphedMonster
{
DECLARE_ACTOR (APig, AMorphedMonster)
};
FState APig::States[] =
{
#define S_PIG_LOOK1 0
S_NORMAL (PIGY, 'B', 10, A_Look , &States[S_PIG_LOOK1]),
#define S_PIG_WALK1 (S_PIG_LOOK1+1)
S_NORMAL (PIGY, 'A', 3, A_Chase , &States[S_PIG_WALK1+1]),
S_NORMAL (PIGY, 'B', 3, A_Chase , &States[S_PIG_WALK1+2]),
S_NORMAL (PIGY, 'C', 3, A_Chase , &States[S_PIG_WALK1+3]),
S_NORMAL (PIGY, 'D', 3, A_Chase , &States[S_PIG_WALK1]),
#define S_PIG_PAIN (S_PIG_WALK1+4)
S_NORMAL (PIGY, 'D', 4, A_PigPain , &States[S_PIG_WALK1]),
#define S_PIG_ATK1 (S_PIG_PAIN+1)
S_NORMAL (PIGY, 'A', 5, A_FaceTarget , &States[S_PIG_ATK1+1]),
S_NORMAL (PIGY, 'A', 10, A_PigAttack , &States[S_PIG_WALK1]),
#define S_PIG_DIE1 (S_PIG_ATK1+2)
S_NORMAL (PIGY, 'E', 4, A_Scream , &States[S_PIG_DIE1+1]),
S_NORMAL (PIGY, 'F', 3, A_NoBlocking , &States[S_PIG_DIE1+2]),
S_NORMAL (PIGY, 'G', 4, A_QueueCorpse , &States[S_PIG_DIE1+3]),
S_NORMAL (PIGY, 'H', 3, NULL , &States[S_PIG_DIE1+4]),
S_NORMAL (PIGY, 'I', 4, NULL , &States[S_PIG_DIE1+5]),
S_NORMAL (PIGY, 'J', 4, NULL , &States[S_PIG_DIE1+6]),
S_NORMAL (PIGY, 'K', 4, NULL , &States[S_PIG_DIE1+7]),
S_NORMAL (PIGY, 'L', -1, NULL , NULL),
#define S_PIG_ICE (S_PIG_DIE1+8)
S_NORMAL (PIGY, 'M', 5, A_FreezeDeath , &States[S_PIG_ICE+1]),
S_NORMAL (PIGY, 'M', 1, A_FreezeDeathChunks , &States[S_PIG_ICE+1]),
};
IMPLEMENT_ACTOR (APig, Hexen, -1, 0)
PROP_SpawnHealth (25)
PROP_PainChance (128)
PROP_SpeedFixed (10)
PROP_RadiusFixed (12)
PROP_HeightFixed (22)
PROP_Mass (60)
PROP_Flags (MF_SOLID|MF_SHOOTABLE)
PROP_Flags2 (MF2_WINDTHRUST|MF2_FLOORCLIP|MF2_PASSMOBJ|MF2_TELESTOMP|MF2_PUSHWALL)
PROP_Flags3 (MF3_DONTMORPH|MF3_ISMONSTER)
PROP_SpawnState (S_PIG_LOOK1)
PROP_SeeState (S_PIG_WALK1)
PROP_PainState (S_PIG_PAIN)
PROP_MeleeState (S_PIG_ATK1)
PROP_DeathState (S_PIG_DIE1)
PROP_IDeathState (S_PIG_ICE)
PROP_SeeSound ("PigActive1")
PROP_PainSound ("PigPain")
PROP_DeathSound ("PigDeath")
PROP_ActiveSound ("PigActive1")
END_DEFAULTS
//============================================================================
//
// A_SnoutAttack
//
//============================================================================
void A_SnoutAttack (AActor *actor)
{
angle_t angle;
int damage;
int slope;
player_t *player;
if (NULL == (player = actor->player))
{
return;
}
damage = 3+(pr_snoutattack()&3);
angle = player->mo->angle;
slope = P_AimLineAttack(player->mo, angle, MELEERANGE);
PuffSpawned = NULL;
P_LineAttack(player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(ASnoutPuff));
S_Sound(player->mo, CHAN_VOICE, "PigActive", 1, ATTN_NORM);
if(linetarget)
{
AdjustPlayerAngle(player->mo);
if(PuffSpawned)
{ // Bit something
S_Sound(player->mo, CHAN_VOICE, "PigAttack", 1, ATTN_NORM);
}
}
}
//============================================================================
//
// A_PigAttack
//
//============================================================================
void A_PigAttack (AActor *actor)
{
if (!actor->target)
{
return;
}
if (actor->CheckMeleeRange ())
{
P_DamageMobj(actor->target, actor, actor, 2+(pr_pigattack()&1), NAME_Melee);
S_Sound(actor, CHAN_WEAPON, "PigAttack", 1, ATTN_NORM);
}
}
//============================================================================
//
// A_PigPain
//
//============================================================================
void A_PigPain (AActor *actor)
{
A_Pain (actor);
if (actor->z <= actor->floorz)
{
actor->momz = FRACUNIT*7/2;
}
}