qzdoom/src/g_hexen/a_demons.cpp
Randy Heit 48bb782b19 - Fixed: Polyobjects are serialized before players, which means that a call
to PO_MovePolyobj() from P_SerializePolyobjs() for a crushing polyobject
  that touches a player actor will not have a valid actor->player->mo chain
  for P_DamageMobj and crash if it happens to touch the player. Since the
  polyobject was presumably in a good spot when the game was saved, we can
  just skip this step entirely and let it take care of itself the next time
  it moves (by which time, the players will be valid).
- Fixed: When transitioning from fullscreen to windowed mode with D3DFB, the
  window kept the WS_EX_TOPMOST style.
- Slight correctness fix: When in fullscreen, the window should have WS_POPUP
  style.
- Added a NULL target check to P_SpawnMissileXYZ(), A_DemonAttack1(),
  A_DemonAttack2_1(), and A_DemonAttack2_2().


SVN r384 (trunk)
2006-11-21 05:43:34 +00:00

666 lines
21 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_atk ("DemonAttack1");
static FRandom pr_demonchunks ("DemonChunks");
//============================================================================
// Demon AI
//============================================================================
void A_DemonAttack1 (AActor *);
void A_DemonAttack2_1 (AActor *);
void A_DemonAttack2_2 (AActor *);
void A_DemonDeath (AActor *);
void A_Demon2Death (AActor *);
static void TossChunks (AActor *, const PClass *const chunks[]);
// Demon, type 1 (green, like D'Sparil's) -----------------------------------
class ADemon1 : public AActor
{
DECLARE_ACTOR (ADemon1, AActor)
};
FState ADemon1::States[] =
{
#define S_DEMN_LOOK1 0
S_NORMAL (DEMN, 'A', 10, A_Look , &States[S_DEMN_LOOK1+1]),
S_NORMAL (DEMN, 'A', 10, A_Look , &States[S_DEMN_LOOK1]),
#define S_DEMN_CHASE1 (S_DEMN_LOOK1+2)
S_NORMAL (DEMN, 'A', 4, A_Chase , &States[S_DEMN_CHASE1+1]),
S_NORMAL (DEMN, 'B', 4, A_Chase , &States[S_DEMN_CHASE1+2]),
S_NORMAL (DEMN, 'C', 4, A_Chase , &States[S_DEMN_CHASE1+3]),
S_NORMAL (DEMN, 'D', 4, A_Chase , &States[S_DEMN_CHASE1]),
#define S_DEMN_PAIN1 (S_DEMN_CHASE1+4)
S_NORMAL (DEMN, 'E', 4, NULL , &States[S_DEMN_PAIN1+1]),
S_NORMAL (DEMN, 'E', 4, A_Pain , &States[S_DEMN_CHASE1]),
#define S_DEMN_ATK1_1 (S_DEMN_PAIN1+2)
S_NORMAL (DEMN, 'E', 6, A_FaceTarget , &States[S_DEMN_ATK1_1+1]),
S_NORMAL (DEMN, 'F', 8, A_FaceTarget , &States[S_DEMN_ATK1_1+2]),
S_NORMAL (DEMN, 'G', 6, A_DemonAttack1 , &States[S_DEMN_CHASE1]),
#define S_DEMN_ATK2_1 (S_DEMN_ATK1_1+3)
S_NORMAL (DEMN, 'E', 5, A_FaceTarget , &States[S_DEMN_ATK2_1+1]),
S_NORMAL (DEMN, 'F', 6, A_FaceTarget , &States[S_DEMN_ATK2_1+2]),
S_NORMAL (DEMN, 'G', 5, A_DemonAttack2_1 , &States[S_DEMN_CHASE1]),
#define S_DEMN_DEATH1 (S_DEMN_ATK2_1+3)
S_NORMAL (DEMN, 'H', 6, NULL , &States[S_DEMN_DEATH1+1]),
S_NORMAL (DEMN, 'I', 6, NULL , &States[S_DEMN_DEATH1+2]),
S_NORMAL (DEMN, 'J', 6, A_Scream , &States[S_DEMN_DEATH1+3]),
S_NORMAL (DEMN, 'K', 6, A_NoBlocking , &States[S_DEMN_DEATH1+4]),
S_NORMAL (DEMN, 'L', 6, A_QueueCorpse , &States[S_DEMN_DEATH1+5]),
S_NORMAL (DEMN, 'M', 6, NULL , &States[S_DEMN_DEATH1+6]),
S_NORMAL (DEMN, 'N', 6, NULL , &States[S_DEMN_DEATH1+7]),
S_NORMAL (DEMN, 'O', 6, NULL , &States[S_DEMN_DEATH1+8]),
S_NORMAL (DEMN, 'P', -1, NULL , NULL),
#define S_DEMN_XDEATH1 (S_DEMN_DEATH1+9)
S_NORMAL (DEMN, 'H', 6, NULL , &States[S_DEMN_XDEATH1+1]),
S_NORMAL (DEMN, 'I', 6, A_DemonDeath , &States[S_DEMN_XDEATH1+2]),
S_NORMAL (DEMN, 'J', 6, A_Scream , &States[S_DEMN_XDEATH1+3]),
S_NORMAL (DEMN, 'K', 6, A_NoBlocking , &States[S_DEMN_XDEATH1+4]),
S_NORMAL (DEMN, 'L', 6, A_QueueCorpse , &States[S_DEMN_XDEATH1+5]),
S_NORMAL (DEMN, 'M', 6, NULL , &States[S_DEMN_XDEATH1+6]),
S_NORMAL (DEMN, 'N', 6, NULL , &States[S_DEMN_XDEATH1+7]),
S_NORMAL (DEMN, 'O', 6, NULL , &States[S_DEMN_XDEATH1+8]),
S_NORMAL (DEMN, 'P', -1, NULL , NULL),
#define S_DEMON_ICE1 (S_DEMN_XDEATH1+9)
S_NORMAL (DEMN, 'Q', 5, A_FreezeDeath , &States[S_DEMON_ICE1+1]),
S_NORMAL (DEMN, 'Q', 1, A_FreezeDeathChunks , &States[S_DEMON_ICE1+1]),
};
IMPLEMENT_ACTOR (ADemon1, Hexen, 31, 3)
PROP_SpawnHealth (250)
PROP_PainChance (50)
PROP_SpeedFixed (13)
PROP_RadiusFixed (32)
PROP_HeightFixed (64)
PROP_Mass (220)
PROP_Flags (MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL)
PROP_Flags2 (MF2_FLOORCLIP|MF2_PASSMOBJ|MF2_TELESTOMP|MF2_MCROSS)
PROP_SpawnState (S_DEMN_LOOK1)
PROP_SeeState (S_DEMN_CHASE1)
PROP_PainState (S_DEMN_PAIN1)
PROP_MeleeState (S_DEMN_ATK1_1)
PROP_MissileState (S_DEMN_ATK2_1)
PROP_DeathState (S_DEMN_DEATH1)
PROP_XDeathState (S_DEMN_XDEATH1)
PROP_IDeathState (S_DEMON_ICE1)
PROP_SeeSound ("DemonSight")
PROP_AttackSound ("DemonAttack")
PROP_PainSound ("DemonPain")
PROP_DeathSound ("DemonDeath")
PROP_ActiveSound ("DemonActive")
END_DEFAULTS
// Demon, type 1, mashed ----------------------------------------------------
class ADemon1Mash : public ADemon1
{
DECLARE_STATELESS_ACTOR (ADemon1Mash, ADemon1)
};
IMPLEMENT_STATELESS_ACTOR (ADemon1Mash, Hexen, -1, 100)
PROP_FlagsSet (MF_NOBLOOD)
PROP_Flags2Set (MF2_BLASTED)
PROP_Flags2Clear (MF2_TELESTOMP)
PROP_Flags4Set(MF4_NOICEDEATH)
PROP_RenderStyle (STYLE_Translucent)
PROP_Alpha (HX_ALTSHADOW)
PROP_DeathState (~0)
PROP_XDeathState (~0)
PROP_IDeathState (~0)
END_DEFAULTS
// Demon chunk, base class --------------------------------------------------
class ADemonChunk : public AActor
{
DECLARE_STATELESS_ACTOR (ADemonChunk, AActor);
};
IMPLEMENT_STATELESS_ACTOR (ADemonChunk, Hexen, -1, 0)
PROP_RadiusFixed (5)
PROP_HeightFixed (5)
PROP_Flags (MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE|MF_CORPSE)
PROP_Flags2 (MF2_FLOORCLIP|MF2_NOTELEPORT)
END_DEFAULTS
// Demon, type 1, chunk 1 ---------------------------------------------------
class ADemon1Chunk1 : public ADemonChunk
{
DECLARE_ACTOR (ADemon1Chunk1, ADemonChunk)
};
FState ADemon1Chunk1::States[] =
{
#define S_DEMONCHUNK1_1 0
S_NORMAL (DEMA, 'A', 4, NULL , &States[S_DEMONCHUNK1_1+1]),
S_NORMAL (DEMA, 'A', 10, A_QueueCorpse , &States[S_DEMONCHUNK1_1+2]),
S_NORMAL (DEMA, 'A', 20, NULL , &States[S_DEMONCHUNK1_1+2]),
#define S_DEMONCHUNK1_4 (S_DEMONCHUNK1_1+3)
S_NORMAL (DEMA, 'A', -1, NULL , NULL),
};
IMPLEMENT_ACTOR (ADemon1Chunk1, Hexen, -1, 0)
PROP_SpawnState (S_DEMONCHUNK1_1)
PROP_DeathState (S_DEMONCHUNK1_4)
END_DEFAULTS
// Demon, type 1, chunk 2 ---------------------------------------------------
class ADemon1Chunk2 : public ADemonChunk
{
DECLARE_ACTOR (ADemon1Chunk2, ADemonChunk)
};
FState ADemon1Chunk2::States[] =
{
#define S_DEMONCHUNK2_1 0
S_NORMAL (DEMB, 'A', 4, NULL , &States[S_DEMONCHUNK2_1+1]),
S_NORMAL (DEMB, 'A', 10, A_QueueCorpse , &States[S_DEMONCHUNK2_1+2]),
S_NORMAL (DEMB, 'A', 20, NULL , &States[S_DEMONCHUNK2_1+2]),
#define S_DEMONCHUNK2_4 (S_DEMONCHUNK2_1+3)
S_NORMAL (DEMB, 'A', -1, NULL , NULL),
};
IMPLEMENT_ACTOR (ADemon1Chunk2, Hexen, -1, 0)
PROP_SpawnState (S_DEMONCHUNK2_1)
PROP_DeathState (S_DEMONCHUNK2_4)
END_DEFAULTS
// Demon, type 1, chunk 3 ---------------------------------------------------
class ADemon1Chunk3 : public ADemonChunk
{
DECLARE_ACTOR (ADemon1Chunk3, ADemonChunk)
};
FState ADemon1Chunk3::States[] =
{
#define S_DEMONCHUNK3_1 0
S_NORMAL (DEMC, 'A', 4, NULL , &States[S_DEMONCHUNK3_1+1]),
S_NORMAL (DEMC, 'A', 10, A_QueueCorpse , &States[S_DEMONCHUNK3_1+2]),
S_NORMAL (DEMC, 'A', 20, NULL , &States[S_DEMONCHUNK3_1+2]),
#define S_DEMONCHUNK3_4 (S_DEMONCHUNK3_1+3)
S_NORMAL (DEMC, 'A', -1, NULL , NULL),
};
IMPLEMENT_ACTOR (ADemon1Chunk3, Hexen, -1, 0)
PROP_SpawnState (S_DEMONCHUNK3_1)
PROP_DeathState (S_DEMONCHUNK3_4)
END_DEFAULTS
// Demon, type 1, chunk 4 ---------------------------------------------------
class ADemon1Chunk4 : public ADemonChunk
{
DECLARE_ACTOR (ADemon1Chunk4, ADemonChunk)
};
FState ADemon1Chunk4::States[] =
{
#define S_DEMONCHUNK4_1 0
S_NORMAL (DEMD, 'A', 4, NULL , &States[S_DEMONCHUNK4_1+1]),
S_NORMAL (DEMD, 'A', 10, A_QueueCorpse , &States[S_DEMONCHUNK4_1+2]),
S_NORMAL (DEMD, 'A', 20, NULL , &States[S_DEMONCHUNK4_1+2]),
#define S_DEMONCHUNK4_4 (S_DEMONCHUNK4_1+3)
S_NORMAL (DEMD, 'A', -1, NULL , NULL),
};
IMPLEMENT_ACTOR (ADemon1Chunk4, Hexen, -1, 0)
PROP_SpawnState (S_DEMONCHUNK4_1)
PROP_DeathState (S_DEMONCHUNK4_4)
END_DEFAULTS
// Demon, type 1, chunk 5 ---------------------------------------------------
class ADemon1Chunk5 : public ADemonChunk
{
DECLARE_ACTOR (ADemon1Chunk5, ADemonChunk)
};
FState ADemon1Chunk5::States[] =
{
#define S_DEMONCHUNK5_1 0
S_NORMAL (DEME, 'A', 4, NULL , &States[S_DEMONCHUNK5_1+1]),
S_NORMAL (DEME, 'A', 10, A_QueueCorpse , &States[S_DEMONCHUNK5_1+2]),
S_NORMAL (DEME, 'A', 20, NULL , &States[S_DEMONCHUNK5_1+2]),
#define S_DEMONCHUNK5_4 (S_DEMONCHUNK5_1+3)
S_NORMAL (DEME, 'A', -1, NULL , NULL),
};
IMPLEMENT_ACTOR (ADemon1Chunk5, Hexen, -1, 0)
PROP_SpawnState (S_DEMONCHUNK5_1)
PROP_DeathState (S_DEMONCHUNK5_4)
END_DEFAULTS
// Demon, type 1, projectile ------------------------------------------------
class ADemon1FX1 : public AActor
{
DECLARE_ACTOR (ADemon1FX1, AActor)
};
FState ADemon1FX1::States[] =
{
#define S_DEMONFX_MOVE1 0
S_BRIGHT (DMFX, 'A', 4, NULL , &States[S_DEMONFX_MOVE1+1]),
S_BRIGHT (DMFX, 'B', 4, NULL , &States[S_DEMONFX_MOVE1+2]),
S_BRIGHT (DMFX, 'C', 4, NULL , &States[S_DEMONFX_MOVE1]),
#define S_DEMONFX_BOOM1 (S_DEMONFX_MOVE1+3)
S_BRIGHT (DMFX, 'D', 4, NULL , &States[S_DEMONFX_BOOM1+1]),
S_BRIGHT (DMFX, 'E', 4, NULL , &States[S_DEMONFX_BOOM1+2]),
S_BRIGHT (DMFX, 'F', 3, NULL , &States[S_DEMONFX_BOOM1+3]),
S_BRIGHT (DMFX, 'G', 3, NULL , &States[S_DEMONFX_BOOM1+4]),
S_BRIGHT (DMFX, 'H', 3, NULL , NULL),
};
IMPLEMENT_ACTOR (ADemon1FX1, Hexen, -1, 0)
PROP_SpeedFixed (15)
PROP_RadiusFixed (10)
PROP_HeightFixed (6)
PROP_Damage (5)
PROP_DamageType (NAME_Fire)
PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE)
PROP_Flags2 (MF2_NOTELEPORT|MF2_IMPACT|MF2_PCROSS)
PROP_RenderStyle (STYLE_Add)
PROP_SpawnState (S_DEMONFX_MOVE1)
PROP_DeathState (S_DEMONFX_BOOM1)
PROP_DeathSound ("DemonMissileExplode")
END_DEFAULTS
// Demon, type 2 (brown) ----------------------------------------------------
class ADemon2 : public ADemon1
{
DECLARE_ACTOR (ADemon2, ADemon1)
};
FState ADemon2::States[] =
{
#define S_DEMN2_LOOK1 0
S_NORMAL (DEM2, 'A', 10, A_Look , &States[S_DEMN2_LOOK1+1]),
S_NORMAL (DEM2, 'A', 10, A_Look , &States[S_DEMN2_LOOK1]),
#define S_DEMN2_CHASE1 (S_DEMN2_LOOK1+2)
S_NORMAL (DEM2, 'A', 4, A_Chase , &States[S_DEMN2_CHASE1+1]),
S_NORMAL (DEM2, 'B', 4, A_Chase , &States[S_DEMN2_CHASE1+2]),
S_NORMAL (DEM2, 'C', 4, A_Chase , &States[S_DEMN2_CHASE1+3]),
S_NORMAL (DEM2, 'D', 4, A_Chase , &States[S_DEMN2_CHASE1]),
#define S_DEMN2_PAIN1 (S_DEMN2_CHASE1+4)
S_NORMAL (DEM2, 'E', 4, NULL , &States[S_DEMN2_PAIN1+1]),
S_NORMAL (DEM2, 'E', 4, A_Pain , &States[S_DEMN2_CHASE1]),
#define S_DEMN2_ATK1_1 (S_DEMN2_PAIN1+2)
S_NORMAL (DEM2, 'E', 6, A_FaceTarget , &States[S_DEMN2_ATK1_1+1]),
S_NORMAL (DEM2, 'F', 8, A_FaceTarget , &States[S_DEMN2_ATK1_1+2]),
S_NORMAL (DEM2, 'G', 6, A_DemonAttack1 , &States[S_DEMN2_CHASE1]),
#define S_DEMN2_ATK2_1 (S_DEMN2_ATK1_1+3)
S_NORMAL (DEM2, 'E', 5, A_FaceTarget , &States[S_DEMN2_ATK2_1+1]),
S_NORMAL (DEM2, 'F', 6, A_FaceTarget , &States[S_DEMN2_ATK2_1+2]),
S_NORMAL (DEM2, 'G', 5, A_DemonAttack2_2 , &States[S_DEMN2_CHASE1]),
#define S_DEMN2_DEATH1 (S_DEMN2_ATK2_1+3)
S_NORMAL (DEM2, 'H', 6, NULL , &States[S_DEMN2_DEATH1+1]),
S_NORMAL (DEM2, 'I', 6, NULL , &States[S_DEMN2_DEATH1+2]),
S_NORMAL (DEM2, 'J', 6, A_Scream , &States[S_DEMN2_DEATH1+3]),
S_NORMAL (DEM2, 'K', 6, A_NoBlocking , &States[S_DEMN2_DEATH1+4]),
S_NORMAL (DEM2, 'L', 6, A_QueueCorpse , &States[S_DEMN2_DEATH1+5]),
S_NORMAL (DEM2, 'M', 6, NULL , &States[S_DEMN2_DEATH1+6]),
S_NORMAL (DEM2, 'N', 6, NULL , &States[S_DEMN2_DEATH1+7]),
S_NORMAL (DEM2, 'O', 6, NULL , &States[S_DEMN2_DEATH1+8]),
S_NORMAL (DEM2, 'P', -1, NULL , NULL),
#define S_DEMN2_XDEATH1 (S_DEMN2_DEATH1+9)
S_NORMAL (DEM2, 'H', 6, NULL , &States[S_DEMN2_XDEATH1+1]),
S_NORMAL (DEM2, 'I', 6, A_Demon2Death , &States[S_DEMN2_XDEATH1+2]),
S_NORMAL (DEM2, 'J', 6, A_Scream , &States[S_DEMN2_XDEATH1+3]),
S_NORMAL (DEM2, 'K', 6, A_NoBlocking , &States[S_DEMN2_XDEATH1+4]),
S_NORMAL (DEM2, 'L', 6, A_QueueCorpse , &States[S_DEMN2_XDEATH1+5]),
S_NORMAL (DEM2, 'M', 6, NULL , &States[S_DEMN2_XDEATH1+6]),
S_NORMAL (DEM2, 'N', 6, NULL , &States[S_DEMN2_XDEATH1+7]),
S_NORMAL (DEM2, 'O', 6, NULL , &States[S_DEMN2_XDEATH1+8]),
S_NORMAL (DEM2, 'P', -1, NULL , NULL),
};
IMPLEMENT_ACTOR (ADemon2, Hexen, 8080, 0)
PROP_SpawnState (S_DEMN2_LOOK1)
PROP_SeeState (S_DEMN2_CHASE1)
PROP_PainState (S_DEMN2_PAIN1)
PROP_MeleeState (S_DEMN2_ATK1_1)
PROP_MissileState (S_DEMN2_ATK2_1)
PROP_DeathState (S_DEMN2_DEATH1)
PROP_XDeathState (S_DEMN2_XDEATH1)
END_DEFAULTS
// Demon, type 2, mashed ----------------------------------------------------
class ADemon2Mash : public ADemon2
{
DECLARE_STATELESS_ACTOR (ADemon2Mash, ADemon2)
};
IMPLEMENT_STATELESS_ACTOR (ADemon2Mash, Hexen, -1, 101)
PROP_FlagsSet (MF_NOBLOOD)
PROP_Flags2Set (MF2_BLASTED)
PROP_Flags2Clear (MF2_TELESTOMP)
PROP_Flags4Set(MF4_NOICEDEATH)
PROP_RenderStyle (STYLE_Translucent)
PROP_Alpha (HX_ALTSHADOW)
PROP_DeathState (~0)
PROP_XDeathState (~0)
PROP_IDeathState (~0)
END_DEFAULTS
// Demon, type 2, chunk 1 ---------------------------------------------------
class ADemon2Chunk1 : public ADemonChunk
{
DECLARE_ACTOR (ADemon2Chunk1, ADemonChunk)
};
FState ADemon2Chunk1::States[] =
{
#define S_DEMON2CHUNK1_1 0
S_NORMAL (DMBA, 'A', 4, NULL , &States[S_DEMON2CHUNK1_1+1]),
S_NORMAL (DMBA, 'A', 10, A_QueueCorpse , &States[S_DEMON2CHUNK1_1+2]),
S_NORMAL (DMBA, 'A', 20, NULL , &States[S_DEMON2CHUNK1_1+2]),
#define S_DEMON2CHUNK1_4 (S_DEMON2CHUNK1_1+3)
S_NORMAL (DMBA, 'A', -1, NULL , NULL),
};
IMPLEMENT_ACTOR (ADemon2Chunk1, Hexen, -1, 0)
PROP_SpawnState (S_DEMON2CHUNK1_1)
PROP_DeathState (S_DEMON2CHUNK1_4)
END_DEFAULTS
// Demon, type 2, chunk 2 ---------------------------------------------------
class ADemon2Chunk2 : public ADemonChunk
{
DECLARE_ACTOR (ADemon2Chunk2, ADemonChunk)
};
FState ADemon2Chunk2::States[] =
{
#define S_DEMON2CHUNK2_1 0
S_NORMAL (DMBB, 'A', 4, NULL , &States[S_DEMON2CHUNK2_1+1]),
S_NORMAL (DMBB, 'A', 10, A_QueueCorpse , &States[S_DEMON2CHUNK2_1+2]),
S_NORMAL (DMBB, 'A', 20, NULL , &States[S_DEMON2CHUNK2_1+2]),
#define S_DEMON2CHUNK2_4 (S_DEMON2CHUNK2_1+3)
S_NORMAL (DMBB, 'A', -1, NULL , NULL),
};
IMPLEMENT_ACTOR (ADemon2Chunk2, Hexen, -1, 0)
PROP_SpawnState (S_DEMON2CHUNK2_1)
PROP_DeathState (S_DEMON2CHUNK2_4)
END_DEFAULTS
// Demon, type 2, chunk 3 ---------------------------------------------------
class ADemon2Chunk3 : public ADemonChunk
{
DECLARE_ACTOR (ADemon2Chunk3, ADemonChunk)
};
FState ADemon2Chunk3::States[] =
{
#define S_DEMON2CHUNK3_1 0
S_NORMAL (DMBC, 'A', 4, NULL , &States[S_DEMON2CHUNK3_1+1]),
S_NORMAL (DMBC, 'A', 10, A_QueueCorpse , &States[S_DEMON2CHUNK3_1+2]),
S_NORMAL (DMBC, 'A', 20, NULL , &States[S_DEMON2CHUNK3_1+2]),
#define S_DEMON2CHUNK3_4 (S_DEMON2CHUNK3_1+3)
S_NORMAL (DMBC, 'A', -1, NULL , NULL),
};
IMPLEMENT_ACTOR (ADemon2Chunk3, Hexen, -1, 0)
PROP_SpawnState (S_DEMON2CHUNK3_1)
PROP_DeathState (S_DEMON2CHUNK3_4)
END_DEFAULTS
// Demon, type 2, chunk 4 ---------------------------------------------------
class ADemon2Chunk4 : public ADemonChunk
{
DECLARE_ACTOR (ADemon2Chunk4, ADemonChunk)
};
FState ADemon2Chunk4::States[] =
{
#define S_DEMON2CHUNK4_1 0
S_NORMAL (DMBD, 'A', 4, NULL , &States[S_DEMON2CHUNK4_1+1]),
S_NORMAL (DMBD, 'A', 10, A_QueueCorpse , &States[S_DEMON2CHUNK4_1+2]),
S_NORMAL (DMBD, 'A', 20, NULL , &States[S_DEMON2CHUNK4_1+2]),
#define S_DEMON2CHUNK4_4 (S_DEMON2CHUNK4_1+3)
S_NORMAL (DMBD, 'A', -1, NULL , NULL),
};
IMPLEMENT_ACTOR (ADemon2Chunk4, Hexen, -1, 0)
PROP_SpawnState (S_DEMON2CHUNK4_1)
PROP_DeathState (S_DEMON2CHUNK4_4)
END_DEFAULTS
// Demon, type 2, chunk 5 ---------------------------------------------------
class ADemon2Chunk5 : public ADemonChunk
{
DECLARE_ACTOR (ADemon2Chunk5, ADemonChunk)
};
FState ADemon2Chunk5::States[] =
{
#define S_DEMON2CHUNK5_1 0
S_NORMAL (DMBE, 'A', 4, NULL , &States[S_DEMON2CHUNK5_1+1]),
S_NORMAL (DMBE, 'A', 10, NULL , &States[S_DEMON2CHUNK5_1+2]),
S_NORMAL (DMBE, 'A', 20, NULL , &States[S_DEMON2CHUNK5_1+2]),
#define S_DEMON2CHUNK5_4 (S_DEMON2CHUNK5_1+3)
S_NORMAL (DMBE, 'A', -1, NULL , NULL),
};
IMPLEMENT_ACTOR (ADemon2Chunk5, Hexen, -1, 0)
PROP_SpawnState (S_DEMON2CHUNK5_1)
PROP_DeathState (S_DEMON2CHUNK5_4)
END_DEFAULTS
// Demon, type 2, projectile ------------------------------------------------
class ADemon2FX1 : public AActor
{
DECLARE_ACTOR (ADemon2FX1, AActor)
};
FState ADemon2FX1::States[] =
{
#define S_DEMON2FX_MOVE1 0
S_BRIGHT (D2FX, 'A', 4, NULL , &States[S_DEMON2FX_MOVE1+1]),
S_BRIGHT (D2FX, 'B', 4, NULL , &States[S_DEMON2FX_MOVE1+2]),
S_BRIGHT (D2FX, 'C', 4, NULL , &States[S_DEMON2FX_MOVE1+3]),
S_BRIGHT (D2FX, 'D', 4, NULL , &States[S_DEMON2FX_MOVE1+4]),
S_BRIGHT (D2FX, 'E', 4, NULL , &States[S_DEMON2FX_MOVE1+5]),
S_BRIGHT (D2FX, 'F', 4, NULL , &States[S_DEMON2FX_MOVE1]),
#define S_DEMON2FX_BOOM1 (S_DEMON2FX_MOVE1+6)
S_BRIGHT (D2FX, 'G', 4, NULL , &States[S_DEMON2FX_BOOM1+1]),
S_BRIGHT (D2FX, 'H', 4, NULL , &States[S_DEMON2FX_BOOM1+2]),
S_BRIGHT (D2FX, 'I', 4, NULL , &States[S_DEMON2FX_BOOM1+3]),
S_BRIGHT (D2FX, 'J', 4, NULL , &States[S_DEMON2FX_BOOM1+4]),
S_BRIGHT (D2FX, 'K', 3, NULL , &States[S_DEMON2FX_BOOM1+5]),
S_BRIGHT (D2FX, 'L', 3, NULL , NULL),
};
IMPLEMENT_ACTOR (ADemon2FX1, Hexen, -1, 0)
PROP_SpeedFixed (15)
PROP_RadiusFixed (10)
PROP_HeightFixed (6)
PROP_Damage (5)
PROP_DamageType (NAME_Fire)
PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE)
PROP_Flags2 (MF2_NOTELEPORT|MF2_IMPACT|MF2_PCROSS)
PROP_RenderStyle (STYLE_Add)
PROP_SpawnState (S_DEMON2FX_MOVE1)
PROP_DeathState (S_DEMON2FX_BOOM1)
PROP_DeathSound ("DemonMissileExplode")
END_DEFAULTS
//============================================================================
//
// A_DemonAttack1 (melee)
//
//============================================================================
void A_DemonAttack1 (AActor *actor)
{
if (actor->target != NULL && actor->CheckMeleeRange ())
{
int damage = pr_atk.HitDice (2);
P_DamageMobj (actor->target, actor, actor, damage, NAME_Melee);
P_TraceBleed (damage, actor->target, actor);
}
}
//============================================================================
//
// A_DemonAttack2_1 (missile)
//
//============================================================================
void A_DemonAttack2_1 (AActor *actor)
{
if (actor->target != NULL)
{
AActor *mo;
// Improve the aiming of this code!
actor->z += 30*FRACUNIT;
mo = P_SpawnMissile (actor, actor->target, RUNTIME_CLASS(ADemon1FX1));
actor->z -= 30*FRACUNIT;
if (mo)
{
S_Sound (actor, CHAN_BODY, "DemonMissileFire", 1, ATTN_NORM);
}
}
}
//============================================================================
//
// A_DemonAttack2_2 (missile)
//
//============================================================================
void A_DemonAttack2_2 (AActor *actor)
{
if (actor->target != NULL)
{
AActor *mo;
// Improve the aiming of this code!
actor->z += 30*FRACUNIT;
mo = P_SpawnMissile (actor, actor->target, RUNTIME_CLASS(ADemon2FX1));
actor->z -= 30*FRACUNIT;
if (mo)
{
S_Sound (actor, CHAN_BODY, "DemonMissileFire", 1, ATTN_NORM);
}
}
}
//============================================================================
//
// A_DemonDeath
//
//============================================================================
void A_DemonDeath (AActor *actor)
{
const PClass *const ChunkTypes[] =
{
RUNTIME_CLASS(ADemon1Chunk5),
RUNTIME_CLASS(ADemon1Chunk4),
RUNTIME_CLASS(ADemon1Chunk3),
RUNTIME_CLASS(ADemon1Chunk2),
RUNTIME_CLASS(ADemon1Chunk1)
};
TossChunks (actor, ChunkTypes);
}
//===========================================================================
//
// A_Demon2Death
//
//===========================================================================
void A_Demon2Death (AActor *actor)
{
const PClass *const ChunkTypes[] =
{
RUNTIME_CLASS(ADemon2Chunk5),
RUNTIME_CLASS(ADemon2Chunk4),
RUNTIME_CLASS(ADemon2Chunk3),
RUNTIME_CLASS(ADemon2Chunk2),
RUNTIME_CLASS(ADemon2Chunk1)
};
TossChunks (actor, ChunkTypes);
}
static void TossChunks (AActor *actor, const PClass *const chunks[])
{
AActor *mo;
angle_t angle;
int i;
for (i = 4; i >= 0; --i)
{
mo = Spawn (chunks[i], actor->x, actor->y, actor->z+45*FRACUNIT, ALLOW_REPLACE);
if (mo)
{
angle = actor->angle + (i<4 ? ANGLE_270 : ANGLE_90);
mo->momz = 8*FRACUNIT;
mo->momx = FixedMul((pr_demonchunks()<<10)+FRACUNIT,
finecosine[angle>>ANGLETOFINESHIFT]);
mo->momy = FixedMul((pr_demonchunks()<<10)+FRACUNIT,
finesine[angle>>ANGLETOFINESHIFT]);
mo->target = actor;
}
}
}