#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 TypeInfo *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 (MOD_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 (MOD_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->CheckMeleeRange ()) { int damage = pr_atk.HitDice (2); P_DamageMobj (actor->target, actor, actor, damage, MOD_HIT); P_TraceBleed (damage, actor->target, actor); } } //============================================================================ // // A_DemonAttack2_1 (missile) // //============================================================================ void A_DemonAttack2_1 (AActor *actor) { 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) { 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 TypeInfo *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 TypeInfo *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 TypeInfo *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); 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; } } }