- fixed: Morphing to a class without a face definition crashed.

- Converted all of Heretic's actors except the weapons to DECORATE.
- Added the option to define the ActorInfos for native classes in DECORATE.


SVN r1078 (trunk)
This commit is contained in:
Christoph Oelckers 2008-07-21 17:03:30 +00:00
commit a8c283dacd
29 changed files with 1580 additions and 2009 deletions

View file

@ -99,12 +99,6 @@ ACTOR(PlayerSkinCheck)
ACTOR(QueueCorpse)
ACTOR(DeQueueCorpse)
ACTOR(SetGravity)
// Special code pointers for Strife's player - not to be used elsewhere!
ACTOR(ItBurnsItBurns)
ACTOR(CrispyPlayer)
ACTOR(DropFire)
ACTOR(ClearTarget)
ACTOR(LookEx)
ACTOR(JumpIfTargetInLOS)
@ -113,3 +107,47 @@ ACTOR(DamageChildren)
ACTOR(CheckForReload)
ACTOR(ResetReloadCounter)
ACTOR(ClearReFire)
// Heretic stuff
ACTOR(Feathers)
ACTOR(BeakRaise)
ACTOR(BeakAttackPL1)
ACTOR(BeakAttackPL2)
ACTOR(Sor1Pain)
ACTOR(Sor1Chase)
ACTOR(Srcr1Attack)
ACTOR(SorcererRise)
ACTOR(Srcr2Decide)
ACTOR(Srcr2Attack)
ACTOR(Sor2DthInit)
ACTOR(Sor2DthLoop)
ACTOR(BlueSpark)
ACTOR(GenWizard)
ACTOR(TimeBomb)
ACTOR(ImpDeath)
ACTOR(ImpXDeath1)
ACTOR(ImpExplode)
ACTOR(PodPain)
ACTOR(RemovePod)
ACTOR(MakePod)
ACTOR(AccTeleGlitter)
ACTOR(VolcanoSet)
ACTOR(VolcanoBlast)
ACTOR(VolcBallImpact)
ACTOR(LichAttack)
ACTOR(LichIceImpact)
ACTOR(LichFireGrow)
ACTOR(WhirlwindSeek)
ACTOR(KnightAttack)
ACTOR(DripBlood)
ACTOR(GhostOff)
ACTOR(WizAtk1)
ACTOR(WizAtk2)
ACTOR(WizAtk3)
// Special code pointers for Strife's player - not to be used elsewhere!
ACTOR(ItBurnsItBurns)
ACTOR(CrispyPlayer)
ACTOR(DropFire)

View file

@ -145,7 +145,14 @@ void PClass::StaticFreeData (PClass *type)
delete type->ActorInfo;
type->ActorInfo = NULL;
}
delete type;
if (type->bRuntimeClass != 2)
{
delete type;
}
else
{
type->Symbols.ReleaseSymbols();
}
}
else
{
@ -290,6 +297,42 @@ PClass *PClass::CreateDerivedClass (FName name, unsigned int size)
return type;
}
// This is used by DECORATE to assign ActorInfos to internal classes
void PClass::InitializeActorInfo ()
{
Symbols.SetParentTable (&ParentClass->Symbols);
Defaults = new BYTE[Size];
if (ParentClass->Defaults != NULL)
{
memcpy (Defaults, ParentClass->Defaults, Size);
if (Size > ParentClass->Size)
{
memset (Defaults + ParentClass->Size, 0, Size - ParentClass->Size);
}
}
else
{
memset (Defaults, 0, Size);
}
bRuntimeClass = 2; // Class is internal but actor data external
FActorInfo *info = ActorInfo = new FActorInfo;
info->Class = this;
info->GameFilter = GAME_Any;
info->SpawnID = 0;
info->DoomEdNum = -1;
info->OwnedStates = NULL;
info->NumOwnedStates = 0;
info->Replacement = NULL;
info->Replacee = NULL;
info->StateList = NULL;
info->DamageFactors = NULL;
info->PainChances = NULL;
m_RuntimeActors.Push (this);
}
// Create the FlatPointers array, if it doesn't exist already.
// It comprises all the Pointers from superclasses plus this class's own Pointers.
// If this class does not define any new Pointers, then FlatPointers will be set

View file

@ -103,7 +103,7 @@ struct PClass
PClass *HashNext;
FMetaTable Meta;
BYTE *Defaults;
bool bRuntimeClass; // class was defined at run-time, not compile-time
BYTE bRuntimeClass; // class was defined at run-time, not compile-time
unsigned short ClassIndex;
PSymbolTable Symbols;
@ -113,6 +113,7 @@ struct PClass
void InsertIntoHash ();
DObject *CreateNew () const;
PClass *CreateDerivedClass (FName name, unsigned int size);
void InitializeActorInfo ();
void BuildFlatPointers ();
void FreeStateList();

View file

