vkdoom_m/src/g_hexen/a_ettin.cpp
Christoph Oelckers 063c85b157 - Fixed: The global WeaponSection string was never freed. It has been replaced
with an FString now.
- Fixed: The music strings in the default level info were never freed and
  caused memory leaks when used repeatedly.
- Fixed: The intermusic string in the level info was never freed.
- Fixed: The default fire obituary should only be printed if the damage
  came from the environment. If it comes from a monster the monster specific
  obituary should be used instead.
- Added custom damage types from the floating point test release.
- Changed Pain Elemental's massacre check. Now A_PainDie checks for the damage 
  type and doesn't spawn anything if it is NAME_Massacre. A_PainDie can also 
  be used by other actors so a more generalized approach is needed than hard
  coding it into the Pain Elemental.
- Converted a few of Doom's monsters to DECORATE because I couldn't test the
  first version of the custom state code with the corpses inheriting from them.
- Added custom states from last year's floating point test release and fixed
  some bugs I found in that code. Unfortunately it wasn't all salvageable
  and it was easier to recreate some parts from scratch.



SVN r368 (trunk)
2006-10-31 14:53:21 +00:00

185 lines
5.8 KiB
C++

#include "actor.h"
#include "info.h"
#include "p_local.h"
#include "s_sound.h"
#include "p_enemy.h"
#include "a_action.h"
#include "m_random.h"
static FRandom pr_ettinatk ("EttinAttack");
static FRandom pr_dropmace ("DropMace");
// Ettin --------------------------------------------------------------------
void A_EttinAttack (AActor *);
void A_DropMace (AActor *);
class AEttin : public AActor
{
DECLARE_ACTOR (AEttin, AActor)
public:
void Howl ();
};
FState AEttin::States[] =
{
#define S_ETTIN_LOOK 0
S_NORMAL (ETTN, 'A', 10, A_Look , &States[S_ETTIN_LOOK+1]),
S_NORMAL (ETTN, 'A', 10, A_Look , &States[S_ETTIN_LOOK+0]),
#define S_ETTIN_CHASE (S_ETTIN_LOOK+2)
S_NORMAL (ETTN, 'A', 5, A_Chase , &States[S_ETTIN_CHASE+1]),
S_NORMAL (ETTN, 'B', 5, A_Chase , &States[S_ETTIN_CHASE+2]),
S_NORMAL (ETTN, 'C', 5, A_Chase , &States[S_ETTIN_CHASE+3]),
S_NORMAL (ETTN, 'D', 5, A_Chase , &States[S_ETTIN_CHASE+0]),
#define S_ETTIN_PAIN (S_ETTIN_CHASE+4)
S_NORMAL (ETTN, 'H', 7, A_Pain , &States[S_ETTIN_CHASE+0]),
#define S_ETTIN_ATK1 (S_ETTIN_PAIN+1)
S_NORMAL (ETTN, 'E', 6, A_FaceTarget , &States[S_ETTIN_ATK1+1]),
S_NORMAL (ETTN, 'F', 6, A_FaceTarget , &States[S_ETTIN_ATK1+2]),
S_NORMAL (ETTN, 'G', 8, A_EttinAttack , &States[S_ETTIN_CHASE+0]),
#define S_ETTIN_DEATH1 (S_ETTIN_ATK1+3)
S_NORMAL (ETTN, 'I', 4, NULL , &States[S_ETTIN_DEATH1+1]),
S_NORMAL (ETTN, 'J', 4, NULL , &States[S_ETTIN_DEATH1+2]),
S_NORMAL (ETTN, 'K', 4, A_Scream , &States[S_ETTIN_DEATH1+3]),
S_NORMAL (ETTN, 'L', 4, A_NoBlocking , &States[S_ETTIN_DEATH1+4]),
S_NORMAL (ETTN, 'M', 4, A_QueueCorpse , &States[S_ETTIN_DEATH1+5]),
S_NORMAL (ETTN, 'N', 4, NULL , &States[S_ETTIN_DEATH1+6]),
S_NORMAL (ETTN, 'O', 4, NULL , &States[S_ETTIN_DEATH1+7]),
S_NORMAL (ETTN, 'P', 4, NULL , &States[S_ETTIN_DEATH1+8]),
S_NORMAL (ETTN, 'Q', -1, NULL , NULL),
#define S_ETTIN_DEATH2 (S_ETTIN_DEATH1+9)
S_NORMAL (ETTB, 'A', 4, NULL , &States[S_ETTIN_DEATH2+1]),
S_NORMAL (ETTB, 'B', 4, A_NoBlocking , &States[S_ETTIN_DEATH2+2]),
S_NORMAL (ETTB, 'C', 4, A_DropMace , &States[S_ETTIN_DEATH2+3]),
S_NORMAL (ETTB, 'D', 4, A_Scream , &States[S_ETTIN_DEATH2+4]),
S_NORMAL (ETTB, 'E', 4, A_QueueCorpse , &States[S_ETTIN_DEATH2+5]),
S_NORMAL (ETTB, 'F', 4, NULL , &States[S_ETTIN_DEATH2+6]),
S_NORMAL (ETTB, 'G', 4, NULL , &States[S_ETTIN_DEATH2+7]),
S_NORMAL (ETTB, 'H', 4, NULL , &States[S_ETTIN_DEATH2+8]),
S_NORMAL (ETTB, 'I', 4, NULL , &States[S_ETTIN_DEATH2+9]),
S_NORMAL (ETTB, 'J', 4, NULL , &States[S_ETTIN_DEATH2+10]),
S_NORMAL (ETTB, 'K', 4, NULL , &States[S_ETTIN_DEATH2+11]),
S_NORMAL (ETTB, 'L', -1, NULL , NULL),
#define S_ETTIN_ICE (S_ETTIN_DEATH2+12)
S_NORMAL (ETTN, 'R', 5, A_FreezeDeath , &States[S_ETTIN_ICE+1]),
S_NORMAL (ETTN, 'R', 1, A_FreezeDeathChunks , &States[S_ETTIN_ICE+1])
};
IMPLEMENT_ACTOR (AEttin, Hexen, 10030, 4)
PROP_SpawnHealth (175)
PROP_RadiusFixed (25)
PROP_HeightFixed (68)
PROP_Mass (175)
PROP_SpeedFixed (13)
PROP_Damage (3)
PROP_PainChance (60)
PROP_Flags (MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL)
PROP_Flags2 (MF2_FLOORCLIP|MF2_PUSHWALL|MF2_MCROSS|MF2_TELESTOMP)
PROP_SpawnState (S_ETTIN_LOOK)
PROP_SeeState (S_ETTIN_CHASE)
PROP_PainState (S_ETTIN_PAIN)
PROP_MeleeState (S_ETTIN_ATK1)
PROP_DeathState (S_ETTIN_DEATH1)
PROP_XDeathState (S_ETTIN_DEATH2)
PROP_IDeathState (S_ETTIN_ICE)
PROP_SeeSound ("EttinSight")
PROP_AttackSound ("EttinAttack")
PROP_PainSound ("EttinPain")
PROP_DeathSound ("EttinDeath")
PROP_ActiveSound ("EttinActive")
END_DEFAULTS
void AEttin::Howl ()
{
int howl = S_FindSound ("PuppyBeat");
if (!S_GetSoundPlayingInfo (this, howl))
{
S_SoundID (this, CHAN_BODY, howl, 1, ATTN_NORM);
}
}
// Ettin mace ---------------------------------------------------------------
class AEttinMace : public AActor
{
DECLARE_ACTOR (AEttinMace, AActor)
};
FState AEttinMace::States[] =
{
S_NORMAL (ETTB, 'M', 5, NULL , &States[1]),
S_NORMAL (ETTB, 'N', 5, NULL , &States[2]),
S_NORMAL (ETTB, 'O', 5, NULL , &States[3]),
S_NORMAL (ETTB, 'P', 5, NULL , &States[0]),
S_NORMAL (ETTB, 'Q', 5, NULL , &States[5]),
S_NORMAL (ETTB, 'R', 5, A_QueueCorpse , &States[6]),
S_NORMAL (ETTB, 'S', -1, NULL , NULL)
};
IMPLEMENT_ACTOR (AEttinMace, Hexen, -1, 0)
PROP_RadiusFixed (5)
PROP_HeightFixed (5)
PROP_Flags (MF_DROPOFF|MF_CORPSE)
PROP_Flags2 (MF2_NOTELEPORT|MF2_FLOORCLIP)
PROP_SpawnState (0)
PROP_CrashState (4)
END_DEFAULTS
// Ettin mash ---------------------------------------------------------------
class AEttinMash : public AEttin
{
DECLARE_STATELESS_ACTOR (AEttinMash, AEttin)
};
IMPLEMENT_STATELESS_ACTOR (AEttinMash, Hexen, -1, 102)
PROP_FlagsSet (MF_NOBLOOD)
PROP_Flags2Set (MF2_FLOORCLIP|MF2_PASSMOBJ|MF2_MCROSS|MF2_PUSHWALL|MF2_BLASTED)
PROP_Flags4Set(MF4_NOICEDEATH)
PROP_RenderStyle (STYLE_Translucent)
PROP_Alpha (HX_ALTSHADOW)
PROP_DeathState (~0)
PROP_XDeathState (~0)
PROP_IDeathState (~0)
END_DEFAULTS
//============================================================================
// Ettin AI
//============================================================================
void A_EttinAttack (AActor *actor)
{
if (actor->CheckMeleeRange())
{
int damage = pr_ettinatk.HitDice (2);
P_DamageMobj (actor->target, actor, actor, damage, NAME_Melee);
P_TraceBleed (damage, actor->target, actor);
}
}
void A_DropMace (AActor *actor)
{
AEttinMace *mo;
mo = Spawn<AEttinMace> (actor->x, actor->y,
actor->z + (actor->height>>1), ALLOW_REPLACE);
if (mo)
{
mo->momx = (pr_dropmace()-128) << 11;
mo->momy = (pr_dropmace()-128) << 11;
mo->momz = FRACUNIT*10+(pr_dropmace()<<10);
mo->target = actor;
}
}