@ -12,166 +12,22 @@
#include "d_event.h"
#include "gstrings.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");
void A_BeakRaise (AActor *);
void A_BeakAttackPL1 (AActor *);
void A_BeakAttackPL2 (AActor *);
void A_Feathers (AActor *);
void A_ChicAttack (AActor *);
void P_UpdateBeak (AActor *);
// Beak puff ----------------------------------------------------------------
class ABeakPuff : public AStaffPuff
{
DECLARE_STATELESS_ACTOR (ABeakPuff, AStaffPuff)
public:
void BeginPlay ();
};
IMPLEMENT_STATELESS_ACTOR (ABeakPuff, Heretic, -1, 0)
PROP_Mass (5)
PROP_RenderStyle (STYLE_Translucent)
PROP_Alpha (HR_SHADOW)
PROP_AttackSound ("chicken/attack")
END_DEFAULTS
void ABeakPuff::BeginPlay ()
{
Super::BeginPlay ();
momz = FRACUNIT;
}
// Beak ---------------------------------------------------------------------
class ABeak : public AWeapon
{
DECLARE_ACTOR (ABeak, AWeapon)
};
class ABeakPowered : public ABeak
{
DECLARE_STATELESS_ACTOR (ABeakPowered, ABeak)
};
FState ABeak::States[] =
{
#define S_BEAKREADY 0
S_NORMAL (BEAK, 'A', 1, A_WeaponReady , &States[S_BEAKREADY]),
#define S_BEAKDOWN (S_BEAKREADY+1)
S_NORMAL (BEAK, 'A', 1, A_Lower , &States[S_BEAKDOWN]),
#define S_BEAKUP (S_BEAKDOWN+1)
S_NORMAL (BEAK, 'A', 1, A_BeakRaise , &States[S_BEAKUP]),
#define S_BEAKATK1 (S_BEAKUP+1)
S_NORMAL (BEAK, 'A', 18, A_BeakAttackPL1 , &States[S_BEAKREADY]),
#define S_BEAKATK2 (S_BEAKATK1+1)
S_NORMAL (BEAK, 'A', 12, A_BeakAttackPL2 , &States[S_BEAKREADY])
};
IMPLEMENT_ACTOR (ABeak, Heretic, -1, 0)
PROP_Weapon_SelectionOrder (10000)
PROP_Weapon_Flags (WIF_DONTBOB|WIF_BOT_MELEE)
PROP_Weapon_UpState (S_BEAKUP)
PROP_Weapon_DownState (S_BEAKDOWN)
PROP_Weapon_ReadyState (S_BEAKREADY)
PROP_Weapon_AtkState (S_BEAKATK1)
PROP_Weapon_HoldAtkState (S_BEAKATK1)
PROP_Weapon_YAdjust (15)
PROP_Weapon_SisterType ("BeakPowered")
END_DEFAULTS
IMPLEMENT_STATELESS_ACTOR (ABeakPowered, Heretic, -1, 0)
PROP_Weapon_Flags (WIF_DONTBOB|WIF_BOT_MELEE|WIF_POWERED_UP)
PROP_Weapon_AtkState (S_BEAKATK2)
PROP_Weapon_HoldAtkState (S_BEAKATK2)
PROP_Weapon_SisterType ("Beak")
END_DEFAULTS
// Chicken player -----------------------------------------------------------
class AChickenPlayer : public APlayerPawn
{
DECLARE_ACTOR (AChickenPlayer, APlayerPawn)
DECLARE_CLASS (AChickenPlayer, APlayerPawn)
public:
void MorphPlayerThink ();
};
FState AChickenPlayer::States[] =
{
#define S_CHICPLAY 0
S_NORMAL (CHKN, 'A', -1, NULL , NULL),
#define S_CHICPLAY_RUN (S_CHICPLAY+1)
S_NORMAL (CHKN, 'A', 3, NULL , &States[S_CHICPLAY_RUN+1]),
S_NORMAL (CHKN, 'B', 3, NULL , &States[S_CHICPLAY_RUN+2]),
S_NORMAL (CHKN, 'A', 3, NULL , &States[S_CHICPLAY_RUN+3]),
S_NORMAL (CHKN, 'B', 3, NULL , &States[S_CHICPLAY_RUN+0]),
#define S_CHICPLAY_ATK (S_CHICPLAY_RUN+4)
S_NORMAL (CHKN, 'C', 12, NULL , &States[S_CHICPLAY]),
#define S_CHICPLAY_PAIN (S_CHICPLAY_ATK+1)
S_NORMAL (CHKN, 'D', 4, A_Feathers , &States[S_CHICPLAY_PAIN+1]),
S_NORMAL (CHKN, 'C', 4, A_Pain , &States[S_CHICPLAY]),
#define S_CHICPLAY_DIE (S_CHICPLAY_PAIN+2)
S_NORMAL (CHKN, 'E', 6, A_Scream , &States[S_CHICPLAY_DIE+1]),
S_NORMAL (CHKN, 'F', 6, A_Feathers , &States[S_CHICPLAY_DIE+2]),
S_NORMAL (CHKN, 'G', 6, NULL , &States[S_CHICPLAY_DIE+3]),
S_NORMAL (CHKN, 'H', 6, A_NoBlocking , &States[S_CHICPLAY_DIE+4]),
S_NORMAL (CHKN, 'I', 6, NULL , &States[S_CHICPLAY_DIE+5]),
S_NORMAL (CHKN, 'J', 6, NULL , &States[S_CHICPLAY_DIE+6]),
S_NORMAL (CHKN, 'K', 6, NULL , &States[S_CHICPLAY_DIE+7]),
S_NORMAL (CHKN, 'L', -1, NULL , NULL)
};
IMPLEMENT_ACTOR (AChickenPlayer, Heretic, -1, 0)
PROP_SpawnHealth (30)
PROP_RadiusFixed (16)
PROP_HeightFixed (24)
PROP_PainChance (255)
PROP_SpeedFixed (1)
PROP_Gravity (FRACUNIT/8)
PROP_Flags (MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_NOTDMATCH|MF_FRIENDLY)
PROP_Flags2 (MF2_WINDTHRUST|MF2_SLIDE|MF2_PASSMOBJ|MF2_PUSHWALL|MF2_FLOORCLIP|MF2_TELESTOMP)
PROP_Flags3 (MF3_NOBLOCKMONST)
PROP_Flags4 (MF4_NOSKIN)
PROP_SpawnState (S_CHICPLAY)
PROP_SeeState (S_CHICPLAY_RUN)
PROP_PainState (S_CHICPLAY_PAIN)
PROP_MissileState (S_CHICPLAY_ATK)
PROP_MeleeState (S_CHICPLAY_ATK)
PROP_DeathState (S_CHICPLAY_DIE)
// [GRB]
PROP_PlayerPawn_JumpZ (FRACUNIT)
PROP_PlayerPawn_ViewHeight (21*FRACUNIT)
PROP_PlayerPawn_ForwardMove1 (FRACUNIT * 2500 / 2048)
PROP_PlayerPawn_ForwardMove2 (FRACUNIT * 2500 / 2048)
PROP_PlayerPawn_SideMove1 (FRACUNIT * 2500 / 2048)
PROP_PlayerPawn_SideMove2 (FRACUNIT * 2500 / 2048)
PROP_PlayerPawn_MorphWeapon ("Beak")
PROP_PainSound ("chicken/pain")
PROP_DeathSound ("chicken/death")
END_DEFAULTS
AT_GAME_SET(ChickenPlayer)
{
RUNTIME_CLASS(AChickenPlayer)->Meta.SetMetaString(APMETA_SoundClass, "chicken");
}
IMPLEMENT_CLASS(AChickenPlayer)
void AChickenPlayer::MorphPlayerThink ()
{
@ -200,102 +56,6 @@ void AChickenPlayer::MorphPlayerThink ()
}
}
// Chicken (non-player) -----------------------------------------------------
class AChicken : public AMorphedMonster
{
DECLARE_ACTOR (AChicken, AMorphedMonster)
};
FState AChicken::States[] =
{
#define S_CHICKEN_LOOK 0
S_NORMAL (CHKN, 'A', 10, A_Look , &States[S_CHICKEN_LOOK+1]),
S_NORMAL (CHKN, 'B', 10, A_Look , &States[S_CHICKEN_LOOK+0]),
#define S_CHICKEN_WALK (S_CHICKEN_LOOK+2)
S_NORMAL (CHKN, 'A', 3, A_Chase , &States[S_CHICKEN_WALK+1]),
S_NORMAL (CHKN, 'B', 3, A_Chase , &States[S_CHICKEN_WALK+0]),
#define S_CHICKEN_PAIN (S_CHICKEN_WALK+2)
S_NORMAL (CHKN, 'D', 5, A_Feathers , &States[S_CHICKEN_PAIN+1]),
S_NORMAL (CHKN, 'C', 5, A_Pain , &States[S_CHICKEN_WALK+0]),
#define S_CHICKEN_ATK (S_CHICKEN_PAIN+2)
S_NORMAL (CHKN, 'A', 8, A_FaceTarget , &States[S_CHICKEN_ATK+1]),
S_NORMAL (CHKN, 'C', 10, A_ChicAttack , &States[S_CHICKEN_WALK+0]),
#define S_CHICKEN_DIE (S_CHICKEN_ATK+2)
S_NORMAL (CHKN, 'E', 6, A_Scream , &States[S_CHICKEN_DIE+1]),
S_NORMAL (CHKN, 'F', 6, A_Feathers , &States[S_CHICKEN_DIE+2]),
S_NORMAL (CHKN, 'G', 6, NULL , &States[S_CHICKEN_DIE+3]),
S_NORMAL (CHKN, 'H', 6, A_NoBlocking , &States[S_CHICKEN_DIE+4]),
S_NORMAL (CHKN, 'I', 6, NULL , &States[S_CHICKEN_DIE+5]),
S_NORMAL (CHKN, 'J', 6, NULL , &States[S_CHICKEN_DIE+6]),
S_NORMAL (CHKN, 'K', 6, NULL , &States[S_CHICKEN_DIE+7]),
S_NORMAL (CHKN, 'L', -1, NULL , NULL)
};
IMPLEMENT_ACTOR (AChicken, Heretic, -1, 122)
PROP_SpawnHealth (10)
PROP_RadiusFixed (9)
PROP_HeightFixed (22)
PROP_Mass (40)
PROP_SpeedFixed (4)
PROP_PainChance (200)
PROP_Flags (MF_SOLID|MF_SHOOTABLE)
PROP_Flags2 (MF2_MCROSS|MF2_WINDTHRUST|MF2_FLOORCLIP|MF2_PASSMOBJ|MF2_PUSHWALL)
PROP_Flags3 (MF3_DONTMORPH|MF3_ISMONSTER)
PROP_SpawnState (S_CHICKEN_LOOK)
PROP_SeeState (S_CHICKEN_WALK)
PROP_PainState (S_CHICKEN_PAIN)
PROP_MeleeState (S_CHICKEN_ATK)
PROP_DeathState (S_CHICKEN_DIE)
PROP_SeeSound ("chicken/pain")
PROP_AttackSound ("chicken/attack")
PROP_PainSound ("chicken/pain")
PROP_DeathSound ("chicken/death")
PROP_ActiveSound ("chicken/active")
PROP_Obituary("$OB_CHICKEN")
END_DEFAULTS
// Feather ------------------------------------------------------------------
class AFeather : public AActor
{
DECLARE_ACTOR (AFeather, AActor)
};
FState AFeather::States[] =
{
#define S_FEATHER 0
S_NORMAL (CHKN, 'M', 3, NULL , &States[S_FEATHER+1]),
S_NORMAL (CHKN, 'N', 3, NULL , &States[S_FEATHER+2]),
S_NORMAL (CHKN, 'O', 3, NULL , &States[S_FEATHER+3]),
S_NORMAL (CHKN, 'P', 3, NULL , &States[S_FEATHER+4]),
S_NORMAL (CHKN, 'Q', 3, NULL , &States[S_FEATHER+5]),
S_NORMAL (CHKN, 'P', 3, NULL , &States[S_FEATHER+6]),
S_NORMAL (CHKN, 'O', 3, NULL , &States[S_FEATHER+7]),
S_NORMAL (CHKN, 'N', 3, NULL , &States[S_FEATHER+0]),
#define S_FEATHERX (S_FEATHER+8)
S_NORMAL (CHKN, 'N', 6, NULL , NULL)
};
IMPLEMENT_ACTOR (AFeather, Heretic, -1, 121)
PROP_RadiusFixed (2)
PROP_HeightFixed (4)
PROP_Gravity (FRACUNIT/8)
PROP_Flags (MF_MISSILE|MF_DROPOFF)
PROP_Flags2 (MF2_NOTELEPORT|MF2_CANNOTPUSH|MF2_WINDTHRUST)
PROP_Flags3 (MF3_DONTSPLASH)
PROP_SpawnState (S_FEATHER)
PROP_DeathState (S_FEATHERX)
END_DEFAULTS
//----------------------------------------------------------------------------
//
// PROC A_ChicAttack
@ -338,12 +98,12 @@ void A_Feathers (AActor *actor)
}
for (i = 0; i < count; i++)
{
mo = Spawn<AFeather> (actor->x, actor->y, actor->z+20*FRACUNIT, NO_REPLACE);
mo = Spawn("Feather", actor->x, actor->y, actor->z+20*FRACUNIT, NO_REPLACE);
mo->target = actor;
mo->momx = pr_feathers.Random2() << 8;
mo->momy = pr_feathers.Random2() << 8;
mo->momz = FRACUNIT + (pr_feathers() << 9);
mo->SetState (&AFeather::States[S_FEATHER+(pr_feathers()&7)]);
mo->SetState (mo->SpawnState + (pr_feathers()&7));
}
}
@ -413,7 +173,7 @@ void A_BeakAttackPL1 (AActor *actor)
damage = 1 + (pr_beakatkpl1()&3);
angle = player->mo->angle;
slope = P_AimLineAttack (player->mo, angle, MELEERANGE, &linetarget);
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(ABeakPuff), true);
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true);
if (linetarget)
{
player->mo->angle = R_PointToAngle2 (player->mo->x,
@ -446,7 +206,7 @@ void A_BeakAttackPL2 (AActor *actor)
damage = pr_beakatkpl2.HitDice (4);
angle = player->mo->angle;
slope = P_AimLineAttack (player->mo, angle, MELEERANGE, &linetarget);
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, RUNTIME_CLASS(ABeakPuff), true);
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true);
if (linetarget)
{
player->mo->angle = R_PointToAngle2 (player->mo->x,

View file

@ -17,368 +17,6 @@ static FRandom pr_s2d ("Srcr2Decide");
static FRandom pr_s2a ("Srcr2Attack");
static FRandom pr_bluespark ("BlueSpark");
void A_Sor1Chase (AActor *);
void A_Sor1Pain (AActor *);
void A_Srcr1Attack (AActor *);
void A_SorZap (AActor *);
void A_SorcererRise (AActor *);
void A_SorRise (AActor *);
void A_SorSightSnd (AActor *);
void A_Srcr2Decide (AActor *);
void A_Srcr2Attack (AActor *);
void A_Sor2DthInit (AActor *);
void A_SorDSph (AActor *);
void A_Sor2DthLoop (AActor *);
void A_SorDExp (AActor *);
void A_SorDBon (AActor *);
void A_BlueSpark (AActor *);
void A_GenWizard (AActor *);
// Boss spot ----------------------------------------------------------------
class ABossSpot : public ASpecialSpot
{
DECLARE_STATELESS_ACTOR (ABossSpot, ASpecialSpot)
};
IMPLEMENT_STATELESS_ACTOR (ABossSpot, Heretic, 56, 141)
PROP_RenderFlags (RF_INVISIBLE)
END_DEFAULTS
// Sorcerer (D'Sparil on his serpent) ---------------------------------------
class ASorcerer1 : public AActor
{
DECLARE_ACTOR (ASorcerer1, AActor)
};
FState ASorcerer1::States[] =
{
#define S_SRCR1_LOOK 0
S_NORMAL (SRCR, 'A', 10, A_Look , &States[S_SRCR1_LOOK+1]),
S_NORMAL (SRCR, 'B', 10, A_Look , &States[S_SRCR1_LOOK+0]),
#define S_SRCR1_WALK (S_SRCR1_LOOK+2)
S_NORMAL (SRCR, 'A', 5, A_Sor1Chase , &States[S_SRCR1_WALK+1]),
S_NORMAL (SRCR, 'B', 5, A_Sor1Chase , &States[S_SRCR1_WALK+2]),
S_NORMAL (SRCR, 'C', 5, A_Sor1Chase , &States[S_SRCR1_WALK+3]),
S_NORMAL (SRCR, 'D', 5, A_Sor1Chase , &States[S_SRCR1_WALK+0]),
#define S_SRCR1_PAIN (S_SRCR1_WALK+4)
S_NORMAL (SRCR, 'Q', 6, A_Sor1Pain , &States[S_SRCR1_WALK+0]),
#define S_SRCR1_ATK (S_SRCR1_PAIN+1)
S_NORMAL (SRCR, 'Q', 7, A_FaceTarget , &States[S_SRCR1_ATK+1]),
S_NORMAL (SRCR, 'R', 6, A_FaceTarget , &States[S_SRCR1_ATK+2]),
S_NORMAL (SRCR, 'S', 10, A_Srcr1Attack , &States[S_SRCR1_WALK+0]),
S_NORMAL (SRCR, 'S', 10, A_FaceTarget , &States[S_SRCR1_ATK+4]),
S_NORMAL (SRCR, 'Q', 7, A_FaceTarget , &States[S_SRCR1_ATK+5]),
S_NORMAL (SRCR, 'R', 6, A_FaceTarget , &States[S_SRCR1_ATK+6]),
S_NORMAL (SRCR, 'S', 10, A_Srcr1Attack , &States[S_SRCR1_WALK+0]),
#define S_SRCR1_DIE (S_SRCR1_ATK+7)
S_NORMAL (SRCR, 'E', 7, NULL , &States[S_SRCR1_DIE+1]),
S_NORMAL (SRCR, 'F', 7, A_Scream , &States[S_SRCR1_DIE+2]),
S_NORMAL (SRCR, 'G', 7, NULL , &States[S_SRCR1_DIE+3]),
S_NORMAL (SRCR, 'H', 6, NULL , &States[S_SRCR1_DIE+4]),
S_NORMAL (SRCR, 'I', 6, NULL , &States[S_SRCR1_DIE+5]),
S_NORMAL (SRCR, 'J', 6, NULL , &States[S_SRCR1_DIE+6]),
S_NORMAL (SRCR, 'K', 6, NULL , &States[S_SRCR1_DIE+7]),
S_NORMAL (SRCR, 'L', 25, A_SorZap , &States[S_SRCR1_DIE+8]),
S_NORMAL (SRCR, 'M', 5, NULL , &States[S_SRCR1_DIE+9]),
S_NORMAL (SRCR, 'N', 5, NULL , &States[S_SRCR1_DIE+10]),
S_NORMAL (SRCR, 'O', 4, NULL , &States[S_SRCR1_DIE+11]),
S_NORMAL (SRCR, 'L', 20, A_SorZap , &States[S_SRCR1_DIE+12]),
S_NORMAL (SRCR, 'M', 5, NULL , &States[S_SRCR1_DIE+13]),
S_NORMAL (SRCR, 'N', 5, NULL , &States[S_SRCR1_DIE+14]),
S_NORMAL (SRCR, 'O', 4, NULL , &States[S_SRCR1_DIE+15]),
S_NORMAL (SRCR, 'L', 12, NULL , &States[S_SRCR1_DIE+16]),
S_NORMAL (SRCR, 'P', -1, A_SorcererRise , NULL)
};
IMPLEMENT_ACTOR (ASorcerer1, Heretic, 7, 142)
PROP_SpawnHealth (2000)
PROP_RadiusFixed (28)
PROP_HeightFixed (100)
PROP_Mass (800)
PROP_SpeedFixed (16)
PROP_PainChance (56)
PROP_Flags (MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL)
PROP_Flags2 (MF2_MCROSS|MF2_FLOORCLIP|MF2_PASSMOBJ|MF2_PUSHWALL|MF2_BOSS)
PROP_Flags3 (MF3_DONTMORPH|MF3_NORADIUSDMG|MF3_NOTARGET)
PROP_Flags4 (MF4_NOICEDEATH)
PROP_SpawnState (S_SRCR1_LOOK)
PROP_SeeState (S_SRCR1_WALK)
PROP_PainState (S_SRCR1_PAIN)
PROP_MissileState (S_SRCR1_ATK)
PROP_DeathState (S_SRCR1_DIE)
PROP_SeeSound ("dsparilserpent/sight")
PROP_AttackSound ("dsparilserpent/attack")
PROP_PainSound ("dsparilserpent/pain")
PROP_DeathSound ("dsparilserpent/death")
PROP_ActiveSound ("dsparilserpent/active")
PROP_Obituary("$OB_DSPARIL1")
PROP_HitObituary("$OB_DSPARIL1HIT")
END_DEFAULTS
// Sorcerer FX 1 ------------------------------------------------------------
class ASorcererFX1 : public AActor
{
DECLARE_ACTOR (ASorcererFX1, AActor)
};
FState ASorcererFX1::States[] =
{
#define S_SRCRFX1 0
S_BRIGHT (FX14, 'A', 6, NULL , &States[S_SRCRFX1+1]),
S_BRIGHT (FX14, 'B', 6, NULL , &States[S_SRCRFX1+2]),
S_BRIGHT (FX14, 'C', 6, NULL , &States[S_SRCRFX1+0]),
#define S_SRCRFXI1 (S_SRCRFX1+3)
S_BRIGHT (FX14, 'D', 5, NULL , &States[S_SRCRFXI1+1]),
S_BRIGHT (FX14, 'E', 5, NULL , &States[S_SRCRFXI1+2]),
S_BRIGHT (FX14, 'F', 5, NULL , &States[S_SRCRFXI1+3]),
S_BRIGHT (FX14, 'G', 5, NULL , &States[S_SRCRFXI1+4]),
S_BRIGHT (FX14, 'H', 5, NULL , NULL)
};
IMPLEMENT_ACTOR (ASorcererFX1, Heretic, -1, 144)
PROP_RadiusFixed (10)
PROP_HeightFixed (10)
PROP_SpeedFixed (20)
PROP_Damage (10)
PROP_DamageType (NAME_Fire)
PROP_Flags (MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY)
PROP_Flags2 (MF2_NOTELEPORT)
PROP_RenderStyle (STYLE_Add)
PROP_SpawnState (S_SRCRFX1)
PROP_DeathState (S_SRCRFXI1)
END_DEFAULTS
AT_SPEED_SET (SorcererFX1, speed)
{
SimpleSpeedSetter (ASorcererFX1, 20*FRACUNIT, 28*FRACUNIT, speed);
}
// Sorcerer 2 (D'Sparil without his serpent) --------------------------------
FState ASorcerer2::States[] =
{
#define S_SOR2_LOOK 0
S_NORMAL (SOR2, 'M', 10, A_Look , &States[S_SOR2_LOOK+1]),
S_NORMAL (SOR2, 'N', 10, A_Look , &States[S_SOR2_LOOK+0]),
#define S_SOR2_WALK (S_SOR2_LOOK+2)
S_NORMAL (SOR2, 'M', 4, A_Chase , &States[S_SOR2_WALK+1]),
S_NORMAL (SOR2, 'N', 4, A_Chase , &States[S_SOR2_WALK+2]),
S_NORMAL (SOR2, 'O', 4, A_Chase , &States[S_SOR2_WALK+3]),
S_NORMAL (SOR2, 'P', 4, A_Chase , &States[S_SOR2_WALK+0]),
#define S_SOR2_RISE (S_SOR2_WALK+4)
S_NORMAL (SOR2, 'A', 4, NULL , &States[S_SOR2_RISE+1]),
S_NORMAL (SOR2, 'B', 4, NULL , &States[S_SOR2_RISE+2]),
S_NORMAL (SOR2, 'C', 4, A_SorRise , &States[S_SOR2_RISE+3]),
S_NORMAL (SOR2, 'D', 4, NULL , &States[S_SOR2_RISE+4]),
S_NORMAL (SOR2, 'E', 4, NULL , &States[S_SOR2_RISE+5]),
S_NORMAL (SOR2, 'F', 4, NULL , &States[S_SOR2_RISE+6]),
S_NORMAL (SOR2, 'G', 12, A_SorSightSnd , &States[S_SOR2_WALK+0]),
#define S_SOR2_PAIN (S_SOR2_RISE+7)
S_NORMAL (SOR2, 'Q', 3, NULL , &States[S_SOR2_PAIN+1]),
S_NORMAL (SOR2, 'Q', 6, A_Pain , &States[S_SOR2_WALK+0]),
#define S_SOR2_ATK (S_SOR2_PAIN+2)
S_NORMAL (SOR2, 'R', 9, A_Srcr2Decide , &States[S_SOR2_ATK+1]),
S_NORMAL (SOR2, 'S', 9, A_FaceTarget , &States[S_SOR2_ATK+2]),
S_NORMAL (SOR2, 'T', 20, A_Srcr2Attack , &States[S_SOR2_WALK+0]),
#define S_SOR2_TELE (S_SOR2_ATK+3)
S_NORMAL (SOR2, 'L', 6, NULL , &States[S_SOR2_TELE+1]),
S_NORMAL (SOR2, 'K', 6, NULL , &States[S_SOR2_TELE+2]),
S_NORMAL (SOR2, 'J', 6, NULL , &States[S_SOR2_TELE+3]),
S_NORMAL (SOR2, 'I', 6, NULL , &States[S_SOR2_TELE+4]),
S_NORMAL (SOR2, 'H', 6, NULL , &States[S_SOR2_TELE+5]),
S_NORMAL (SOR2, 'G', 6, NULL , &States[S_SOR2_WALK+0]),
#define S_SOR2_DIE (S_SOR2_TELE+6)
S_NORMAL (SDTH, 'A', 8, A_Sor2DthInit , &States[S_SOR2_DIE+1]),
S_NORMAL (SDTH, 'B', 8, NULL , &States[S_SOR2_DIE+2]),
S_NORMAL (SDTH, 'C', 8, A_SorDSph , &States[S_SOR2_DIE+3]),
S_NORMAL (SDTH, 'D', 7, NULL , &States[S_SOR2_DIE+4]),
S_NORMAL (SDTH, 'E', 7, NULL , &States[S_SOR2_DIE+5]),
S_NORMAL (SDTH, 'F', 7, A_Sor2DthLoop , &States[S_SOR2_DIE+6]),
S_NORMAL (SDTH, 'G', 6, A_SorDExp , &States[S_SOR2_DIE+7]),
S_NORMAL (SDTH, 'H', 6, NULL , &States[S_SOR2_DIE+8]),
S_NORMAL (SDTH, 'I', 18, NULL , &States[S_SOR2_DIE+9]),
S_NORMAL (SDTH, 'J', 6, A_NoBlocking , &States[S_SOR2_DIE+10]),
S_NORMAL (SDTH, 'K', 6, A_SorDBon , &States[S_SOR2_DIE+11]),
S_NORMAL (SDTH, 'L', 6, NULL , &States[S_SOR2_DIE+12]),
S_NORMAL (SDTH, 'M', 6, NULL , &States[S_SOR2_DIE+13]),
S_NORMAL (SDTH, 'N', 6, NULL , &States[S_SOR2_DIE+14]),
S_NORMAL (SDTH, 'O', -1, A_BossDeath , NULL)
};
IMPLEMENT_ACTOR (ASorcerer2, Heretic, -1, 143)
PROP_SpawnHealth (3500)
PROP_RadiusFixed (16)
PROP_HeightFixed (70)
PROP_Mass (300)
PROP_SpeedFixed (14)
PROP_PainChance (32)
PROP_Flags (MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_DROPOFF)
PROP_Flags2 (MF2_MCROSS|MF2_FLOORCLIP|MF2_PASSMOBJ|MF2_PUSHWALL|MF2_BOSS)
PROP_Flags3 (MF3_DONTMORPH|MF3_FULLVOLACTIVE|MF3_NORADIUSDMG|MF3_NOTARGET)
PROP_Flags4 (MF4_NOICEDEATH)
PROP_SpawnState (S_SOR2_LOOK)
PROP_SeeState (S_SOR2_WALK)
PROP_PainState (S_SOR2_PAIN)
PROP_MissileState (S_SOR2_ATK)
PROP_DeathState (S_SOR2_DIE)
PROP_SeeSound ("dsparil/sight")
PROP_AttackSound ("dsparil/attack")
PROP_PainSound ("dsparil/pain")
PROP_ActiveSound ("dsparil/active")
PROP_Obituary("$OB_DSPARIL2")
PROP_HitObituary("$OB_DSPARIL2HIT")
END_DEFAULTS
// Sorcerer 2 FX 1 ----------------------------------------------------------
class ASorcerer2FX1 : public AActor
{
DECLARE_ACTOR (ASorcerer2FX1, AActor)
public:
void GetExplodeParms (int &damage, int &distance, bool &hurtSource);
};
FState ASorcerer2FX1::States[] =
{
#define S_SOR2FX1 0
S_BRIGHT (FX16, 'A', 3, A_BlueSpark , &States[S_SOR2FX1+1]),
S_BRIGHT (FX16, 'B', 3, A_BlueSpark , &States[S_SOR2FX1+2]),
S_BRIGHT (FX16, 'C', 3, A_BlueSpark , &States[S_SOR2FX1+0]),
#define S_SOR2FXI1 (S_SOR2FX1+3)
S_BRIGHT (FX16, 'G', 5, A_Explode , &States[S_SOR2FXI1+1]),
S_BRIGHT (FX16, 'H', 5, NULL , &States[S_SOR2FXI1+2]),
S_BRIGHT (FX16, 'I', 5, NULL , &States[S_SOR2FXI1+3]),
S_BRIGHT (FX16, 'J', 5, NULL , &States[S_SOR2FXI1+4]),
S_BRIGHT (FX16, 'K', 5, NULL , &States[S_SOR2FXI1+5]),
S_BRIGHT (FX16, 'L', 5, NULL , NULL)
};
IMPLEMENT_ACTOR (ASorcerer2FX1, Heretic, -1, 145)
PROP_RadiusFixed (10)
PROP_HeightFixed (6)
PROP_SpeedFixed (20)
PROP_Damage (1)
PROP_Flags (MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY)
PROP_Flags2 (MF2_NOTELEPORT)
PROP_RenderStyle (STYLE_Add)
PROP_SpawnState (S_SOR2FX1)
PROP_DeathState (S_SOR2FXI1)
END_DEFAULTS
AT_SPEED_SET (Sorcerer2FX1, speed)
{
SimpleSpeedSetter (ASorcerer2FX1, 20*FRACUNIT, 28*FRACUNIT, speed);
}
void ASorcerer2FX1::GetExplodeParms (int &damage, int &distance, bool &hurtSource)
{
damage = 80 + (pr_s2fx1() & 31);
}
// Sorcerer 2 FX Spark ------------------------------------------------------
class ASorcerer2FXSpark : public AActor
{
DECLARE_ACTOR (ASorcerer2FXSpark, AActor)
};
FState ASorcerer2FXSpark::States[] =
{
#define S_SOR2FXSPARK 0
S_BRIGHT (FX16, 'D', 12, NULL , &States[S_SOR2FXSPARK+1]),
S_BRIGHT (FX16, 'E', 12, NULL , &States[S_SOR2FXSPARK+2]),
S_BRIGHT (FX16, 'F', 12, NULL , NULL)
};
IMPLEMENT_ACTOR (ASorcerer2FXSpark, Heretic, -1, 0)
PROP_RadiusFixed (20)
PROP_HeightFixed (16)
PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY)
PROP_Flags2 (MF2_NOTELEPORT|MF2_CANNOTPUSH)
PROP_RenderStyle (STYLE_Add)
PROP_SpawnState (S_SOR2FXSPARK)
END_DEFAULTS
// Sorcerer 2 FX 2 ----------------------------------------------------------
class ASorcerer2FX2 : public AActor
{
DECLARE_ACTOR (ASorcerer2FX2, AActor)
};
FState ASorcerer2FX2::States[] =
{
#define S_SOR2FX2 0
S_BRIGHT (FX11, 'A', 35, NULL , &States[S_SOR2FX2+1]),
S_BRIGHT (FX11, 'A', 5, A_GenWizard , &States[S_SOR2FX2+2]),
S_BRIGHT (FX11, 'B', 5, NULL , &States[S_SOR2FX2+1]),
#define S_SOR2FXI2 (S_SOR2FX2+3)
S_BRIGHT (FX11, 'C', 5, NULL , &States[S_SOR2FXI2+1]),
S_BRIGHT (FX11, 'D', 5, NULL , &States[S_SOR2FXI2+2]),
S_BRIGHT (FX11, 'E', 5, NULL , &States[S_SOR2FXI2+3]),
S_BRIGHT (FX11, 'F', 5, NULL , &States[S_SOR2FXI2+4]),
S_BRIGHT (FX11, 'G', 5, NULL , NULL)
};
IMPLEMENT_ACTOR (ASorcerer2FX2, Heretic, -1, 146)
PROP_RadiusFixed (10)
PROP_HeightFixed (6)
PROP_SpeedFixed (6)
PROP_Damage (10)
PROP_Flags (MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY)
PROP_Flags2 (MF2_NOTELEPORT)
PROP_RenderStyle (STYLE_Add)
PROP_SpawnState (S_SOR2FX2)
PROP_DeathState (S_SOR2FXI2)
END_DEFAULTS
// Sorcerer 2 Telefade ------------------------------------------------------
class ASorcerer2Telefade : public AActor
{
DECLARE_ACTOR (ASorcerer2Telefade, AActor)
};
FState ASorcerer2Telefade::States[] =
{
#define S_SOR2TELEFADE 0
S_NORMAL (SOR2, 'G', 8, NULL , &States[S_SOR2TELEFADE+1]),
S_NORMAL (SOR2, 'H', 6, NULL , &States[S_SOR2TELEFADE+2]),
S_NORMAL (SOR2, 'I', 6, NULL , &States[S_SOR2TELEFADE+3]),
S_NORMAL (SOR2, 'J', 6, NULL , &States[S_SOR2TELEFADE+4]),
S_NORMAL (SOR2, 'K', 6, NULL , &States[S_SOR2TELEFADE+5]),
S_NORMAL (SOR2, 'L', 6, NULL , NULL)
};
IMPLEMENT_ACTOR (ASorcerer2Telefade, Heretic, -1, 0)
PROP_Flags (MF_NOBLOCKMAP)
PROP_SpawnState (S_SOR2TELEFADE)
END_DEFAULTS
//----------------------------------------------------------------------------
//
// PROC A_Sor1Pain
@ -433,19 +71,21 @@ void A_Srcr1Attack (AActor *actor)
P_TraceBleed (damage, actor->target, actor);
return;
}
const PClass *fx = PClass::FindClass("SorcererFX1");
if (actor->health > (actor->GetDefault()->health/3)*2)
{ // Spit one fireball
P_SpawnMissileZ (actor, actor->z + 48*FRACUNIT, actor->target, RUNTIME_CLASS(ASorcererFX1));
P_SpawnMissileZ (actor, actor->z + 48*FRACUNIT, actor->target, fx );
}
else
{ // Spit three fireballs
mo = P_SpawnMissileZ (actor, actor->z + 48*FRACUNIT, actor->target, RUNTIME_CLASS(ASorcererFX1));
mo = P_SpawnMissileZ (actor, actor->z + 48*FRACUNIT, actor->target, fx);
if (mo != NULL)
{
momz = mo->momz;
angle = mo->angle;
P_SpawnMissileAngleZ (actor, actor->z + 48*FRACUNIT, RUNTIME_CLASS(ASorcererFX1), angle-ANGLE_1*3, momz);
P_SpawnMissileAngleZ (actor, actor->z + 48*FRACUNIT, RUNTIME_CLASS(ASorcererFX1), angle+ANGLE_1*3, momz);
P_SpawnMissileAngleZ (actor, actor->z + 48*FRACUNIT, fx, angle-ANGLE_1*3, momz);
P_SpawnMissileAngleZ (actor, actor->z + 48*FRACUNIT, fx, angle+ANGLE_1*3, momz);
}
if (actor->health < actor->GetDefault()->health/3)
{ // Maybe attack again
@ -456,7 +96,7 @@ void A_Srcr1Attack (AActor *actor)
else
{ // Set state to attack again
actor->special1 = 1;
actor->SetState (&ASorcerer1::States[S_SRCR1_ATK+3]);
actor->SetState (actor->FindState("Missile2"));
}
}
}
@ -473,8 +113,8 @@ void A_SorcererRise (AActor *actor)
AActor *mo;
actor->flags &= ~MF_SOLID;
mo = Spawn<ASorcerer2> (actor->x, actor->y, actor->z, ALLOW_REPLACE);
mo->SetState (&ASorcerer2::States[S_SOR2_RISE]);
mo = Spawn("Sorcerer2", actor->x, actor->y, actor->z, ALLOW_REPLACE);
mo->SetState (mo->FindState("Rise"));
mo->angle = actor->angle;
mo->CopyFriendliness (actor, true);
}
@ -496,7 +136,7 @@ void P_DSparilTeleport (AActor *actor)
DSpotState *state = DSpotState::GetSpotState();
if (state == NULL) return;
spot = state->GetSpotWithMinDistance(RUNTIME_CLASS(ABossSpot), actor->x, actor->y, 128*FRACUNIT);
spot = state->GetSpotWithMinDistance(PClass::FindClass("BossSpot"), actor->x, actor->y, 128*FRACUNIT);
if (spot == NULL) return;
prevX = actor->x;
@ -504,9 +144,9 @@ void P_DSparilTeleport (AActor *actor)
prevZ = actor->z;
if (P_TeleportMove (actor, spot->x, spot->y, spot->z, false))
{
mo = Spawn<ASorcerer2Telefade> (prevX, prevY, prevZ, ALLOW_REPLACE);
mo = Spawn("Sorcerer2Telefade", prevX, prevY, prevZ, ALLOW_REPLACE);
S_Sound (mo, CHAN_BODY, "misc/teleport", 1, ATTN_NORM);
actor->SetState (&ASorcerer2::States[S_SOR2_TELE]);
actor->SetState (actor->FindState("Teleport"));
S_Sound (actor, CHAN_BODY, "misc/teleport", 1, ATTN_NORM);
actor->z = actor->floorz;
actor->angle = spot->angle;
@ -565,14 +205,17 @@ void A_Srcr2Attack (AActor *actor)
chance = actor->health < actor->GetDefault()->health/2 ? 96 : 48;
if (pr_s2a() < chance)
{ // Wizard spawners
P_SpawnMissileAngle (actor, RUNTIME_CLASS(ASorcerer2FX2),
actor->angle-ANG45, FRACUNIT/2);
P_SpawnMissileAngle (actor, RUNTIME_CLASS(ASorcerer2FX2),
actor->angle+ANG45, FRACUNIT/2);
const PClass *fx = PClass::FindClass("Sorcerer2FX2");
if (fx)
{
P_SpawnMissileAngle (actor, fx, actor->angle-ANG45, FRACUNIT/2);
P_SpawnMissileAngle (actor, fx, actor->angle+ANG45, FRACUNIT/2);
}
}
else
{ // Blue bolt
P_SpawnMissile (actor, actor->target, RUNTIME_CLASS(ASorcerer2FX1));
P_SpawnMissile (actor, actor->target, PClass::FindClass("Sorcerer2FX1"));
}
}
@ -589,7 +232,7 @@ void A_BlueSpark (AActor *actor)
for (i = 0; i < 2; i++)
{
mo = Spawn<ASorcerer2FXSpark> (actor->x, actor->y, actor->z, ALLOW_REPLACE);
mo = Spawn("Sorcerer2FXSpark", actor->x, actor->y, actor->z, ALLOW_REPLACE);
mo->momx = pr_bluespark.Random2() << 9;
mo->momy = pr_bluespark.Random2() << 9;
mo->momz = FRACUNIT + (pr_bluespark()<<8);
@ -606,9 +249,10 @@ void A_GenWizard (AActor *actor)
{
AActor *mo;
mo = Spawn<AWizard> (actor->x, actor->y, actor->z - GetDefault<AWizard>()->height/2, ALLOW_REPLACE);
mo = Spawn("Wizard", actor->x, actor->y, actor->z, ALLOW_REPLACE);
if (mo != NULL)
{
mo->z -= mo->GetDefault()->height/2;
if (!P_TestMobjLocation (mo))
{ // Didn't fit
mo->Destroy ();
@ -650,19 +294,7 @@ void A_Sor2DthLoop (AActor *actor)
{
if (--actor->special1)
{ // Need to loop
actor->SetState (&ASorcerer2::States[S_SOR2_DIE+3]);
actor->SetState (actor->FindState("DeathLoop"));
}
}
//----------------------------------------------------------------------------
//
// D'Sparil Sound Routines
//
//----------------------------------------------------------------------------
void A_SorZap (AActor *actor) {S_Sound (actor, CHAN_BODY, "dsparil/zap", 1, ATTN_NONE);}
void A_SorRise (AActor *actor) {S_Sound (actor, CHAN_BODY, "dsparil/rise", 1, ATTN_NONE);}
void A_SorDSph (AActor *actor) {S_Sound (actor, CHAN_BODY, "dsparil/scream", 1, ATTN_NONE);}
void A_SorDExp (AActor *actor) {S_Sound (actor, CHAN_BODY, "dsparil/explode", 1, ATTN_NONE);}
void A_SorDBon (AActor *actor) {S_Sound (actor, CHAN_BODY, "dsparil/bones", 1, ATTN_NONE);}
void A_SorSightSnd (AActor *actor) {S_Sound (actor, CHAN_BODY, "dsparil/sight", 1, ATTN_NONE);}

View file

@ -10,25 +10,13 @@
class AArtiTomeOfPower : public APowerupGiver
{
DECLARE_ACTOR (AArtiTomeOfPower, APowerupGiver)
DECLARE_CLASS (AArtiTomeOfPower, APowerupGiver)
public:
bool Use (bool pickup);
};
FState AArtiTomeOfPower::States[] =
{
S_NORMAL (PWBK, 'A', 350, NULL, &States[0])
};
IMPLEMENT_ACTOR (AArtiTomeOfPower, Heretic, 86, 134)
PROP_Flags (MF_SPECIAL|MF_COUNTITEM)
PROP_Flags2 (MF2_FLOATBOB)
PROP_SpawnState (0)
PROP_Inventory_PickupFlash (1)
PROP_Inventory_Icon ("ARTIPWBK")
PROP_PowerupGiver_Powerup ("PowerWeaponLevel2")
PROP_Inventory_PickupMessage("$TXT_ARTITOMEOFPOWER")
END_DEFAULTS
IMPLEMENT_CLASS (AArtiTomeOfPower)
bool AArtiTomeOfPower::Use (bool pickup)
{
@ -55,70 +43,28 @@ bool AArtiTomeOfPower::Use (bool pickup)
// Time bomb ----------------------------------------------------------------
class AActivatedTimeBomb : public AActor
void A_TimeBomb(AActor *self)
{
DECLARE_ACTOR (AActivatedTimeBomb, AActor)
public:
void PreExplode ()
{
z += 32*FRACUNIT;
alpha = OPAQUE;
}
};
FState AActivatedTimeBomb::States[] =
{
S_NORMAL (FBMB, 'A', 10, NULL , &States[1]),
S_NORMAL (FBMB, 'B', 10, NULL , &States[2]),
S_NORMAL (FBMB, 'C', 10, NULL , &States[3]),
S_NORMAL (FBMB, 'D', 10, NULL , &States[4]),
S_NORMAL (FBMB, 'E', 6, A_Scream , &States[5]),
S_BRIGHT (XPL1, 'A', 4, A_Explode, &States[6]),
S_BRIGHT (XPL1, 'B', 4, NULL , &States[7]),
S_BRIGHT (XPL1, 'C', 4, NULL , &States[8]),
S_BRIGHT (XPL1, 'D', 4, NULL , &States[9]),
S_BRIGHT (XPL1, 'E', 4, NULL , &States[10]),
S_BRIGHT (XPL1, 'F', 4, NULL , NULL)
};
IMPLEMENT_ACTOR (AActivatedTimeBomb, Heretic, -1, 0)
PROP_Flags (MF_NOGRAVITY)
PROP_RenderStyle (STYLE_Translucent)
PROP_Alpha (HR_SHADOW)
PROP_SpawnState (0)
PROP_DeathSound ("misc/timebomb")
END_DEFAULTS
self->z += 32*FRACUNIT;
self->RenderStyle = STYLE_Add;
self->alpha = FRACUNIT;
A_Explode(self);
}
class AArtiTimeBomb : public AInventory
{
DECLARE_ACTOR (AArtiTimeBomb, AInventory)
DECLARE_CLASS (AArtiTimeBomb, AInventory)
public:
bool Use (bool pickup);
};
FState AArtiTimeBomb::States[] =
{
S_NORMAL (FBMB, 'E', 350, NULL, &States[0]),
};
IMPLEMENT_ACTOR (AArtiTimeBomb, Heretic, 34, 72)
PROP_Flags (MF_SPECIAL|MF_COUNTITEM)
PROP_Flags2 (MF2_FLOATBOB)
PROP_SpawnState (0)
PROP_Inventory_DefMaxAmount
PROP_Inventory_PickupFlash (1)
PROP_Inventory_FlagsSet (IF_INVBAR|IF_FANCYPICKUPSOUND)
PROP_Inventory_Icon ("ARTIFBMB")
PROP_Inventory_PickupSound ("misc/p_pkup")
PROP_Inventory_PickupMessage("$TXT_ARTIFIREBOMB")
END_DEFAULTS
IMPLEMENT_CLASS (AArtiTimeBomb)
bool AArtiTimeBomb::Use (bool pickup)
{
angle_t angle = Owner->angle >> ANGLETOFINESHIFT;
AActor *mo = Spawn<AActivatedTimeBomb> (
AActor *mo = Spawn("ActivatedTimeBomb",
Owner->x + 24*finecosine[angle],
Owner->y + 24*finesine[angle],
Owner->z - Owner->floorclip, ALLOW_REPLACE);

View file

@ -21,18 +21,6 @@ class APhoenixPuff : public AActor
DECLARE_ACTOR (APhoenixPuff, AActor)
};
class ASorcerer2 : public AActor
{
DECLARE_ACTOR (ASorcerer2, AActor)
};
class AWizard : public AActor
{
DECLARE_ACTOR (AWizard, AActor)
public:
void NoBlockingSet ();
};
void P_DSparilTeleport (AActor *actor);
class AStaffPuff : public AActor

View file

@ -8,218 +8,6 @@
#include "gstrings.h"
static FRandom pr_imp ("ImpExplode");
static FRandom pr_impmeatk ("ImpMeAttack");
static FRandom pr_impmsatk ("ImpMsAttack");
static FRandom pr_impmsatk2 ("ImpMsAttack2");
void A_ImpExplode (AActor *);
void A_ImpMeAttack (AActor *);
void A_ImpMsAttack (AActor *);
void A_ImpMsAttack2 (AActor *);
void A_ImpDeath (AActor *);
void A_ImpXDeath1 (AActor *);
void A_ImpXDeath2 (AActor *);
// Heretic imp (as opposed to the Doom variety) -----------------------------
class AHereticImp : public AActor
{
DECLARE_ACTOR (AHereticImp, AActor)
};
FState AHereticImp::States[] =
{
#define S_IMP_LOOK 0
S_NORMAL (IMPX, 'A', 10, A_Look , &States[S_IMP_LOOK+1]),
S_NORMAL (IMPX, 'B', 10, A_Look , &States[S_IMP_LOOK+2]),
S_NORMAL (IMPX, 'C', 10, A_Look , &States[S_IMP_LOOK+3]),
S_NORMAL (IMPX, 'B', 10, A_Look , &States[S_IMP_LOOK+0]),
#define S_IMP_FLY (S_IMP_LOOK+4)
S_NORMAL (IMPX, 'A', 3, A_Chase , &States[S_IMP_FLY+1]),
S_NORMAL (IMPX, 'A', 3, A_Chase , &States[S_IMP_FLY+2]),
S_NORMAL (IMPX, 'B', 3, A_Chase , &States[S_IMP_FLY+3]),
S_NORMAL (IMPX, 'B', 3, A_Chase , &States[S_IMP_FLY+4]),
S_NORMAL (IMPX, 'C', 3, A_Chase , &States[S_IMP_FLY+5]),
S_NORMAL (IMPX, 'C', 3, A_Chase , &States[S_IMP_FLY+6]),
S_NORMAL (IMPX, 'B', 3, A_Chase , &States[S_IMP_FLY+7]),
S_NORMAL (IMPX, 'B', 3, A_Chase , &States[S_IMP_FLY+0]),
#define S_IMP_MEATK (S_IMP_FLY+8)
S_NORMAL (IMPX, 'D', 6, A_FaceTarget , &States[S_IMP_MEATK+1]),
S_NORMAL (IMPX, 'E', 6, A_FaceTarget , &States[S_IMP_MEATK+2]),
S_NORMAL (IMPX, 'F', 6, A_ImpMeAttack , &States[S_IMP_FLY+0]),
#define S_IMP_MSATK1 (S_IMP_MEATK+3)
S_NORMAL (IMPX, 'A', 10, A_FaceTarget , &States[S_IMP_MSATK1+1]),
S_NORMAL (IMPX, 'B', 6, A_ImpMsAttack , &States[S_IMP_MSATK1+2]),
S_NORMAL (IMPX, 'C', 6, NULL , &States[S_IMP_MSATK1+3]),
S_NORMAL (IMPX, 'B', 6, NULL , &States[S_IMP_MSATK1+4]),
S_NORMAL (IMPX, 'A', 6, NULL , &States[S_IMP_MSATK1+5]),
S_NORMAL (IMPX, 'B', 6, NULL , &States[S_IMP_MSATK1+2]),
#define S_IMP_PAIN (S_IMP_MSATK1+6)
S_NORMAL (IMPX, 'G', 3, NULL , &States[S_IMP_PAIN+1]),
S_NORMAL (IMPX, 'G', 3, A_Pain , &States[S_IMP_FLY+0]),
#define S_IMP_DIE (S_IMP_PAIN+2)
S_NORMAL (IMPX, 'G', 4, A_ImpDeath , &States[S_IMP_DIE+1]),
S_NORMAL (IMPX, 'H', 5, NULL , &States[S_IMP_DIE+1]),
#define S_IMP_XDIE (S_IMP_DIE+2)
S_NORMAL (IMPX, 'S', 5, A_ImpXDeath1 , &States[S_IMP_XDIE+1]),
S_NORMAL (IMPX, 'T', 5, NULL , &States[S_IMP_XDIE+2]),
S_NORMAL (IMPX, 'U', 5, NULL , &States[S_IMP_XDIE+3]),
S_NORMAL (IMPX, 'V', 5, A_ImpXDeath2 , &States[S_IMP_XDIE+4]),
S_NORMAL (IMPX, 'W', 5, NULL , &States[S_IMP_XDIE+4]),
#define S_IMP_CRASH (S_IMP_XDIE+5)
S_NORMAL (IMPX, 'I', 7, A_ImpExplode , &States[S_IMP_CRASH+1]),
S_NORMAL (IMPX, 'J', 7, A_Scream , &States[S_IMP_CRASH+2]),
S_NORMAL (IMPX, 'K', 7, NULL , &States[S_IMP_CRASH+3]),
S_NORMAL (IMPX, 'L', -1, NULL , NULL),
#define S_IMP_XCRASH (S_IMP_CRASH+4)
S_NORMAL (IMPX, 'X', 7, NULL , &States[S_IMP_XCRASH+1]),
S_NORMAL (IMPX, 'Y', 7, NULL , &States[S_IMP_XCRASH+2]),
S_NORMAL (IMPX, 'Z', -1, NULL , NULL)
};
IMPLEMENT_ACTOR (AHereticImp, Heretic, 66, 5)
PROP_SpawnHealth (40)
PROP_RadiusFixed (16)
PROP_HeightFixed (36)
PROP_Mass (50)
PROP_SpeedFixed (10)
PROP_PainChance (200)
PROP_Flags (MF_SOLID|MF_SHOOTABLE|MF_FLOAT|MF_NOGRAVITY|MF_COUNTKILL)
PROP_Flags2 (MF2_MCROSS|MF2_SPAWNFLOAT|MF2_PASSMOBJ|MF2_PUSHWALL)
PROP_Flags3 (MF3_DONTOVERLAP)
PROP_Flags4 (MF4_MISSILEMORE)
PROP_SpawnState (S_IMP_LOOK)
PROP_SeeState (S_IMP_FLY)
PROP_PainState (S_IMP_PAIN)
PROP_MeleeState (S_IMP_MEATK)
PROP_MissileState (S_IMP_MSATK1)
PROP_CrashState (S_IMP_CRASH)
PROP_DeathState (S_IMP_DIE)
PROP_XDeathState (S_IMP_XDIE)
PROP_SeeSound ("himp/sight")
PROP_AttackSound ("himp/attack")
PROP_PainSound ("himp/pain")
PROP_DeathSound ("himp/death")
PROP_ActiveSound ("himp/active")
PROP_Obituary("$OB_HERETICIMP")
PROP_HitObituary("$OB_HERETICIMPHIT")
END_DEFAULTS
// Heretic imp leader -------------------------------------------------------
class AHereticImpLeader : public AHereticImp
{
DECLARE_ACTOR (AHereticImpLeader, AHereticImp)
};
FState AHereticImpLeader::States[] =
{
#define S_IMP_MSATK2 0
S_NORMAL (IMPX, 'D', 6, A_FaceTarget , &States[S_IMP_MSATK2+1]),
S_NORMAL (IMPX, 'E', 6, A_FaceTarget , &States[S_IMP_MSATK2+2]),
S_NORMAL (IMPX, 'F', 6, A_ImpMsAttack2 , &AHereticImp::States[S_IMP_FLY]),
};
IMPLEMENT_ACTOR (AHereticImpLeader, Heretic, 5, 7)
PROP_SpawnHealth (80)
PROP_MeleeState (PROP_CLEAR_STATE)
PROP_MissileState (S_IMP_MSATK2)
PROP_Flags4Clear(MF4_MISSILEMORE) // The imp leader does have a 'normal' missile range!
PROP_AttackSound ("himp/leaderattack")
END_DEFAULTS
// Heretic imp chunk 1 ------------------------------------------------------
class AHereticImpChunk1 : public AActor
{
DECLARE_ACTOR (AHereticImpChunk1, AActor)
};
FState AHereticImpChunk1::States[] =
{
S_NORMAL (IMPX, 'M', 5, NULL , &States[1]),
S_NORMAL (IMPX, 'N', 700, NULL , &States[2]),
S_NORMAL (IMPX, 'O', 700, NULL , NULL)
};
IMPLEMENT_ACTOR (AHereticImpChunk1, Heretic, -1, 0)
PROP_Mass (5)
PROP_Radius (4)
PROP_SpawnState (0)
END_DEFAULTS
// Heretic imp chunk 2 ------------------------------------------------------
class AHereticImpChunk2 : public AActor
{
DECLARE_ACTOR (AHereticImpChunk2, AActor)
};
FState AHereticImpChunk2::States[] =
{
S_NORMAL (IMPX, 'P', 5, NULL , &States[1]),
S_NORMAL (IMPX, 'Q', 700, NULL , &States[2]),
S_NORMAL (IMPX, 'R', 700, NULL , NULL)
};
IMPLEMENT_ACTOR (AHereticImpChunk2, Heretic, -1, 0)
PROP_Mass (5)
PROP_Radius (4)
PROP_SpawnState (0)
END_DEFAULTS
// Heretic imp ball ---------------------------------------------------------
class AHereticImpBall : public AActor
{
DECLARE_ACTOR (AHereticImpBall, AActor)
};
FState AHereticImpBall::States[] =
{
#define S_IMPFX 0
S_BRIGHT (FX10, 'A', 6, NULL , &States[S_IMPFX+1]),
S_BRIGHT (FX10, 'B', 6, NULL , &States[S_IMPFX+2]),
S_BRIGHT (FX10, 'C', 6, NULL , &States[S_IMPFX+0]),
#define S_IMPFXI (S_IMPFX+3)
S_BRIGHT (FX10, 'D', 5, NULL , &States[S_IMPFXI+1]),
S_BRIGHT (FX10, 'E', 5, NULL , &States[S_IMPFXI+2]),
S_BRIGHT (FX10, 'F', 5, NULL , &States[S_IMPFXI+3]),
S_BRIGHT (FX10, 'G', 5, NULL , NULL)
};
IMPLEMENT_ACTOR (AHereticImpBall, Heretic, -1, 10)
PROP_RadiusFixed (8)
PROP_HeightFixed (8)
PROP_SpeedFixed (10)
PROP_Damage (1)
PROP_Flags (MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY)
PROP_Flags2 (MF2_WINDTHRUST|MF2_NOTELEPORT)
PROP_RenderStyle (STYLE_Add)
PROP_SpawnState (S_IMPFX)
PROP_DeathState (S_IMPFXI)
END_DEFAULTS
AT_SPEED_SET (HereticImpBall, speed)
{
SimpleSpeedSetter (AHereticImpBall, 10*FRACUNIT, 20*FRACUNIT, speed);
}
//----------------------------------------------------------------------------
//
@ -233,100 +21,21 @@ void A_ImpExplode (AActor *self)
self->flags &= ~MF_NOGRAVITY;
chunk = Spawn<AHereticImpChunk1> (self->x, self->y, self->z, ALLOW_REPLACE);
chunk = Spawn("HereticImpChunk1", self->x, self->y, self->z, ALLOW_REPLACE);
chunk->momx = pr_imp.Random2 () << 10;
chunk->momy = pr_imp.Random2 () << 10;
chunk->momz = 9*FRACUNIT;
chunk = Spawn<AHereticImpChunk2> (self->x, self->y, self->z, ALLOW_REPLACE);
chunk = Spawn("HereticImpChunk2", self->x, self->y, self->z, ALLOW_REPLACE);
chunk->momx = pr_imp.Random2 () << 10;
chunk->momy = pr_imp.Random2 () << 10;
chunk->momz = 9*FRACUNIT;
if (self->special1 == 666)
{ // Extreme death crash
self->SetState (&AHereticImp::States[S_IMP_XCRASH]);
self->SetState (self->FindState("XCrash"));
}
}
//----------------------------------------------------------------------------
//
// PROC A_ImpMeAttack
//
//----------------------------------------------------------------------------
void A_ImpMeAttack (AActor *self)
{
if (!self->target)
{
return;
}
S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM);
if (self->CheckMeleeRange ())
{
int damage = 5+(pr_impmeatk()&7);
P_DamageMobj (self->target, self, self, damage, NAME_Melee);
P_TraceBleed (damage, self->target, self);
}
}
//----------------------------------------------------------------------------
//
// PROC A_ImpMsAttack
//
//----------------------------------------------------------------------------
void A_ImpMsAttack (AActor *self)
{
AActor *dest;
angle_t an;
int dist;
if (!self->target || pr_impmsatk() > 64)
{
self->SetState (self->SeeState);
return;
}
dest = self->target;
self->flags |= MF_SKULLFLY;
S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM);
A_FaceTarget (self);
an = self->angle >> ANGLETOFINESHIFT;
self->momx = FixedMul (12*FRACUNIT, finecosine[an]);
self->momy = FixedMul (12*FRACUNIT, finesine[an]);
dist = P_AproxDistance (dest->x - self->x, dest->y - self->y);
dist = dist/(12*FRACUNIT);
if (dist < 1)
{
dist = 1;
}
self->momz = (dest->z + (dest->height>>1) - self->z)/dist;
}
//----------------------------------------------------------------------------
//
// PROC A_ImpMsAttack2
//
// Fireball attack of the imp leader.
//
//----------------------------------------------------------------------------
void A_ImpMsAttack2 (AActor *self)
{
if (!self->target)
{
return;
}
S_Sound (self, CHAN_WEAPON, self->AttackSound, 1, ATTN_NORM);
if (self->CheckMeleeRange ())
{
int damage = 5+(pr_impmsatk2()&7);
P_DamageMobj (self->target, self, self, damage, NAME_Melee);
P_TraceBleed (damage, self->target, self);
return;
}
P_SpawnMissile (self, self->target, RUNTIME_CLASS(AHereticImpBall));
}
//----------------------------------------------------------------------------
//
// PROC A_ImpDeath
@ -337,10 +46,6 @@ void A_ImpDeath (AActor *self)
{
self->flags &= ~MF_SOLID;
self->flags2 |= MF2_FLOORCLIP;
if (self->z <= self->floorz)
{
//self->SetState (&AHereticImp::States[S_IMP_CRASH]);
}
}
//----------------------------------------------------------------------------
@ -357,18 +62,3 @@ void A_ImpXDeath1 (AActor *self)
self->special1 = 666; // Flag the crash routine
}
//----------------------------------------------------------------------------
//
// PROC A_ImpXDeath2
//
//----------------------------------------------------------------------------
void A_ImpXDeath2 (AActor *self)
{
self->flags &= ~MF_NOGRAVITY;
if (self->z <= self->floorz)
{
self->SetState (&AHereticImp::States[S_IMP_CRASH]);
}
}

View file

@ -18,129 +18,6 @@ static FRandom pr_volcano ("VolcanoSet");
static FRandom pr_blast ("VolcanoBlast");
static FRandom pr_impact ("VolcBallImpact");
// --- Pods -----------------------------------------------------------------
void A_PodPain (AActor *);
void A_RemovePod (AActor *);
void A_MakePod (AActor *);
// Pod ----------------------------------------------------------------------
class APod : public AActor
{
DECLARE_ACTOR (APod, AActor)
HAS_OBJECT_POINTERS
public:
void BeginPlay ();
TObjPtr<AActor> Generator;
void Serialize (FArchive &arc);
};
IMPLEMENT_POINTY_CLASS (APod)
DECLARE_POINTER (Generator)
END_POINTERS;
void APod::Serialize (FArchive &arc)
{
Super::Serialize (arc);
arc << Generator;
}
FState APod::States[] =
{
#define S_POD_WAIT 0
S_NORMAL (PPOD, 'A', 10, NULL , &States[S_POD_WAIT+0]),
#define S_POD_PAIN (S_POD_WAIT+1)
S_NORMAL (PPOD, 'B', 14, A_PodPain , &States[S_POD_WAIT+0]),
#define S_POD_DIE (S_POD_PAIN+1)
S_BRIGHT (PPOD, 'C', 5, A_RemovePod , &States[S_POD_DIE+1]),
S_BRIGHT (PPOD, 'D', 5, A_Scream , &States[S_POD_DIE+2]),
S_BRIGHT (PPOD, 'E', 5, A_Explode , &States[S_POD_DIE+3]),
S_BRIGHT (PPOD, 'F', 10, NULL , &AActor::States[S_FREETARGMOBJ]),
#define S_POD_GROW (S_POD_DIE+4)
S_NORMAL (PPOD, 'I', 3, NULL , &States[S_POD_GROW+1]),
S_NORMAL (PPOD, 'J', 3, NULL , &States[S_POD_GROW+2]),
S_NORMAL (PPOD, 'K', 3, NULL , &States[S_POD_GROW+3]),
S_NORMAL (PPOD, 'L', 3, NULL , &States[S_POD_GROW+4]),
S_NORMAL (PPOD, 'M', 3, NULL , &States[S_POD_GROW+5]),
S_NORMAL (PPOD, 'N', 3, NULL , &States[S_POD_GROW+6]),
S_NORMAL (PPOD, 'O', 3, NULL , &States[S_POD_GROW+7]),
S_NORMAL (PPOD, 'P', 3, NULL , &States[S_POD_WAIT+0])
};
BEGIN_DEFAULTS (APod, Heretic, 2035, 125)
PROP_SpawnHealth (45)
PROP_RadiusFixed (16)
PROP_HeightFixed (54)
PROP_PainChance (255)
PROP_Flags (MF_SOLID|MF_NOBLOOD|MF_SHOOTABLE|MF_DROPOFF)
PROP_Flags2 (MF2_WINDTHRUST|MF2_PUSHABLE|MF2_SLIDE|MF2_PASSMOBJ|MF2_TELESTOMP)
PROP_Flags3 (MF3_DONTMORPH|MF3_NOBLOCKMONST|MF3_DONTGIB)
PROP_Flags5 (MF5_OLDRADIUSDMG)
PROP_SpawnState (S_POD_WAIT)
PROP_PainState (S_POD_PAIN)
PROP_DeathState (S_POD_DIE)
PROP_DeathSound ("world/podexplode")
END_DEFAULTS
void APod::BeginPlay ()
{
Super::BeginPlay ();
Generator = NULL;
}
// Pod goo (falls from pod when damaged) ------------------------------------
class APodGoo : public AActor
{
DECLARE_ACTOR (APodGoo, AActor)
};
FState APodGoo::States[] =
{
#define S_PODGOO 0
S_NORMAL (PPOD, 'G', 8, NULL , &States[S_PODGOO+1]),
S_NORMAL (PPOD, 'H', 8, NULL , &States[S_PODGOO+0]),
#define S_PODGOOX (S_PODGOO+2)
S_NORMAL (PPOD, 'G', 10, NULL , NULL)
};
IMPLEMENT_ACTOR (APodGoo, Heretic, -1, 0)
PROP_RadiusFixed (2)
PROP_HeightFixed (4)
PROP_Gravity (FRACUNIT/8)
PROP_Flags (MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF)
PROP_Flags2 (MF2_NOTELEPORT|MF2_CANNOTPUSH)
PROP_SpawnState (S_PODGOO)
END_DEFAULTS
// Pod generator ------------------------------------------------------------
class APodGenerator : public AActor
{
DECLARE_ACTOR (APodGenerator, AActor)
};
FState APodGenerator::States[] =
{
S_NORMAL (TNT1, 'A', 35, A_MakePod , &States[0])
};
IMPLEMENT_ACTOR (APodGenerator, Heretic, 43, 126)
PROP_Flags (MF_NOBLOCKMAP|MF_NOSECTOR)
PROP_SpawnState (0)
END_DEFAULTS
// --- Pod action functions -------------------------------------------------
//----------------------------------------------------------------------------
//
// PROC A_PodPain
@ -160,7 +37,7 @@ void A_PodPain (AActor *actor)
}
for (count = chance > 240 ? 2 : 1; count; count--)
{
goo = Spawn<APodGoo> (actor->x, actor->y, actor->z + 48*FRACUNIT, ALLOW_REPLACE);
goo = Spawn("PodGoo", actor->x, actor->y, actor->z + 48*FRACUNIT, ALLOW_REPLACE);
goo->target = actor;
goo->momx = pr_podpain.Random2() << 9;
goo->momy = pr_podpain.Random2() << 9;
@ -178,7 +55,7 @@ void A_RemovePod (AActor *actor)
{
AActor *mo;
if ( (mo = static_cast<APod *>(actor)->Generator) )
if ( (mo = actor->master))
{
if (mo->special1 > 0)
{
@ -197,7 +74,7 @@ void A_RemovePod (AActor *actor)
void A_MakePod (AActor *actor)
{
APod *mo;
AActor *mo;
fixed_t x;
fixed_t y;
fixed_t z;
@ -209,142 +86,20 @@ void A_MakePod (AActor *actor)
x = actor->x;
y = actor->y;
z = actor->z;
mo = Spawn<APod> (x, y, ONFLOORZ, ALLOW_REPLACE);
mo = Spawn("Pod", x, y, ONFLOORZ, ALLOW_REPLACE);
if (!P_CheckPosition (mo, x, y))
{ // Didn't fit
mo->Destroy ();
return;
}
mo->SetState (&APod::States[S_POD_GROW]);
mo->SetState (mo->FindState("Grow"));
P_ThrustMobj (mo, pr_makepod()<<24, (fixed_t)(4.5*FRACUNIT));
S_Sound (mo, CHAN_BODY, "world/podgrow", 1, ATTN_IDLE);
actor->special1++; // Increment generated pod count
mo->Generator = actor; // Link the generator to the pod
mo->master = actor; // Link the generator to the pod
return;
}
// --- Teleglitter ----------------------------------------------------------
void A_SpawnTeleGlitter (AActor *);
void A_SpawnTeleGlitter2 (AActor *);
void A_AccTeleGlitter (AActor *);
// Teleglitter generator 1 --------------------------------------------------
class ATeleGlitterGenerator1 : public AActor
{
DECLARE_ACTOR (ATeleGlitterGenerator1, AActor)
};
FState ATeleGlitterGenerator1::States[] =
{
S_NORMAL (TGLT, 'A', 8, A_SpawnTeleGlitter , &States[0])
};
IMPLEMENT_ACTOR (ATeleGlitterGenerator1, Heretic, 74, 166)
PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOSECTOR)
PROP_SpawnState (0)
END_DEFAULTS
// Teleglitter generator 2 --------------------------------------------------
class ATeleGlitterGenerator2 : public AActor
{
DECLARE_ACTOR (ATeleGlitterGenerator2, AActor)
};
FState ATeleGlitterGenerator2::States[] =
{
S_NORMAL (TGLT, 'F', 8, A_SpawnTeleGlitter2 , &States[0])
};
IMPLEMENT_ACTOR (ATeleGlitterGenerator2, Heretic, 52, 167)
PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOSECTOR)
PROP_SpawnState (0)
END_DEFAULTS
// Teleglitter 1 ------------------------------------------------------------
class ATeleGlitter1 : public AActor
{
DECLARE_ACTOR (ATeleGlitter1, AActor)
};
FState ATeleGlitter1::States[] =
{
S_BRIGHT (TGLT, 'A', 2, NULL , &States[1]),
S_BRIGHT (TGLT, 'B', 2, A_AccTeleGlitter , &States[2]),
S_BRIGHT (TGLT, 'C', 2, NULL , &States[3]),
S_BRIGHT (TGLT, 'D', 2, A_AccTeleGlitter , &States[4]),
S_BRIGHT (TGLT, 'E', 2, NULL , &States[0])
};
IMPLEMENT_ACTOR (ATeleGlitter1, Heretic, -1, 0)
PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY|MF_MISSILE)
PROP_RenderStyle (STYLE_Add)
PROP_SpawnState (0)
PROP_Damage (0)
END_DEFAULTS
// Teleglitter 2 ------------------------------------------------------------
class ATeleGlitter2 : public AActor
{
DECLARE_ACTOR (ATeleGlitter2, AActor)
};
FState ATeleGlitter2::States[] =
{
S_BRIGHT (TGLT, 'F', 2, NULL , &States[1]),
S_BRIGHT (TGLT, 'G', 2, A_AccTeleGlitter , &States[2]),
S_BRIGHT (TGLT, 'H', 2, NULL , &States[3]),
S_BRIGHT (TGLT, 'I', 2, A_AccTeleGlitter , &States[4]),
S_BRIGHT (TGLT, 'J', 2, NULL , &States[0])
};
IMPLEMENT_ACTOR (ATeleGlitter2, Heretic, -1, 0)
PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY|MF_MISSILE)
PROP_RenderStyle (STYLE_Add)
PROP_SpawnState (0)
PROP_Damage (0)
END_DEFAULTS
// --- Teleglitter action functions -----------------------------------------
//----------------------------------------------------------------------------
//
// PROC A_SpawnTeleGlitter
//
//----------------------------------------------------------------------------
void A_SpawnTeleGlitter (AActor *actor)
{
AActor *mo;
fixed_t x = actor->x+((pr_teleg()&31)-16)*FRACUNIT;
fixed_t y = actor->y+((pr_teleg()&31)-16)*FRACUNIT;
mo = Spawn<ATeleGlitter1> (x, y,
actor->Sector->floorplane.ZatPoint (actor->x, actor->y), ALLOW_REPLACE);
mo->momz = FRACUNIT/4;
}
//----------------------------------------------------------------------------
//
// PROC A_SpawnTeleGlitter2
//
//----------------------------------------------------------------------------
void A_SpawnTeleGlitter2 (AActor *actor)
{
AActor *mo;
fixed_t x = actor->x+((pr_teleg2()&31)-16)*FRACUNIT;
fixed_t y = actor->y+((pr_teleg2()&31)-16)*FRACUNIT;
mo = Spawn<ATeleGlitter2> (x, y,
actor->Sector->floorplane.ZatPoint (actor->x, actor->y), ALLOW_REPLACE);
mo->momz = FRACUNIT/4;
}
//----------------------------------------------------------------------------
//
// PROC A_AccTeleGlitter
@ -359,135 +114,9 @@ void A_AccTeleGlitter (AActor *actor)
}
}
// --- Volcano --------------------------------------------------------------
void A_VolcanoSet (AActor *);
void A_VolcanoBlast (AActor *);
void A_VolcBallImpact (AActor *);
extern void A_BeastPuff (AActor *);
// Volcano ------------------------------------------------------------------
class AVolcano : public AActor
{
DECLARE_ACTOR (AVolcano, AActor)
};
FState AVolcano::States[] =
{
S_NORMAL (VLCO, 'A', 350, NULL , &States[1]),
S_NORMAL (VLCO, 'A', 35, A_VolcanoSet , &States[2]),
S_NORMAL (VLCO, 'B', 3, NULL , &States[3]),
S_NORMAL (VLCO, 'C', 3, NULL , &States[4]),
S_NORMAL (VLCO, 'D', 3, NULL , &States[5]),
S_NORMAL (VLCO, 'B', 3, NULL , &States[6]),
S_NORMAL (VLCO, 'C', 3, NULL , &States[7]),
S_NORMAL (VLCO, 'D', 3, NULL , &States[8]),
S_NORMAL (VLCO, 'E', 10, A_VolcanoBlast , &States[1])
};
IMPLEMENT_ACTOR (AVolcano, Heretic, 87, 150)
PROP_RadiusFixed (12)
PROP_HeightFixed (20)
PROP_Flags (MF_SOLID)
PROP_SpawnState (0)
END_DEFAULTS
// Volcano blast ------------------------------------------------------------
class AVolcanoBlast : public AActor
{
DECLARE_ACTOR (AVolcanoBlast, AActor)
};
FState AVolcanoBlast::States[] =
{
#define S_VOLCANOBALL 0
S_NORMAL (VFBL, 'A', 4, A_BeastPuff , &States[S_VOLCANOBALL+1]),
S_NORMAL (VFBL, 'B', 4, A_BeastPuff , &States[S_VOLCANOBALL+0]),
#define S_VOLCANOBALLX (S_VOLCANOBALL+2)
S_NORMAL (XPL1, 'A', 4, A_VolcBallImpact , &States[S_VOLCANOBALLX+1]),
S_NORMAL (XPL1, 'B', 4, NULL , &States[S_VOLCANOBALLX+2]),
S_NORMAL (XPL1, 'C', 4, NULL , &States[S_VOLCANOBALLX+3]),
S_NORMAL (XPL1, 'D', 4, NULL , &States[S_VOLCANOBALLX+4]),
S_NORMAL (XPL1, 'E', 4, NULL , &States[S_VOLCANOBALLX+5]),
S_NORMAL (XPL1, 'F', 4, NULL , NULL)
};
IMPLEMENT_ACTOR (AVolcanoBlast, Heretic, -1, 123)
PROP_RadiusFixed (8)
PROP_HeightFixed (8)
PROP_SpeedFixed (2)
PROP_Damage (2)
PROP_DamageType (NAME_Fire)
PROP_Gravity (FRACUNIT/8)
PROP_Flags (MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF)
PROP_Flags2 (MF2_NOTELEPORT)
PROP_SpawnState (S_VOLCANOBALL)
PROP_DeathState (S_VOLCANOBALLX)
PROP_DeathSound ("world/volcano/blast")
END_DEFAULTS
// Volcano T Blast ----------------------------------------------------------
class AVolcanoTBlast : public AActor
{
DECLARE_ACTOR (AVolcanoTBlast, AActor)
};
FState AVolcanoTBlast::States[] =
{
#define S_VOLCANOTBALL 0
S_NORMAL (VTFB, 'A', 4, NULL , &States[S_VOLCANOTBALL+1]),
S_NORMAL (VTFB, 'B', 4, NULL , &States[S_VOLCANOTBALL+0]),
#define S_VOLCANOTBALLX (S_VOLCANOTBALL+2)
S_NORMAL (SFFI, 'C', 4, NULL , &States[S_VOLCANOTBALLX+1]),
S_NORMAL (SFFI, 'B', 4, NULL , &States[S_VOLCANOTBALLX+2]),
S_NORMAL (SFFI, 'A', 4, NULL , &States[S_VOLCANOTBALLX+3]),
S_NORMAL (SFFI, 'B', 4, NULL , &States[S_VOLCANOTBALLX+4]),
S_NORMAL (SFFI, 'C', 4, NULL , &States[S_VOLCANOTBALLX+5]),
S_NORMAL (SFFI, 'D', 4, NULL , &States[S_VOLCANOTBALLX+6]),
S_NORMAL (SFFI, 'E', 4, NULL , NULL)
};
IMPLEMENT_ACTOR (AVolcanoTBlast, Heretic, -1, 124)
PROP_RadiusFixed (8)
PROP_HeightFixed (6)
PROP_SpeedFixed (2)
PROP_Damage (1)
PROP_DamageType (NAME_Fire)
PROP_Gravity (FRACUNIT/8)
PROP_Flags (MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF)
PROP_Flags2 (MF2_NOTELEPORT)
PROP_SpawnState (S_VOLCANOTBALL)
PROP_DeathState (S_VOLCANOTBALLX)
END_DEFAULTS
//----------------------------------------------------------------------------
//
// PROC A_BeastPuff
//
//----------------------------------------------------------------------------
void A_BeastPuff (AActor *actor)
{
if (pr_volcano() > 64)
{
fixed_t x, y, z;
x = actor->x + (pr_volcano.Random2 () << 10);
y = actor->y + (pr_volcano.Random2 () << 10);
z = actor->z + (pr_volcano.Random2 () << 10);
Spawn ("Puffy", x, y, z, ALLOW_REPLACE);
}
}//----------------------------------------------------------------------------
//
// PROC A_VolcanoSet
//
//----------------------------------------------------------------------------
@ -513,7 +142,7 @@ void A_VolcanoBlast (AActor *volcano)
count = 1 + (pr_blast() % 3);
for (i = 0; i < count; i++)
{
blast = Spawn<AVolcanoBlast> (volcano->x, volcano->y,
blast = Spawn("VolcanoBlast", volcano->x, volcano->y,
volcano->z + 44*FRACUNIT, ALLOW_REPLACE);
blast->target = volcano;
angle = pr_blast () << 24;
@ -549,7 +178,7 @@ void A_VolcBallImpact (AActor *ball)
P_RadiusAttack (ball, ball->target, 25, 25, NAME_Fire, true);
for (i = 0; i < 4; i++)
{
tiny = Spawn<AVolcanoTBlast> (ball->x, ball->y, ball->z, ALLOW_REPLACE);
tiny = Spawn("VolcanoTBlast", ball->x, ball->y, ball->z, ALLOW_REPLACE);
tiny->target = ball;
angle = i*ANG90;
tiny->angle = angle;

View file

@ -2229,7 +2229,7 @@ END_DEFAULTS
int AHornRodFX2::DoSpecialDamage (AActor *target, int damage)
{
if (target->IsKindOf (RUNTIME_CLASS (ASorcerer2)) && pr_hrfx2() < 96)
if (target->IsKindOf (PClass::FindClass("Sorcerer2")) && pr_hrfx2() < 96)
{ // D'Sparil teleports away
P_DSparilTeleport (target);
return -1;
@ -2665,7 +2665,7 @@ END_DEFAULTS
int APhoenixFX1::DoSpecialDamage (AActor *target, int damage)
{
if (target->IsKindOf (RUNTIME_CLASS (ASorcerer2)) && pr_pfx1() < 96)
if (target->IsKindOf (PClass::FindClass("Sorcerer2")) && pr_hrfx2() < 96)
{ // D'Sparil teleports away
P_DSparilTeleport (target);
return -1;

View file

@ -11,235 +11,14 @@ static FRandom pr_foo ("WhirlwindDamage");
static FRandom pr_atk ("LichAttack");
static FRandom pr_seek ("WhirlwindSeek");
void A_LichAttack (AActor *);
void A_LichIceImpact (AActor *);
void A_LichFireGrow (AActor *);
void A_WhirlwindSeek (AActor *);
// Ironlich -----------------------------------------------------------------
class AIronlich : public AActor
{
DECLARE_ACTOR (AIronlich, AActor)
public:
void NoBlockingSet ();
};
FState AIronlich::States[] =
{
#define S_HEAD_LOOK 0
S_NORMAL (LICH, 'A', 10, A_Look , &States[S_HEAD_LOOK]),
#define S_HEAD_FLOAT (S_HEAD_LOOK+1)
S_NORMAL (LICH, 'A', 4, A_Chase , &States[S_HEAD_FLOAT]),
#define S_HEAD_ATK (S_HEAD_FLOAT+1)
S_NORMAL (LICH, 'A', 5, A_FaceTarget , &States[S_HEAD_ATK+1]),
S_NORMAL (LICH, 'B', 20, A_LichAttack , &States[S_HEAD_FLOAT]),
#define S_HEAD_PAIN (S_HEAD_ATK+2)
S_NORMAL (LICH, 'A', 4, NULL , &States[S_HEAD_PAIN+1]),
S_NORMAL (LICH, 'A', 4, A_Pain , &States[S_HEAD_FLOAT]),
#define S_HEAD_DIE (S_HEAD_PAIN+2)
S_NORMAL (LICH, 'C', 7, NULL , &States[S_HEAD_DIE+1]),
S_NORMAL (LICH, 'D', 7, A_Scream , &States[S_HEAD_DIE+2]),
S_NORMAL (LICH, 'E', 7, NULL , &States[S_HEAD_DIE+3]),
S_NORMAL (LICH, 'F', 7, NULL , &States[S_HEAD_DIE+4]),
S_NORMAL (LICH, 'G', 7, A_NoBlocking , &States[S_HEAD_DIE+5]),
S_NORMAL (LICH, 'H', 7, NULL , &States[S_HEAD_DIE+6]),
S_NORMAL (LICH, 'I', -1, A_BossDeath , NULL)
};
IMPLEMENT_ACTOR (AIronlich, Heretic, 6, 20)
PROP_SpawnHealth (700)
PROP_RadiusFixed (40)
PROP_HeightFixed (72)
PROP_Mass (325)
PROP_SpeedFixed (6)
PROP_PainChance (32)
PROP_Flags (MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_NOBLOOD)
PROP_Flags2 (MF2_MCROSS|MF2_PASSMOBJ|MF2_PUSHWALL)
PROP_Flags3 (MF3_DONTMORPH|MF3_DONTSQUASH)
PROP_Flags4 (MF4_BOSSDEATH)
PROP_SpawnState (S_HEAD_LOOK)
PROP_SeeState (S_HEAD_FLOAT)
PROP_PainState (S_HEAD_PAIN)
PROP_MissileState (S_HEAD_ATK)
PROP_DeathState (S_HEAD_DIE)
PROP_SeeSound ("ironlich/sight")
PROP_AttackSound ("ironlich/attack")
PROP_PainSound ("ironlich/pain")
PROP_DeathSound ("ironlich/death")
PROP_ActiveSound ("ironlich/active")
PROP_Obituary("$OB_IRONLICH")
PROP_HitObituary("$OB_IRONLICHHIT")
END_DEFAULTS
void AIronlich::NoBlockingSet ()
{
P_DropItem (this, "BlasterAmmo", 10, 84);
P_DropItem (this, "ArtiEgg", 0, 51);
}
// Head FX 1 ----------------------------------------------------------------
class AHeadFX1 : public AActor
{
DECLARE_ACTOR (AHeadFX1, AActor)
};
FState AHeadFX1::States[] =
{
#define S_HEADFX1 0
S_BRIGHT (FX05, 'A', 6, NULL , &States[S_HEADFX1+1]),
S_BRIGHT (FX05, 'B', 6, NULL , &States[S_HEADFX1+2]),
S_BRIGHT (FX05, 'C', 6, NULL , &States[S_HEADFX1+0]),
#define S_HEADFXI1 (S_HEADFX1+3)
S_BRIGHT (FX05, 'D', 5, A_LichIceImpact , &States[S_HEADFXI1+1]),
S_BRIGHT (FX05, 'E', 5, NULL , &States[S_HEADFXI1+2]),
S_BRIGHT (FX05, 'F', 5, NULL , &States[S_HEADFXI1+3]),
S_BRIGHT (FX05, 'G', 5, NULL , NULL)
};
IMPLEMENT_ACTOR (AHeadFX1, Heretic, -1, 164)
PROP_RadiusFixed (12)
PROP_HeightFixed (6)
PROP_SpeedFixed (13)
PROP_Damage (1)
PROP_Flags (MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY)
PROP_Flags2 (MF2_NOTELEPORT|MF2_THRUGHOST)
PROP_RenderStyle (STYLE_Add)
PROP_SpawnState (S_HEADFX1)
PROP_DeathState (S_HEADFXI1)
END_DEFAULTS
AT_SPEED_SET (HeadFX1, speed)
{
SimpleSpeedSetter (AHeadFX1, 13*FRACUNIT, 20*FRACUNIT, speed);
}
// Head FX 2 ----------------------------------------------------------------
class AHeadFX2 : public AActor
{
DECLARE_ACTOR (AHeadFX2, AActor)
};
FState AHeadFX2::States[] =
{
#define S_HEADFX2 0
S_BRIGHT (FX05, 'H', 6, NULL , &States[S_HEADFX2+1]),
S_BRIGHT (FX05, 'I', 6, NULL , &States[S_HEADFX2+2]),
S_BRIGHT (FX05, 'J', 6, NULL , &States[S_HEADFX2+0]),
#define S_HEADFXI2 (S_HEADFX2+3)
S_BRIGHT (FX05, 'D', 5, NULL , &States[S_HEADFXI2+1]),
S_BRIGHT (FX05, 'E', 5, NULL , &States[S_HEADFXI2+2]),
S_BRIGHT (FX05, 'F', 5, NULL , &States[S_HEADFXI2+3]),
S_BRIGHT (FX05, 'G', 5, NULL , NULL)
};
IMPLEMENT_ACTOR (AHeadFX2, Heretic, -1, 0)
PROP_RadiusFixed (12)
PROP_HeightFixed (6)
PROP_SpeedFixed (8)
PROP_Damage (3)
PROP_Flags (MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY)
PROP_Flags2 (MF2_NOTELEPORT)
PROP_RenderStyle (STYLE_Add)
PROP_SpawnState (S_HEADFX2)
PROP_DeathState (S_HEADFXI2)
END_DEFAULTS
// Head FX 3 ----------------------------------------------------------------
class AHeadFX3 : public AActor
{
DECLARE_ACTOR (AHeadFX3, AActor)
};
FState AHeadFX3::States[] =
{
#define S_HEADFX3 0
S_BRIGHT (FX06, 'A', 4, A_LichFireGrow , &States[S_HEADFX3+1]),
S_BRIGHT (FX06, 'B', 4, A_LichFireGrow , &States[S_HEADFX3+2]),
S_BRIGHT (FX06, 'C', 4, A_LichFireGrow , &States[S_HEADFX3+0]),
S_BRIGHT (FX06, 'A', 5, NULL , &States[S_HEADFX3+4]),
S_BRIGHT (FX06, 'B', 5, NULL , &States[S_HEADFX3+5]),
S_BRIGHT (FX06, 'C', 5, NULL , &States[S_HEADFX3+3]),
#define S_HEADFXI3 (S_HEADFX3+6)
S_BRIGHT (FX06, 'D', 5, NULL , &States[S_HEADFXI3+1]),
S_BRIGHT (FX06, 'E', 5, NULL , &States[S_HEADFXI3+2]),
S_BRIGHT (FX06, 'F', 5, NULL , &States[S_HEADFXI3+3]),
S_BRIGHT (FX06, 'G', 5, NULL , NULL)
};
IMPLEMENT_ACTOR (AHeadFX3, Heretic, -1, 0)
PROP_RadiusFixed (14)
PROP_HeightFixed (12)
PROP_SpeedFixed (10)
PROP_Damage (5)
PROP_Flags (MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY)
PROP_Flags2 (MF2_WINDTHRUST|MF2_NOTELEPORT)
PROP_RenderStyle (STYLE_Add)
PROP_SpawnState (S_HEADFX3)
PROP_DeathState (S_HEADFXI3)
END_DEFAULTS
AT_SPEED_SET (HeadFX3, speed)
{
SimpleSpeedSetter (AHeadFX3, 10*FRACUNIT, 18*FRACUNIT, speed);
}
// Whirlwind ----------------------------------------------------------------
class AWhirlwind : public AActor
{
DECLARE_ACTOR (AWhirlwind, AActor)
DECLARE_CLASS (AWhirlwind, AActor)
public:
int DoSpecialDamage (AActor *target, int damage);
};
FState AWhirlwind::States[] =
{
#define S_HEADFX4 0
S_NORMAL (FX07, 'D', 3, NULL , &States[S_HEADFX4+1]),
S_NORMAL (FX07, 'E', 3, NULL , &States[S_HEADFX4+2]),
S_NORMAL (FX07, 'F', 3, NULL , &States[S_HEADFX4+3]),
S_NORMAL (FX07, 'G', 3, NULL , &States[S_HEADFX4+4]),
S_NORMAL (FX07, 'A', 3, A_WhirlwindSeek , &States[S_HEADFX4+5]),
S_NORMAL (FX07, 'B', 3, A_WhirlwindSeek , &States[S_HEADFX4+6]),
S_NORMAL (FX07, 'C', 3, A_WhirlwindSeek , &States[S_HEADFX4+4]),
#define S_HEADFXI4 (S_HEADFX4+7)
S_NORMAL (FX07, 'G', 4, NULL , &States[S_HEADFXI4+1]),
S_NORMAL (FX07, 'F', 4, NULL , &States[S_HEADFXI4+2]),
S_NORMAL (FX07, 'E', 4, NULL , &States[S_HEADFXI4+3]),
S_NORMAL (FX07, 'D', 4, NULL , NULL)
};
IMPLEMENT_ACTOR (AWhirlwind, Heretic, -1, 165)
PROP_RadiusFixed (16)
PROP_HeightFixed (74)
PROP_SpeedFixed (10)
PROP_Damage (1)
PROP_Flags (MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY)
PROP_Flags2 (MF2_NOTELEPORT|MF2_SEEKERMISSILE)
PROP_Flags3 (MF3_EXPLOCOUNT)
PROP_RenderStyle (STYLE_Translucent)
PROP_Alpha (HR_SHADOW)
PROP_SpawnState (S_HEADFX4)
PROP_DeathState (S_HEADFXI4)
END_DEFAULTS
IMPLEMENT_CLASS(AWhirlwind)
int AWhirlwind::DoSpecialDamage (AActor *target, int damage)
{
@ -309,18 +88,18 @@ void A_LichAttack (AActor *actor)
randAttack = pr_atk ();
if (randAttack < atkResolve1[dist])
{ // Ice ball
P_SpawnMissile (actor, target, RUNTIME_CLASS(AHeadFX1));
P_SpawnMissile (actor, target, PClass::FindClass("HeadFX1"));
S_Sound (actor, CHAN_BODY, "ironlich/attack2", 1, ATTN_NORM);
}
else if (randAttack < atkResolve2[dist])
{ // Fire column
baseFire = P_SpawnMissile (actor, target, RUNTIME_CLASS(AHeadFX3));
baseFire = P_SpawnMissile (actor, target, PClass::FindClass("HeadFX3"));
if (baseFire != NULL)
{
baseFire->SetState (&AHeadFX3::States[S_HEADFX3+3]); // Don't grow
baseFire->SetState (baseFire->FindState("NoGrow"));
for (i = 0; i < 5; i++)
{
fire = Spawn<AHeadFX3> (baseFire->x, baseFire->y,
fire = Spawn("HeadFX3", baseFire->x, baseFire->y,
baseFire->z, ALLOW_REPLACE);
if (i == 0)
{
@ -394,7 +173,7 @@ void A_LichIceImpact (AActor *ice)
for (i = 0; i < 8; i++)
{
shard = Spawn<AHeadFX2> (ice->x, ice->y, ice->z, ALLOW_REPLACE);
shard = Spawn("HeadFX2", ice->x, ice->y, ice->z, ALLOW_REPLACE);
angle = i*ANG45;
shard->target = ice->target;
shard->angle = angle;
@ -419,7 +198,7 @@ void A_LichFireGrow (AActor *fire)
if (fire->health == 0)
{
fire->Damage = fire->GetDefault()->Damage;
fire->SetState (&AHeadFX3::States[S_HEADFX3+3]);
fire->SetState (fire->FindState("NoGrow"));
}
}

View file

@ -11,170 +11,6 @@
static FRandom pr_dripblood ("DripBlood");
static FRandom pr_knightatk ("KnightAttack");
void A_KnightAttack (AActor *);
void A_DripBlood (AActor *);
void A_AxeSound (AActor *);
// Knight -------------------------------------------------------------------
class AKnight : public AActor
{
DECLARE_ACTOR (AKnight, AActor)
public:
void NoBlockingSet ();
};
FState AKnight::States[] =
{
#define S_KNIGHT_STND 0
S_NORMAL (KNIG, 'A', 10, A_Look , &States[S_KNIGHT_STND+1]),
S_NORMAL (KNIG, 'B', 10, A_Look , &States[S_KNIGHT_STND+0]),
#define S_KNIGHT_WALK (S_KNIGHT_STND+2)
S_NORMAL (KNIG, 'A', 4, A_Chase , &States[S_KNIGHT_WALK+1]),
S_NORMAL (KNIG, 'B', 4, A_Chase , &States[S_KNIGHT_WALK+2]),
S_NORMAL (KNIG, 'C', 4, A_Chase , &States[S_KNIGHT_WALK+3]),
S_NORMAL (KNIG, 'D', 4, A_Chase , &States[S_KNIGHT_WALK+0]),
#define S_KNIGHT_ATK (S_KNIGHT_WALK+4)
S_NORMAL (KNIG, 'E', 10, A_FaceTarget , &States[S_KNIGHT_ATK+1]),
S_NORMAL (KNIG, 'F', 8, A_FaceTarget , &States[S_KNIGHT_ATK+2]),
S_NORMAL (KNIG, 'G', 8, A_KnightAttack , &States[S_KNIGHT_ATK+3]),
S_NORMAL (KNIG, 'E', 10, A_FaceTarget , &States[S_KNIGHT_ATK+4]),
S_NORMAL (KNIG, 'F', 8, A_FaceTarget , &States[S_KNIGHT_ATK+5]),
S_NORMAL (KNIG, 'G', 8, A_KnightAttack , &States[S_KNIGHT_WALK+0]),
#define S_KNIGHT_PAIN (S_KNIGHT_ATK+6)
S_NORMAL (KNIG, 'H', 3, NULL , &States[S_KNIGHT_PAIN+1]),
S_NORMAL (KNIG, 'H', 3, A_Pain , &States[S_KNIGHT_WALK+0]),
#define S_KNIGHT_DIE (S_KNIGHT_PAIN+2)
S_NORMAL (KNIG, 'I', 6, NULL , &States[S_KNIGHT_DIE+1]),
S_NORMAL (KNIG, 'J', 6, A_Scream , &States[S_KNIGHT_DIE+2]),
S_NORMAL (KNIG, 'K', 6, NULL , &States[S_KNIGHT_DIE+3]),
S_NORMAL (KNIG, 'L', 6, A_NoBlocking , &States[S_KNIGHT_DIE+4]),
S_NORMAL (KNIG, 'M', 6, NULL , &States[S_KNIGHT_DIE+5]),
S_NORMAL (KNIG, 'N', 6, NULL , &States[S_KNIGHT_DIE+6]),
S_NORMAL (KNIG, 'O', -1, NULL , NULL)
};
IMPLEMENT_ACTOR (AKnight, Heretic, 64, 6)
PROP_SpawnHealth (200)
PROP_RadiusFixed (24)
PROP_HeightFixed (78)
PROP_Mass (150)
PROP_SpeedFixed (12)
PROP_PainChance (100)
PROP_Flags (MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL)
PROP_Flags2 (MF2_MCROSS|MF2_FLOORCLIP|MF2_PASSMOBJ|MF2_PUSHWALL)
PROP_SpawnState (S_KNIGHT_STND)
PROP_SeeState (S_KNIGHT_WALK)
PROP_PainState (S_KNIGHT_PAIN)
PROP_MeleeState (S_KNIGHT_ATK)
PROP_MissileState (S_KNIGHT_ATK)
PROP_DeathState (S_KNIGHT_DIE)
PROP_SeeSound ("hknight/sight")
PROP_AttackSound ("hknight/attack")
PROP_PainSound ("hknight/pain")
PROP_DeathSound ("hknight/death")
PROP_ActiveSound ("hknight/active")
PROP_Obituary("$OB_BONEKNIGHT")
PROP_HitObituary("$OB_BONEKNIGHTHIT")
END_DEFAULTS
void AKnight::NoBlockingSet ()
{
P_DropItem (this, "CrossbowAmmo", 5, 84);
}
// Knight ghost -------------------------------------------------------------
class AKnightGhost : public AKnight
{
DECLARE_STATELESS_ACTOR (AKnightGhost, AKnight)
};
IMPLEMENT_STATELESS_ACTOR (AKnightGhost, Heretic, 65, 129)
PROP_FlagsSet (MF_SHADOW)
PROP_Flags3 (MF3_GHOST)
PROP_RenderStyle (STYLE_Translucent)
PROP_Alpha (HR_SHADOW)
END_DEFAULTS
// Knight axe ---------------------------------------------------------------
class AKnightAxe : public AActor
{
DECLARE_ACTOR (AKnightAxe, AActor)
};
FState AKnightAxe::States[] =
{
#define S_SPINAXE 0
S_BRIGHT (SPAX, 'A', 3, A_AxeSound , &States[S_SPINAXE+1]),
S_BRIGHT (SPAX, 'B', 3, NULL , &States[S_SPINAXE+2]),
S_BRIGHT (SPAX, 'C', 3, NULL , &States[S_SPINAXE+0]),
#define S_SPINAXEX (S_SPINAXE+3)
S_BRIGHT (SPAX, 'D', 6, NULL , &States[S_SPINAXEX+1]),
S_BRIGHT (SPAX, 'E', 6, NULL , &States[S_SPINAXEX+2]),
S_BRIGHT (SPAX, 'F', 6, NULL , NULL)
};
IMPLEMENT_ACTOR (AKnightAxe, Heretic, -1, 127)
PROP_RadiusFixed (10)
PROP_HeightFixed (8)
PROP_SpeedFixed (9)
PROP_Damage (2)
PROP_Flags (MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY)
PROP_Flags2 (MF2_WINDTHRUST|MF2_NOTELEPORT|MF2_THRUGHOST)
PROP_SpawnState (S_SPINAXE)
PROP_DeathState (S_SPINAXEX)
PROP_DeathSound ("hknight/hit")
END_DEFAULTS
AT_SPEED_SET (KnightAxe, speed)
{
SimpleSpeedSetter (AKnightAxe, 9*FRACUNIT, 18*FRACUNIT, speed);
}
// Red axe ------------------------------------------------------------------
class ARedAxe : public AKnightAxe
{
DECLARE_ACTOR (ARedAxe, AKnightAxe)
};
FState ARedAxe::States[] =
{
#define S_REDAXE 0
S_BRIGHT (RAXE, 'A', 5, A_DripBlood , &States[S_REDAXE+1]),
S_BRIGHT (RAXE, 'B', 5, A_DripBlood , &States[S_REDAXE+0]),
#define S_REDAXEX (S_REDAXE+2)
S_BRIGHT (RAXE, 'C', 6, NULL , &States[S_REDAXEX+1]),
S_BRIGHT (RAXE, 'D', 6, NULL , &States[S_REDAXEX+2]),
S_BRIGHT (RAXE, 'E', 6, NULL , NULL)
};
IMPLEMENT_ACTOR (ARedAxe, Heretic, -1, 128)
PROP_Damage (7)
PROP_FlagsSet (MF_NOBLOCKMAP)
PROP_Flags2Clear (MF2_WINDTHRUST)
PROP_SpawnState (S_REDAXE)
PROP_DeathState (S_REDAXEX)
END_DEFAULTS
AT_SPEED_SET (RedAxe, speed)
{
SimpleSpeedSetter (ARedAxe, 9*FRACUNIT, 18*FRACUNIT, speed);
}
//----------------------------------------------------------------------------
//
// PROC A_DripBlood
@ -218,20 +54,10 @@ void A_KnightAttack (AActor *actor)
S_Sound (actor, CHAN_BODY, actor->AttackSound, 1, ATTN_NORM);
if (actor->flags & MF_SHADOW || pr_knightatk () < 40)
{ // Red axe
P_SpawnMissileZ (actor, actor->z + 36*FRACUNIT, actor->target, RUNTIME_CLASS(ARedAxe));
P_SpawnMissileZ (actor, actor->z + 36*FRACUNIT, actor->target, PClass::FindClass("RedAxe"));
return;
}
// Green axe
P_SpawnMissileZ (actor, actor->z + 36*FRACUNIT, actor->target, RUNTIME_CLASS(AKnightAxe));
P_SpawnMissileZ (actor, actor->z + 36*FRACUNIT, actor->target, PClass::FindClass("KnightAxe"));
}
//---------------------------------------------------------------------------
//
// PROC A_AxeSound
//
//---------------------------------------------------------------------------
void A_AxeSound (AActor *actor)
{
S_Sound (actor, CHAN_BODY, "hknight/axewhoosh", 1, ATTN_NORM);
}

View file

@ -10,126 +10,6 @@
static FRandom pr_wizatk3 ("WizAtk3");
void A_WizAtk1 (AActor *);
void A_WizAtk2 (AActor *);
void A_WizAtk3 (AActor *);
void A_GhostOff (AActor *);
// Class definitions --------------------------------------------------------
FState AWizard::States[] =
{
#define S_WIZARD_LOOK 0
S_NORMAL (WZRD, 'A', 10, A_Look , &States[S_WIZARD_LOOK+1]),
S_NORMAL (WZRD, 'B', 10, A_Look , &States[S_WIZARD_LOOK+0]),
#define S_WIZARD_WALK (S_WIZARD_LOOK+2)
S_NORMAL (WZRD, 'A', 3, A_Chase , &States[S_WIZARD_WALK+1]),
S_NORMAL (WZRD, 'A', 4, A_Chase , &States[S_WIZARD_WALK+2]),
S_NORMAL (WZRD, 'A', 3, A_Chase , &States[S_WIZARD_WALK+3]),
S_NORMAL (WZRD, 'A', 4, A_Chase , &States[S_WIZARD_WALK+4]),
S_NORMAL (WZRD, 'B', 3, A_Chase , &States[S_WIZARD_WALK+5]),
S_NORMAL (WZRD, 'B', 4, A_Chase , &States[S_WIZARD_WALK+6]),
S_NORMAL (WZRD, 'B', 3, A_Chase , &States[S_WIZARD_WALK+7]),
S_NORMAL (WZRD, 'B', 4, A_Chase , &States[S_WIZARD_WALK+0]),
#define S_WIZARD_ATK (S_WIZARD_WALK+8)
S_NORMAL (WZRD, 'C', 4, A_WizAtk1 , &States[S_WIZARD_ATK+1]),
S_NORMAL (WZRD, 'C', 4, A_WizAtk2 , &States[S_WIZARD_ATK+2]),
S_NORMAL (WZRD, 'C', 4, A_WizAtk1 , &States[S_WIZARD_ATK+3]),
S_NORMAL (WZRD, 'C', 4, A_WizAtk2 , &States[S_WIZARD_ATK+4]),
S_NORMAL (WZRD, 'C', 4, A_WizAtk1 , &States[S_WIZARD_ATK+5]),
S_NORMAL (WZRD, 'C', 4, A_WizAtk2 , &States[S_WIZARD_ATK+6]),
S_NORMAL (WZRD, 'C', 4, A_WizAtk1 , &States[S_WIZARD_ATK+7]),
S_NORMAL (WZRD, 'C', 4, A_WizAtk2 , &States[S_WIZARD_ATK+8]),
S_NORMAL (WZRD, 'D', 12, A_WizAtk3 , &States[S_WIZARD_WALK+0]),
#define S_WIZARD_PAIN (S_WIZARD_ATK+9)
S_NORMAL (WZRD, 'E', 3, A_GhostOff , &States[S_WIZARD_PAIN+1]),
S_NORMAL (WZRD, 'E', 3, A_Pain , &States[S_WIZARD_WALK+0]),
#define S_WIZARD_DIE (S_WIZARD_PAIN+2)
S_NORMAL (WZRD, 'F', 6, A_GhostOff , &States[S_WIZARD_DIE+1]),
S_NORMAL (WZRD, 'G', 6, A_Scream , &States[S_WIZARD_DIE+2]),
S_NORMAL (WZRD, 'H', 6, NULL , &States[S_WIZARD_DIE+3]),
S_NORMAL (WZRD, 'I', 6, NULL , &States[S_WIZARD_DIE+4]),
S_NORMAL (WZRD, 'J', 6, A_NoBlocking , &States[S_WIZARD_DIE+5]),
S_NORMAL (WZRD, 'K', 6, NULL , &States[S_WIZARD_DIE+6]),
S_NORMAL (WZRD, 'L', 6, NULL , &States[S_WIZARD_DIE+7]),
S_NORMAL (WZRD, 'M', -1, NULL , NULL)
};
IMPLEMENT_ACTOR (AWizard, Heretic, 15, 19)
PROP_SpawnHealth (180)
PROP_RadiusFixed (16)
PROP_HeightFixed (68)
PROP_Mass (100)
PROP_SpeedFixed (12)
PROP_PainChance (64)
PROP_Flags (MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL|MF_FLOAT|MF_NOGRAVITY)
PROP_Flags2 (MF2_MCROSS|MF2_PASSMOBJ|MF2_PUSHWALL)
PROP_Flags3 (MF3_DONTOVERLAP)
PROP_SpawnState (S_WIZARD_LOOK)
PROP_SeeState (S_WIZARD_WALK)
PROP_PainState (S_WIZARD_PAIN)
PROP_MissileState (S_WIZARD_ATK)
PROP_DeathState (S_WIZARD_DIE)
PROP_SeeSound ("wizard/sight")
PROP_AttackSound ("wizard/attack")
PROP_PainSound ("wizard/pain")
PROP_DeathSound ("wizard/death")
PROP_ActiveSound ("wizard/active")
PROP_Obituary("$OB_WIZARD")
PROP_HitObituary("$OB_WIZARDHIT")
END_DEFAULTS
void AWizard::NoBlockingSet ()
{
P_DropItem (this, "BlasterAmmo", 10, 84);
P_DropItem (this, "ArtiTomeOfPower", 0, 4);
}
class AWizardFX1 : public AActor
{
DECLARE_ACTOR (AWizardFX1, AActor)
};
FState AWizardFX1::States[] =
{
#define S_WIZFX1 0
S_BRIGHT (FX11, 'A', 6, NULL , &States[S_WIZFX1+1]),
S_BRIGHT (FX11, 'B', 6, NULL , &States[S_WIZFX1+0]),
#define S_WIZFXI1 (S_WIZFX1+2)
S_BRIGHT (FX11, 'C', 5, NULL , &States[S_WIZFXI1+1]),
S_BRIGHT (FX11, 'D', 5, NULL , &States[S_WIZFXI1+2]),
S_BRIGHT (FX11, 'E', 5, NULL , &States[S_WIZFXI1+3]),
S_BRIGHT (FX11, 'F', 5, NULL , &States[S_WIZFXI1+4]),
S_BRIGHT (FX11, 'G', 5, NULL , NULL)
};
IMPLEMENT_ACTOR (AWizardFX1, Heretic, -1, 140)
PROP_RadiusFixed (10)
PROP_HeightFixed (6)
PROP_SpeedFixed (18)
PROP_Damage (3)
PROP_Flags (MF_NOBLOCKMAP|MF_MISSILE|MF_DROPOFF|MF_NOGRAVITY)
PROP_Flags2 (MF2_NOTELEPORT)
PROP_RenderStyle (STYLE_Add)
PROP_SpawnState (S_WIZFX1)
PROP_DeathState (S_WIZFXI1)
END_DEFAULTS
AT_SPEED_SET (WizardFX1, speed)
{
SimpleSpeedSetter (AWizardFX1, 18*FRACUNIT, 24*FRACUNIT, speed);
}
// --- Action functions -----------------------------------------------------
//----------------------------------------------------------------------------
//
// PROC A_GhostOff
@ -191,10 +71,11 @@ void A_WizAtk3 (AActor *actor)
P_TraceBleed (damage, actor->target, actor);
return;
}
mo = P_SpawnMissile (actor, actor->target, RUNTIME_CLASS(AWizardFX1));
const PClass *fx = PClass::FindClass("WizardFX1");
mo = P_SpawnMissile (actor, actor->target, fx);
if (mo != NULL)
{
P_SpawnMissileAngle(actor, RUNTIME_CLASS(AWizardFX1), mo->angle-(ANG45/8), mo->momz);
P_SpawnMissileAngle(actor, RUNTIME_CLASS(AWizardFX1), mo->angle+(ANG45/8), mo->momz);
P_SpawnMissileAngle(actor, fx, mo->angle-(ANG45/8), mo->momz);
P_SpawnMissileAngle(actor, fx, mo->angle+(ANG45/8), mo->momz);
}
}

View file

@ -151,12 +151,15 @@ bool P_MorphPlayer (player_t *activator, player_t *p, const PClass *spawntype, i
// taking events, set up the face, if any;
// this is only needed for old-skool skins
// and for the original DOOM status bar.
if ((p == &players[consoleplayer]) &&
(strcmp(spawntype->Meta.GetMetaString (APMETA_Face), "None") != 0))
if (p == &players[consoleplayer])
{
StatusBar->SetFace(&skins[p->MorphedPlayerClass]);
}
const char *face = spawntype->Meta.GetMetaString (APMETA_Face);
if (face != NULL && strcmp(face, "None") != 0)
{
StatusBar->SetFace(&skins[p->MorphedPlayerClass]);
}
}
return true;
}

View file

@ -287,6 +287,10 @@ static void ParseActionDef (FScanner &sc, PClass *cls)
static FActorInfo *CreateNewActor(FScanner &sc, FActorInfo **parentc, Baggage *bag)
{
FName typeName;
const PClass *replacee = NULL;
int DoomEdNum = -1;
PClass *ti = NULL;
FActorInfo *info = NULL;
// Get actor name
sc.MustGetString();
@ -339,10 +343,14 @@ static FActorInfo *CreateNewActor(FScanner &sc, FActorInfo **parentc, Baggage *b
{
sc.ScriptError ("Parent type '%s' not found", colon);
}
else if (parent->ActorInfo == NULL)
else if (!parent->IsDescendantOf(RUNTIME_CLASS(AActor)))
{
sc.ScriptError ("Parent type '%s' is not an actor", colon);
}
else if (parent->ActorInfo == NULL)
{
sc.ScriptError ("uninitialized parent type '%s'", colon);
}
else
{
*parentc = parent->ActorInfo;
@ -351,8 +359,57 @@ static FActorInfo *CreateNewActor(FScanner &sc, FActorInfo **parentc, Baggage *b
else sc.UnGet();
}
PClass *ti = parent->CreateDerivedClass (typeName, parent->Size);
FActorInfo *info = ti->ActorInfo;
// Check for "replaces"
if (sc.CheckString ("replaces"))
{
// Get actor name
sc.MustGetString ();
replacee = PClass::FindClass (sc.String);
if (replacee == NULL)
{
sc.ScriptError ("Replaced type '%s' not found", sc.String);
}
else if (replacee->ActorInfo == NULL)
{
sc.ScriptError ("Replaced type '%s' is not an actor", sc.String);
}
}
// Now, after the actor names have been parsed, it is time to switch to C-mode
// for the rest of the actor definition.
sc.SetCMode (true);
if (sc.CheckNumber())
{
if (sc.Number>=-1 && sc.Number<32768) DoomEdNum = sc.Number;
else sc.ScriptError ("DoomEdNum must be in the range [-1,32767]");
}
if (sc.CheckString("native"))
{
ti = (PClass*)PClass::FindClass(typeName);
if (ti == NULL)
{
sc.ScriptError("Unknown native class '%s'", typeName.GetChars());
}
else if (ti->ParentClass != parent)
{
sc.ScriptError("Native class '%s' does not inherit from '%s'",
typeName.GetChars(),parent->TypeName.GetChars());
}
else if (ti->ActorInfo != NULL)
{
sc.ScriptMessage("Redefinition of internal class '%s'", typeName.GetChars());
}
ti->InitializeActorInfo();
info = ti->ActorInfo;
}
else
{
ti = parent->CreateDerivedClass (typeName, parent->Size);
info = ti->ActorInfo;
}
MakeStateDefines(parent->ActorInfo->StateList);
@ -373,40 +430,14 @@ static FActorInfo *CreateNewActor(FScanner &sc, FActorInfo **parentc, Baggage *b
*info->PainChances = *parent->ActorInfo->PainChances;
}
// Check for "replaces"
sc.MustGetString ();
if (sc.Compare ("replaces"))
if (replacee != NULL)
{
const PClass *replacee;
// Get actor name
sc.MustGetString ();
replacee = PClass::FindClass (sc.String);
if (replacee == NULL)
{
sc.ScriptError ("Replaced type '%s' not found", sc.String);
}
else if (replacee->ActorInfo == NULL)
{
sc.ScriptError ("Replaced type '%s' is not an actor", sc.String);
}
replacee->ActorInfo->Replacement = ti->ActorInfo;
ti->ActorInfo->Replacee = replacee->ActorInfo;
}
else
{
sc.UnGet();
}
// Now, after the actor names have been parsed, it is time to switch to C-mode
// for the rest of the actor definition.
sc.SetCMode (true);
if (sc.CheckNumber())
{
if (sc.Number>=-1 && sc.Number<32768) info->DoomEdNum = sc.Number;
else sc.ScriptError ("DoomEdNum must be in the range [-1,32767]");
}
info->DoomEdNum = DoomEdNum;
if (parent == RUNTIME_CLASS(AWeapon))
{
// preinitialize kickback to the default for the game

View file

@ -172,6 +172,7 @@ static flagdef ActorFlags[]=
DEFINE_FLAG(MF3, DONTOVERLAP, AActor, flags3),
DEFINE_FLAG(MF3, DONTMORPH, AActor, flags3),
DEFINE_FLAG(MF3, DONTSQUASH, AActor, flags3),
DEFINE_FLAG(MF3, EXPLOCOUNT, AActor, flags3),
DEFINE_FLAG(MF3, FULLVOLACTIVE, AActor, flags3),
DEFINE_FLAG(MF3, ISMONSTER, AActor, flags3),
DEFINE_FLAG(MF3, SKYEXPLODE, AActor, flags3),