- Converted Ettin and Centaur to DECORATE.

- Made the Ettin's and Centaur's howling sound an actor property.
- Added A_CustomComboAttack function to finally have something that can
  replace the old A_ComboAttack function.
- Added A_SpawnItemEx function that removes the problems with A_SpawnItem
  and which also should make most of the A_CustomMissile abuse unnecessary.
- Added A_QueueCorpse to the list of DECORATE code pointers.
- Made the size of Hexen's corpse queue configurable by CVAR
  (sv_corpsequeuesize.) Setting this CVAR to -1 will disable corpse 
  queuing completely so that even in Hexen all corpses will stay forever.


SVN r392 (trunk)
This commit is contained in:
Christoph Oelckers 2006-11-27 00:01:30 +00:00
parent d840d9b68a
commit a90ba9deb6
20 changed files with 648 additions and 701 deletions

View file

@ -1,4 +1,14 @@
November 26, 2006 (Changes by Graf Zahl)
- Converted Ettin and Centaur to DECORATE.
- Made the Ettin's and Centaur's howling sound an actor property.
- Added A_CustomComboAttack function to finally have something that can
replace the old A_ComboAttack function.
- Added A_SpawnItemEx function that removes the problems with A_SpawnItem
and which also should make most of the A_CustomMissile abuse unnecessary.
- Added A_QueueCorpse to the list of DECORATE code pointers.
- Made the size of Hexen's corpse queue configurable by CVAR
(sv_corpsequeuesize.) Setting this CVAR to -1 will disable corpse
queuing completely so that even in Hexen all corpses will stay forever.
- Added random2 function to DECORATE's expression evaluator. This is to
better emulate some calculation of internal code pointers.
- Added named RNG support to DECORATE's expression evaluator. Just use

View file

@ -418,6 +418,7 @@ enum
AMETA_FastSpeed, // Speed in fast mode
AMETA_RDFactor, // Radius damage factor
AMETA_CameraHeight, // Height of camera when used as such
AMETA_HowlSound, // Sound being played when electrocuted or poisoned
};
// Map Object definition.
@ -476,7 +477,8 @@ public:
virtual int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype);
// Centaurs and ettins squeal when electrocuted, poisoned, or "holy"-ed
virtual void Howl ();
// Made a metadata property so no longer virtual
void Howl ();
// Called by A_NoBlocking in case the actor wants to drop some presents
virtual void NoBlockingSet ();
@ -504,9 +506,6 @@ public:
// Called by RoughBlockCheck
virtual bool IsOkayToAttack (AActor *target);
virtual void ChangeSpecial (int special, int data1, int data2,
int data3, int data4, int data5);
// Plays the actor's ActiveSound if its voice isn't already making noise.
void PlayActiveSound ();

View file

@ -1,326 +1,10 @@
#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"
#include "a_hexenglobal.h"
static FRandom pr_centaurdefend ("CentaurDefend");
static FRandom pr_reflect ("CentaurDeflect");
static FRandom pr_centaurattack ("CentaurAttack");
static FRandom pr_centaurdrop ("CentaurDrop");
void A_CentaurDefend (AActor *);
void A_CentaurAttack (AActor *);
void A_CentaurAttack2 (AActor *);
void A_CentaurDropStuff (AActor *);
// Centaur ------------------------------------------------------------------
FState ACentaur::States[] =
{
#define S_CENTAUR_LOOK1 0
S_NORMAL (CENT, 'A', 10, A_Look , &States[S_CENTAUR_LOOK1+1]),
S_NORMAL (CENT, 'B', 10, A_Look , &States[S_CENTAUR_LOOK1]),
#define S_CENTAUR_WALK1 (S_CENTAUR_LOOK1+2)
S_NORMAL (CENT, 'A', 4, A_Chase , &States[S_CENTAUR_WALK1+1]),
S_NORMAL (CENT, 'B', 4, A_Chase , &States[S_CENTAUR_WALK1+2]),
S_NORMAL (CENT, 'C', 4, A_Chase , &States[S_CENTAUR_WALK1+3]),
S_NORMAL (CENT, 'D', 4, A_Chase , &States[S_CENTAUR_WALK1]),
#define S_CENTAUR_PAIN1 (S_CENTAUR_WALK1+4)
S_NORMAL (CENT, 'G', 6, A_Pain , &States[S_CENTAUR_PAIN1+1]),
S_NORMAL (CENT, 'G', 6, A_SetReflectiveInvulnerable, &States[S_CENTAUR_PAIN1+2]),
S_NORMAL (CENT, 'E', 15, A_CentaurDefend , &States[S_CENTAUR_PAIN1+3]),
S_NORMAL (CENT, 'E', 15, A_CentaurDefend , &States[S_CENTAUR_PAIN1+4]),
S_NORMAL (CENT, 'E', 15, A_CentaurDefend , &States[S_CENTAUR_PAIN1+5]),
S_NORMAL (CENT, 'E', 1, A_UnSetReflectiveInvulnerable, &States[S_CENTAUR_WALK1]),
#define S_CENTAUR_ATK1 (S_CENTAUR_PAIN1+6)
S_NORMAL (CENT, 'H', 5, A_FaceTarget , &States[S_CENTAUR_ATK1+1]),
S_NORMAL (CENT, 'I', 4, A_FaceTarget , &States[S_CENTAUR_ATK1+2]),
S_NORMAL (CENT, 'J', 7, A_CentaurAttack , &States[S_CENTAUR_WALK1]),
#define S_CENTAUR_MISSILE1 (S_CENTAUR_ATK1+3)
S_NORMAL (CENT, 'E', 10, A_FaceTarget , &States[S_CENTAUR_MISSILE1+1]),
S_BRIGHT (CENT, 'F', 8, A_CentaurAttack2 , &States[S_CENTAUR_MISSILE1+2]),
S_NORMAL (CENT, 'E', 10, A_FaceTarget , &States[S_CENTAUR_MISSILE1+3]),
S_BRIGHT (CENT, 'F', 8, A_CentaurAttack2 , &States[S_CENTAUR_WALK1]),
#define S_CENTAUR_DEATH1 (S_CENTAUR_MISSILE1+4)
S_NORMAL (CENT, 'K', 4, NULL , &States[S_CENTAUR_DEATH1+1]),
S_NORMAL (CENT, 'L', 4, A_Scream , &States[S_CENTAUR_DEATH1+2]),
S_NORMAL (CENT, 'M', 4, NULL , &States[S_CENTAUR_DEATH1+3]),
S_NORMAL (CENT, 'N', 4, NULL , &States[S_CENTAUR_DEATH1+4]),
S_NORMAL (CENT, 'O', 4, A_NoBlocking , &States[S_CENTAUR_DEATH1+5]),
S_NORMAL (CENT, 'P', 4, NULL , &States[S_CENTAUR_DEATH1+6]),
S_NORMAL (CENT, 'Q', 4, NULL , &States[S_CENTAUR_DEATH1+7]),
S_NORMAL (CENT, 'R', 4, A_QueueCorpse , &States[S_CENTAUR_DEATH1+8]),
S_NORMAL (CENT, 'S', 4, NULL , &States[S_CENTAUR_DEATH1+9]),
S_NORMAL (CENT, 'T', -1, NULL , NULL),
#define S_CENTAUR_DEATH_X1 (S_CENTAUR_DEATH1+10)
S_NORMAL (CTXD, 'A', 4, NULL , &States[S_CENTAUR_DEATH_X1+1]),
S_NORMAL (CTXD, 'B', 4, A_NoBlocking , &States[S_CENTAUR_DEATH_X1+2]),
S_NORMAL (CTXD, 'C', 4, A_CentaurDropStuff , &States[S_CENTAUR_DEATH_X1+3]),
S_NORMAL (CTXD, 'D', 3, A_Scream , &States[S_CENTAUR_DEATH_X1+4]),
S_NORMAL (CTXD, 'E', 4, A_QueueCorpse , &States[S_CENTAUR_DEATH_X1+5]),
S_NORMAL (CTXD, 'F', 3, NULL , &States[S_CENTAUR_DEATH_X1+6]),
S_NORMAL (CTXD, 'G', 4, NULL , &States[S_CENTAUR_DEATH_X1+7]),
S_NORMAL (CTXD, 'H', 3, NULL , &States[S_CENTAUR_DEATH_X1+8]),
S_NORMAL (CTXD, 'I', 4, NULL , &States[S_CENTAUR_DEATH_X1+9]),
S_NORMAL (CTXD, 'J', 3, NULL , &States[S_CENTAUR_DEATH_X1+10]),
S_NORMAL (CTXD, 'K', -1, NULL , NULL),
#define S_CENTAUR_ICE1 (S_CENTAUR_DEATH_X1+11)
S_NORMAL (CENT, 'U', 5, A_FreezeDeath , &States[S_CENTAUR_ICE1+1]),
S_NORMAL (CENT, 'U', 1, A_FreezeDeathChunks , &States[S_CENTAUR_ICE1+1]),
};
IMPLEMENT_ACTOR (ACentaur, Hexen, 107, 1)
PROP_SpawnHealth (200)
PROP_PainChance (135)
PROP_SpeedFixed (13)
PROP_HeightFixed (64)
PROP_Mass (120)
PROP_Flags (MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL)
PROP_Flags2 (MF2_FLOORCLIP|MF2_PASSMOBJ|MF2_TELESTOMP|MF2_PUSHWALL|MF2_MCROSS)
PROP_Flags4 (MF4_SHIELDREFLECT)
PROP_SpawnState (S_CENTAUR_LOOK1)
PROP_SeeState (S_CENTAUR_WALK1)
PROP_PainState (S_CENTAUR_PAIN1)
PROP_MeleeState (S_CENTAUR_ATK1)
PROP_DeathState (S_CENTAUR_DEATH1)
PROP_XDeathState (S_CENTAUR_DEATH_X1)
PROP_IDeathState (S_CENTAUR_ICE1)
PROP_SeeSound ("CentaurSight")
PROP_AttackSound ("CentaurAttack")
PROP_PainSound ("CentaurPain")
PROP_DeathSound ("CentaurDeath")
PROP_ActiveSound ("CentaurActive")
END_DEFAULTS
void ACentaur::Howl ()
{
int howl = S_FindSound ("PuppyBeat");
if (!S_GetSoundPlayingInfo (this, howl))
{
S_SoundID (this, CHAN_BODY, howl, 1, ATTN_NORM);
}
}
// Centaur Leader -----------------------------------------------------------
class ACentaurLeader : public ACentaur
{
DECLARE_STATELESS_ACTOR (ACentaurLeader, ACentaur)
};
IMPLEMENT_STATELESS_ACTOR (ACentaurLeader, Hexen, 115, 2)
PROP_SpawnHealth (250)
PROP_PainChance (96)
PROP_SpeedFixed (10)
PROP_MissileState (S_CENTAUR_MISSILE1)
END_DEFAULTS
// Mashed centaur -----------------------------------------------------------
//
// The mashed centaur is only placed through ACS. Nowhere in the game source
// is it ever referenced.
class ACentaurMash : public ACentaur
{
DECLARE_STATELESS_ACTOR (ACentaurMash, ACentaur)
};
IMPLEMENT_STATELESS_ACTOR (ACentaurMash, Hexen, -1, 103)
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
// Centaur projectile -------------------------------------------------------
class ACentaurFX : public AActor
{
DECLARE_ACTOR (ACentaurFX, AActor)
};
FState ACentaurFX::States[] =
{
#define S_CENTAUR_FX1 0
S_BRIGHT (CTFX, 'A', -1, NULL , NULL),
#define S_CENTAUR_FX_X1 (S_CENTAUR_FX1+1)
S_BRIGHT (CTFX, 'B', 4, NULL , &States[S_CENTAUR_FX_X1+1]),
S_BRIGHT (CTFX, 'C', 3, NULL , &States[S_CENTAUR_FX_X1+2]),
S_BRIGHT (CTFX, 'D', 4, NULL , &States[S_CENTAUR_FX_X1+3]),
S_BRIGHT (CTFX, 'E', 3, NULL , &States[S_CENTAUR_FX_X1+4]),
S_BRIGHT (CTFX, 'F', 2, NULL , NULL),
};
IMPLEMENT_ACTOR (ACentaurFX, Hexen, -1, 0)
PROP_SpeedFixed (20)
PROP_Damage (4)
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_CENTAUR_FX1)
PROP_DeathState (S_CENTAUR_FX_X1)
PROP_DeathSound ("CentaurMissileExplode")
END_DEFAULTS
// Centaur shield (debris) --------------------------------------------------
class ACentaurShield : public AActor
{
DECLARE_ACTOR (ACentaurShield, AActor)
};
FState ACentaurShield::States[] =
{
#define S_CENTAUR_SHIELD1 0
S_NORMAL (CTDP, 'A', 3, NULL , &States[S_CENTAUR_SHIELD1+1]),
S_NORMAL (CTDP, 'B', 3, NULL , &States[S_CENTAUR_SHIELD1+2]),
S_NORMAL (CTDP, 'C', 3, NULL , &States[S_CENTAUR_SHIELD1+3]),
S_NORMAL (CTDP, 'D', 3, NULL , &States[S_CENTAUR_SHIELD1+4]),
S_NORMAL (CTDP, 'E', 3, NULL , &States[S_CENTAUR_SHIELD1+5]),
S_NORMAL (CTDP, 'F', 3, NULL , &States[S_CENTAUR_SHIELD1+2]),
#define S_CENTAUR_SHIELD_X1 (S_CENTAUR_SHIELD1+6)
S_NORMAL (CTDP, 'G', 4, NULL , &States[S_CENTAUR_SHIELD_X1+1]),
S_NORMAL (CTDP, 'H', 4, A_QueueCorpse , &States[S_CENTAUR_SHIELD_X1+2]),
S_NORMAL (CTDP, 'I', 4, NULL , &States[S_CENTAUR_SHIELD_X1+3]),
S_NORMAL (CTDP, 'J', -1, NULL , NULL),
};
IMPLEMENT_ACTOR (ACentaurShield, Hexen, -1, 0)
PROP_Flags (MF_DROPOFF|MF_CORPSE)
PROP_Flags2 (MF2_NOTELEPORT)
PROP_SpawnState (S_CENTAUR_SHIELD1)
PROP_CrashState (S_CENTAUR_SHIELD_X1)
END_DEFAULTS
// Centaur sword (debris) ---------------------------------------------------
class ACentaurSword : public AActor
{
DECLARE_ACTOR (ACentaurSword, AActor)
};
FState ACentaurSword::States[] =
{
#define S_CENTAUR_SWORD1 0
S_NORMAL (CTDP, 'K', 3, NULL , &States[S_CENTAUR_SWORD1+1]),
S_NORMAL (CTDP, 'L', 3, NULL , &States[S_CENTAUR_SWORD1+2]),
S_NORMAL (CTDP, 'M', 3, NULL , &States[S_CENTAUR_SWORD1+3]),
S_NORMAL (CTDP, 'N', 3, NULL , &States[S_CENTAUR_SWORD1+4]),
S_NORMAL (CTDP, 'O', 3, NULL , &States[S_CENTAUR_SWORD1+5]),
S_NORMAL (CTDP, 'P', 3, NULL , &States[S_CENTAUR_SWORD1+6]),
S_NORMAL (CTDP, 'Q', 3, NULL , &States[S_CENTAUR_SWORD1+2]),
#define S_CENTAUR_SWORD_X1 (S_CENTAUR_SWORD1+7)
S_NORMAL (CTDP, 'R', 4, NULL , &States[S_CENTAUR_SWORD_X1+1]),
S_NORMAL (CTDP, 'S', 4, A_QueueCorpse , &States[S_CENTAUR_SWORD_X1+2]),
S_NORMAL (CTDP, 'T', -1, NULL , NULL),
};
IMPLEMENT_ACTOR (ACentaurSword, Hexen, -1, 0)
PROP_Flags (MF_DROPOFF|MF_CORPSE)
PROP_Flags2 (MF2_NOTELEPORT)
PROP_SpawnState (S_CENTAUR_SWORD1)
PROP_CrashState (S_CENTAUR_SWORD_X1)
END_DEFAULTS
//============================================================================
//
// A_CentaurAttack
//
//============================================================================
void A_CentaurAttack (AActor *actor)
{
if (!actor->target)
{
return;
}
if (actor->CheckMeleeRange ())
{
int damage = pr_centaurattack()%7+3;
P_DamageMobj (actor->target, actor, actor, damage, NAME_Melee);
P_TraceBleed (damage, actor->target, actor);
}
}
//============================================================================
//
// A_CentaurAttack2
//
//============================================================================
void A_CentaurAttack2 (AActor *actor)
{
if (!actor->target)
{
return;
}
P_SpawnMissileZ (actor, actor->z + 45*FRACUNIT,
actor->target, RUNTIME_CLASS(ACentaurFX));
S_Sound (actor, CHAN_WEAPON, "CentaurLeaderAttack", 1, ATTN_NORM);
}
//============================================================================
//
// A_CentaurDropStuff
//
// Spawn shield/sword sprites when the centaur pulps
//============================================================================
void A_CentaurDropStuff (AActor *actor)
{
const PClass *const DropTypes[] =
{
RUNTIME_CLASS(ACentaurSword),
RUNTIME_CLASS(ACentaurShield)
};
for (int i = countof(DropTypes)-1; i >= 0; --i)
{
AActor *mo;
mo = Spawn (DropTypes[i], actor->x, actor->y, actor->z+45*FRACUNIT, ALLOW_REPLACE);
if (mo)
{
angle_t angle = actor->angle + (i ? ANGLE_90 : ANGLE_270);
mo->momz = FRACUNIT*8+(pr_centaurdrop()<<10);
mo->momx = FixedMul(((pr_centaurdrop()-128)<<11)+FRACUNIT,
finecosine[angle>>ANGLETOFINESHIFT]);
mo->momy = FixedMul(((pr_centaurdrop()-128)<<11)+FRACUNIT,
finesine[angle>>ANGLETOFINESHIFT]);
mo->target = actor;
}
}
}
//============================================================================
//
// A_CentaurDefend

View file

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

View file

@ -52,13 +52,6 @@ public:
void BeginPlay ();
};
class ACentaur : public AActor
{
DECLARE_ACTOR (ACentaur, AActor)
public:
void Howl ();
};
class AFourthWeaponPiece : public AInventory
{
DECLARE_STATELESS_ACTOR (AFourthWeaponPiece, AInventory)

View file

@ -683,10 +683,6 @@ AActor *P_SpawnKoraxMissile (fixed_t x, fixed_t y, fixed_t z,
z -= source->floorclip;
th = Spawn (type, x, y, z, ALLOW_REPLACE);
if (th->SeeSound)
{
S_SoundID (th, CHAN_BODY, th->SeeSound, 1, ATTN_NORM);
}
th->target = source; // Originator
an = R_PointToAngle2(x, y, dest->x, dest->y);
if (dest->flags & MF_SHADOW)

View file

@ -130,7 +130,11 @@ int ALightning::SpecialMissileHit (AActor *thing)
if ((!thing->player && !(thing->flags2&MF2_BOSS))
|| !(level.time&1))
{
if (thing->IsKindOf(RUNTIME_CLASS(ACentaur)))
// There needs to be a better way to do this...
static const PClass *centaur=NULL;
if (!centaur) centaur = PClass::FindClass("Centaur");
if (thing->IsKindOf(centaur))
{ // Lightning does more damage to centaurs
P_DamageMobj(thing, this, target, 9, NAME_Electric);
}

View file

@ -321,7 +321,6 @@ void A_FreezeDeathChunks (AActor *actor)
//----------------------------------------------------------------------------
// Corpse queue for monsters - this should be saved out
#define CORPSEQUEUESIZE 64
class DCorpsePointer : public DThinker
{
@ -341,6 +340,22 @@ IMPLEMENT_POINTY_CLASS(DCorpsePointer)
DECLARE_POINTER(Corpse)
END_POINTERS
CUSTOM_CVAR(Int, sv_corpsequeuesize, 64, CVAR_ARCHIVE|CVAR_SERVERINFO)
{
if (self > 0)
{
TThinkerIterator<DCorpsePointer> iterator (STAT_CORPSEPOINTER);
DCorpsePointer *first = iterator.Next ();
while (first != NULL && first->Count > (DWORD)self)
{
DCorpsePointer *next = iterator.Next ();
next->Count = first->Count;
first->Destroy ();
first = next;
}
}
}
DCorpsePointer::DCorpsePointer (AActor *ptr)
: DThinker (STAT_CORPSEPOINTER), Corpse (ptr)
@ -354,7 +369,7 @@ DCorpsePointer::DCorpsePointer (AActor *ptr)
if (first != this)
{
if (first->Count >= CORPSEQUEUESIZE)
if (first->Count >= (DWORD)sv_corpsequeuesize)
{
DCorpsePointer *next = iterator.Next ();
next->Count = first->Count;
@ -399,6 +414,7 @@ void DCorpsePointer::Serialize (FArchive &arc)
// throw another corpse on the queue
void A_QueueCorpse (AActor *actor)
{
if (sv_corpsequeuesize > 0)
new DCorpsePointer (actor);
}

View file

@ -2319,6 +2319,11 @@ int AActor::GetMissileDamage (int mask, int add)
void AActor::Howl ()
{
int howl = GetClass()->Meta.GetMetaInt(AMETA_HowlSound);
if (!S_GetSoundPlayingInfo (this, howl))
{
S_SoundID (this, CHAN_BODY, howl, 1, ATTN_NORM);
}
}
void AActor::NoBlockingSet ()
@ -2433,17 +2438,6 @@ bool AActor::IsOkayToAttack (AActor *link)
return false;
}
void AActor::ChangeSpecial (int special, int data1, int data2,
int data3, int data4, int data5)
{
this->special = special;
args[0] = data1;
args[1] = data2;
args[2] = data3;
args[3] = data4;
args[4] = data5;
}
void AActor::SetShade (DWORD rgb)
{
PalEntry *entry = (PalEntry *)&rgb;

View file

@ -140,6 +140,9 @@ static int DoomSpecificInfo (char *buffer, char *end)
int main (int argc, char **argv)
{
printf("ZDoom v%s - SVN revision %s - SDL version\nCompiled on %s\n\n",
DOTVERSIONSTR_NOREV,SVN_REVISION_STRING,__DATE__);
{
int s[4] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS };
cc_install_handlers(4, s, "zdoom-crash.log", DoomSpecificInfo);

View file

@ -348,7 +348,7 @@ int I_PickIWad (WadStuff *wads, int numwads, bool queryiwad, int defaultiwad)
{
int i;
printf ("Please select a game wad:\n");
printf ("Please select a game wad (or 0 to exit):\n");
for (i = 0; i < numwads; ++i)
{
const char *filepart = strrchr (wads[i].Path, '/');

View file

@ -132,6 +132,7 @@ static flagdef ActorFlags[]=
DEFINE_FLAG2(MF2_LOGRAV, LOWGRAVITY, AActor, flags2),
DEFINE_FLAG(MF2, WINDTHRUST, AActor, flags2),
DEFINE_FLAG(MF2, HERETICBOUNCE , AActor, flags2),
DEFINE_FLAG(MF2, BLASTED, AActor, flags2),
DEFINE_FLAG(MF2, FLOORCLIP, AActor, flags2),
DEFINE_FLAG(MF2, SPAWNFLOAT, AActor, flags2),
DEFINE_FLAG(MF2, NOTELEPORT, AActor, flags2),
@ -477,6 +478,7 @@ ACTOR(LightInverse)
ACTOR(GiveInventory)
ACTOR(TakeInventory)
ACTOR(SpawnItem)
ACTOR(SpawnItemEx)
ACTOR(ThrowGrenade)
ACTOR(Recoil)
ACTOR(SelectWeapon)
@ -506,6 +508,7 @@ ACTOR(TakeFromTarget)
ACTOR(JumpIfInTargetInventory)
ACTOR(CountdownArg)
ACTOR(CustomMeleeAttack)
ACTOR(CustomComboAttack)
ACTOR(Light)
ACTOR(Burst)
ACTOR(SkullPop)
@ -517,6 +520,7 @@ ACTOR(SPosAttackUseAtkSound)
ACTOR(Respawn)
ACTOR(BarrelDestroy)
ACTOR(PlayerSkinCheck)
ACTOR(QueueCorpse)
#include "d_dehackedactions.h"
@ -697,6 +701,7 @@ AFuncDesc AFTable[]=
FUNC(A_GiveInventory, "Mx" )
FUNC(A_TakeInventory, "Mx" )
FUNC(A_SpawnItem, "Mxxyx" )
FUNC(A_SpawnItemEx, "Mxxxxxxxx" )
FUNC(A_ThrowGrenade, "Mxxxy" )
FUNC(A_SelectWeapon, "M")
FUNC(A_Print, "Txt")
@ -728,12 +733,14 @@ AFuncDesc AFTable[]=
FUNC(A_TakeFromTarget, "Mx" )
FUNC(A_CountdownArg, "X")
FUNC(A_CustomMeleeAttack, "Xssty" )
FUNC(A_CustomComboAttack, "MXXsty" )
FUNC(A_Burst, "M")
FUNC(A_RadiusThrust, "xxy")
{"A_Explode", A_ExplodeParms, "xxy" },
FUNC(A_Stop, NULL)
FUNC(A_Respawn, "y")
FUNC(A_BarrelDestroy, NULL)
FUNC(A_QueueCorpse, NULL)
};
//==========================================================================
@ -2819,6 +2826,15 @@ static void ActorActiveSound (AActor *defaults, Baggage &bag)
defaults->ActiveSound=S_FindSound(sc_String);
}
//==========================================================================
//
//==========================================================================
static void ActorHowlSound (AActor *defaults, Baggage &bag)
{
SC_MustGetString();
bag.Info->Class->Meta.SetMetaInt (AMETA_HowlSound, S_FindSound(sc_String));
}
//==========================================================================
//
//==========================================================================
@ -4138,6 +4154,7 @@ static const ActorProps props[] =
{ "health.lowmessage", (apf)HealthLowMessage, RUNTIME_CLASS(AHealth) },
{ "height", ActorHeight, RUNTIME_CLASS(AActor) },
{ "hitobituary", ActorHitObituary, RUNTIME_CLASS(AActor) },
{ "howlsound", ActorHowlSound, RUNTIME_CLASS(AActor) },
{ "ice", ActorIceState, RUNTIME_CLASS(AActor) },
{ "inventory.amount", (apf)InventoryAmount, RUNTIME_CLASS(AInventory) },
{ "inventory.defmaxamount", (apf)InventoryDefMaxAmount, RUNTIME_CLASS(AInventory) },

View file

@ -844,6 +844,63 @@ void A_CustomMeleeAttack (AActor *self)
}
}
//==========================================================================
//
// A fully customizable combo attack
//
//==========================================================================
void A_CustomComboAttack (AActor *self)
{
int index=CheckIndex(6);
if (index<0) return;
ENamedName MissileName=(ENamedName)StateParameters[index];
fixed_t SpawnHeight=fixed_t(EvalExpressionF (StateParameters[index+1], self) * FRACUNIT);
int damage = EvalExpressionI (StateParameters[index+2], self);
int MeleeSound = StateParameters[index+3];
ENamedName DamageType = (ENamedName)StateParameters[index+4];
bool bleed = EvalExpressionN (StateParameters[index+5], self);
if (!self->target)
return;
A_FaceTarget (self);
if (self->CheckMeleeRange ())
{
if (DamageType==NAME_None) DamageType = NAME_Melee; // Melee is the default type
if (MeleeSound) S_SoundID (self, CHAN_WEAPON, MeleeSound, 1, ATTN_NORM);
P_DamageMobj (self->target, self, self, damage, DamageType);
if (bleed) P_TraceBleed (damage, self->target, self);
}
else
{
const PClass * ti=PClass::FindClass(MissileName);
if (ti)
{
// Although there is a P_SpawnMissileZ function its
// aiming is much too bad to be of any use
self->z+=SpawnHeight-32*FRACUNIT;
AActor * missile = P_SpawnMissile (self, self->target, ti);
self->z-=SpawnHeight-32*FRACUNIT;
if (missile)
{
// automatic handling of seeker missiles
if (missile->flags2&MF2_SEEKERMISSILE)
{
missile->tracer=self->target;
}
// set the health value so that the missile works properly
if (missile->flags4&MF4_SPECTRAL)
{
missile->health=-2;
}
}
}
}
}
//==========================================================================
//
// State jump function
@ -1228,6 +1285,71 @@ void A_TakeFromTarget(AActor * self)
DoTakeInventory(self, self->target);
}
//===========================================================================
//
// Common code for A_SpawnItem and A_SpawnItemEx
//
//===========================================================================
static void InitSpawnedItem(AActor *self, AActor *mo, INTBOOL transfer_translation, INTBOOL setmaster)
{
if (mo)
{
AActor * originator = self;
if (transfer_translation)
{
mo->Translation = self->Translation;
}
mo->angle=self->angle;
while (originator && isMissile(originator)) originator = originator->target;
if (mo->flags3&MF3_ISMONSTER)
{
if (!P_TestMobjLocation(mo))
{
// The monster is blocked so don't spawn it at all!
if (mo->CountsAsKill()) level.total_monsters--;
mo->Destroy();
if (pStateCall != NULL) pStateCall->Result=false; // for an inventory iten's use state
return;
}
else if (originator)
{
if (originator->flags3&MF3_ISMONSTER)
{
// If this is a monster transfer all friendliness information
mo->CopyFriendliness(originator, true);
if (setmaster) mo->master = originator; // don't let it attack you (optional)!
}
else if (originator->player)
{
// A player always spawns a monster friendly to him
mo->flags|=MF_FRIENDLY;
mo->FriendPlayer = originator->player-players+1;
AActor * attacker=originator->player->attacker;
if (attacker)
{
if (!(attacker->flags&MF_FRIENDLY) ||
(deathmatch && attacker->FriendPlayer!=0 && attacker->FriendPlayer!=mo->FriendPlayer))
{
// Target the monster which last attacked the player
mo->target = attacker;
}
}
}
}
}
else
{
// If this is a missile or something else set the target to the originator
mo->target=originator? originator : self;
}
}
}
//===========================================================================
//
// A_SpawnItem
@ -1235,6 +1357,7 @@ void A_TakeFromTarget(AActor * self)
// Spawns an item in front of the caller like Heretic's time bomb
//
//===========================================================================
void A_SpawnItem(AActor * self)
{
FState * CallingState;
@ -1276,60 +1399,88 @@ void A_SpawnItem(AActor * self)
self->y + FixedMul(distance, finesine[self->angle>>ANGLETOFINESHIFT]),
self->z - self->floorclip + zheight, ALLOW_REPLACE);
if (mo)
{
AActor * originator = self;
if (transfer_translation)
{
mo->Translation = self->Translation;
InitSpawnedItem(self, mo, transfer_translation, useammo);
}
mo->angle=self->angle;
while (originator && isMissile(originator)) originator = originator->target;
//===========================================================================
//
// A_SpawnItemEx
//
// Enhanced spawning function
//
//===========================================================================
enum SIX_Flags
{
SIXF_TRANSFERTRANSLATION=1,
SIXF_ABSOLUTEPOSITION=2,
SIXF_ABSOLUTEANGLE=4,
SIXF_ABSOLUTEMOMENTUM=8,
SIXF_SETMASTER=16
};
if (mo->flags3&MF3_ISMONSTER)
void A_SpawnItemEx(AActor * self)
{
if (!P_TestMobjLocation(mo))
FState * CallingState;
int index=CheckIndex(9, &CallingState);
if (index<0) return;
const PClass * missile= PClass::FindClass((ENamedName)StateParameters[index]);
fixed_t xofs = fixed_t(EvalExpressionF (StateParameters[index+1], self) * FRACUNIT);
fixed_t yofs = fixed_t(EvalExpressionF (StateParameters[index+2], self) * FRACUNIT);
fixed_t zofs = fixed_t(EvalExpressionF (StateParameters[index+3], self) * FRACUNIT);
fixed_t xmom = fixed_t(EvalExpressionF (StateParameters[index+4], self) * FRACUNIT);
fixed_t ymom = fixed_t(EvalExpressionF (StateParameters[index+5], self) * FRACUNIT);
fixed_t zmom = fixed_t(EvalExpressionF (StateParameters[index+6], self) * FRACUNIT);
angle_t Angle= angle_t(EvalExpressionF (StateParameters[index+7], self) * ANGLE_1);
int flags = EvalExpressionI (StateParameters[index+8], self);
if (!missile)
{
// The monster is blocked so don't spawn it at all!
if (mo->CountsAsKill()) level.total_monsters--;
mo->Destroy();
if (pStateCall != NULL) pStateCall->Result=false; // for an inventory iten's use state
if (pStateCall != NULL) pStateCall->Result=false;
return;
}
else if (originator)
{
if (originator->flags3&MF3_ISMONSTER)
{
// If this is a monster transfer all friendliness information
mo->CopyFriendliness(originator, true);
if (useammo) mo->master = originator; // don't let it attack you (optional)!
}
else if (originator->player)
{
// A player always spawns a monster friendly to him
mo->flags|=MF_FRIENDLY;
mo->FriendPlayer = originator->player-players+1;
AActor * attacker=originator->player->attacker;
if (attacker)
// Don't spawn monsters if this actor has been massacred
if (self->DamageType == NAME_Massacre && GetDefaultByType(missile)->flags3&MF3_ISMONSTER) return;
fixed_t x,y,z;
if (!(flags & SIXF_ABSOLUTEANGLE))
{
if (!(attacker->flags&MF_FRIENDLY) ||
(deathmatch && attacker->FriendPlayer!=0 && attacker->FriendPlayer!=mo->FriendPlayer))
Angle += self->angle;
}
angle_t ang = Angle >> ANGLETOFINESHIFT;
if (flags & SIXF_ABSOLUTEPOSITION)
{
// Target the monster which last attacked the player
mo->target = attacker;
}
}
}
}
x = self->x + xofs;
y = self->y + yofs;
}
else
{
// If this is a missile or something else set the target to the originator
mo->target=originator? originator : self;
// in relative mode negative y values mean 'left' and positive ones mean 'right'
// This is the inverse orientation of the absolute mode!
x = self->x + FixedMul(xofs, finecosine[ang]) + FixedMul(yofs, finesine[ang]);
y = self->y + FixedMul(xofs, finesine[ang]) - FixedMul(yofs, finecosine[ang]);
}
if (!(flags & SIXF_ABSOLUTEMOMENTUM))
{
// Same orientation issue here!
fixed_t newxmom = FixedMul(xmom, finecosine[ang]) + FixedMul(ymom, finesine[ang]);
ymom = FixedMul(xmom, finesine[ang]) - FixedMul(ymom, finecosine[ang]);
xmom = newxmom;
}
AActor * mo = Spawn( missile, x, y, self->z + self->floorclip + zofs, ALLOW_REPLACE);
InitSpawnedItem(self, mo, (flags & SIXF_TRANSFERTRANSLATION), (flags&SIXF_SETMASTER));
if (mo)
{
mo->momx=xmom;
mo->momy=ymom;
mo->momz=zmom;
mo->angle=Angle;
}
}

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Version="8,00"
Name="updaterevision"
ProjectGUID="{6077B7D6-349F-4077-B552-3BC302EF5859}"
RootNamespace="updaterevision"
@ -27,7 +27,7 @@
>
<Tool
Name="VCPreBuildEventTool"
CommandLine="echo ------------------- VERY IMPORTANT: --------------------&#x0D;&#x0A;echo You must copy the mt.exe from&#x0D;&#x0A;echo $(VSINSTALLDIR)\Common7\Tools\bin&#x0D;&#x0A;echo on top of the version in&#x0D;&#x0A;echo $(VSINSTALLDIR)\VC\bin&#x0D;&#x0A;echo or your computer may restart while building."
CommandLine="echo ------------------- VERY IMPORTANT: --------------------&#x0D;&#x0A;echo You must copy the mt.exe from&#x0D;&#x0A;echo $(VSINSTALLDIR)\Common7\Tools\bin&#x0D;&#x0A;echo on top of the version in&#x0D;&#x0A;echo $(VSINSTALLDIR)\VC\bin&#x0D;&#x0A;echo or your computer may restart while building.&#x0D;&#x0A;"
/>
<Tool
Name="VCCustomBuildTool"
@ -96,6 +96,83 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
CommandLine="echo ------------------- VERY IMPORTANT: --------------------&#x0D;&#x0A;echo You must copy the mt.exe from&#x0D;&#x0A;echo $(VSINSTALLDIR)\Common7\Tools\bin&#x0D;&#x0A;echo on top of the version in&#x0D;&#x0A;echo $(VSINSTALLDIR)\VC\bin&#x0D;&#x0A;echo or your computer may restart while building.&#x0D;&#x0A;"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
AdditionalManifestFiles="$(InputDir)trustinfo.txt"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
@ -172,83 +249,6 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
CommandLine="echo ------------------- VERY IMPORTANT: --------------------&#x0D;&#x0A;echo You must copy the mt.exe from&#x0D;&#x0A;echo $(VSINSTALLDIR)\Common7\Tools\bin&#x0D;&#x0A;echo on top of the version in&#x0D;&#x0A;echo $(VSINSTALLDIR)\VC\bin&#x0D;&#x0A;echo or your computer may restart while building."
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
AdditionalManifestFiles="$(InputDir)trustinfo.txt"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"

View file

@ -55,6 +55,8 @@
#include "actors/hexen/puzzleitems.txt"
#include "actors/hexen/scriptprojectiles.txt"
#include "actors/hexen/speedboots.txt"
#include "actors/hexen/ettin.txt"
#include "actors/hexen/centaur.txt"
#include "actors/strife/beggars.txt"
#include "actors/strife/merchants.txt"

View file

@ -0,0 +1,188 @@
// Centaur ------------------------------------------------------------------
ACTOR Centaur 107
{
Game Hexen
SpawnID 1
Health 200
Painchance 135
Speed 13
Height 64
Mass 120
Monster
+FLOORCLIP
+TELESTOMP
+SHIELDREFLECT
SeeSound "CentaurSight"
AttackSound "CentaurAttack"
PainSound "CentaurPain"
DeathSound "CentaurDeath"
ActiveSound "CentaurActive"
HowlSound "PuppyBeat"
States
{
Spawn:
CENT AB 10 A_Look
Loop
See:
CENT ABCD 4 A_Chase
Loop
Pain:
CENT G 6 A_Pain
CENT G 6 A_SetReflectiveInvulnerable
CENT EEE 15 A_CentaurDefend
CENT E 1 A_UnsetReflectiveInvulnerable
Goto See
Melee:
CENT H 5 A_FaceTarget
CENT I 4 A_FaceTarget
CENT J 7 A_CustomMeleeAttack(random[CentaurAttack](3,9))
Goto See
Death:
CENT K 4
CENT L 4 A_Scream
CENT MN 4
CENT O 4 A_NoBlocking
CENT PQ 4
CENT R 4 A_QueueCorpse
CENT S 4
CENT T -1
Stop
XDeath:
CTXD A 4
CTXD B 4 A_NoBlocking
CTXD C 0 A_SpawnItemEx("CentaurSword", 0, 0, 45,
1 + random[CentaurDrop](-128,127)*0.03125,
1 + random[CentaurDrop](-128,127)*0.03125,
8 + random[CentaurDrop](0,255)*0.015625, 270)
CTXD C 4 A_SpawnItemEx("CentaurShield", 0, 0, 45,
1 + random[CentaurDrop](-128,127)*0.03125,
1 + random[CentaurDrop](-128,127)*0.03125,
8 + random[CentaurDrop](0,255)*0.015625, 90)
CTXD D 3 A_Scream
CTXD E 4 A_QueueCorpse
CTXD F 3
CTXD G 4
CTXD H 3
CTXD I 4
CTXD J 3
CTXD K -1
Ice:
CENT U 5 A_FreezeDeath
CENT U 1 A_FreezeDeathChunks
Wait
}
}
// Centaur Leader -----------------------------------------------------------
ACTOR CentaurLeader : Centaur 115
{
Game Hexen
SpawnID 2
Health 250
PainChance 96
Speed 10
States
{
Missile:
CENT E 10 A_FaceTarget
CENT F 8 Bright A_CustomMissile("CentaurFX", 45, 0, 0, 1)
CENT E 10 A_FaceTarget
CENT F 8 Bright A_CustomMissile("CentaurFX", 45, 0, 0, 1)
Goto See
}
}
// Mashed centaur -----------------------------------------------------------
//
// The mashed centaur is only placed through ACS. Nowhere in the game source
// is it ever referenced.
ACTOR CentaurMash
{
Game Hexen
SpawnID 103
+NOBLOOD
+BLASTED
-TELESTOMP
+NOICEDEATH
RenderStyle Translucent
Alpha 0.4
States
{
Death:
XDeath:
Ice:
Stop
}
}
// Centaur projectile -------------------------------------------------------
ACTOR CentaurFX
{
Speed 20
Damage 4
Projectile
+SPAWNSOUNDSOURCE
RenderStyle Add
SeeSound "CentaurLeaderAttack"
DeathSound "CentaurMissileExplode"
States
{
Spawn:
CTFX A -1 Bright
Stop
Death:
CTFX B 4 Bright
CTFX C 3 Bright
CTFX D 4 Bright
CTFX E 3 Bright
CTFX F 2 Bright
Stop
}
}
// Centaur shield (debris) --------------------------------------------------
ACTOR CentaurShield
{
+DROPOFF
+CORPSE
+NOTELEPORT
States
{
Spawn:
CTDP ABCDEF 3
Goto Spawn+2
Crash:
CTDP G 4
CTDP H 4 A_QueueCorpse
CTDP I 4
CTDP J -1
Stop
}
}
// Centaur sword (debris) ---------------------------------------------------
ACTOR CentaurSword
{
+DROPOFF
+CORPSE
+NOTELEPORT
States
{
Spawn:
CTDP KLMNOPQ 3
Goto Spawn+2
Crash:
CTDP R 4
CTDP S 4 A_QueueCorpse
CTDP T -1
Stop
}
}

View file

@ -0,0 +1,109 @@
// Ettin --------------------------------------------------------------------
ACTOR Ettin 10030
{
Game Hexen
SpawnID 4
Health 175
Radius 25
Height 68
Mass 175
Speed 13
Damage 3
Painchance 60
Monster
+FLOORCLIP
+TELESTOMP
SeeSound "EttinSight"
AttackSound "EttinAttack"
PainSound "EttinPain"
DeathSound "EttinDeath"
ActiveSound "EttinActive"
HowlSound "PuppyBeat"
States
{
Spawn:
ETTN AA 10 A_Look
Loop
See:
ETTN ABCD 5 A_Chase
Loop
Pain:
ETTN H 7 A_Pain
Goto See
Melee:
ETTN EF 6 A_FaceTarget
ETTN G 8 A_CustomMeleeAttack(random[EttinAttack](1,8)*2)
Goto See
Death:
ETTN IJ 4
ETTN K 4 A_Scream
ETTN L 4 A_NoBlocking
ETTN M 4 A_QueueCorpse
ETTN NOP 4
ETTN Q -1
Stop
XDeath:
ETTB A 4
ETTB B 4 A_NoBlocking
ETTB C 4 A_SpawnItemEx("EttinMace", 0,0,8.5,
random[DropMace](-128,127) * 0.03125,
random[DropMace](-128,127) * 0.03125,
10 + random[DropMace](0,255) * 0.015625, 0, 4)
ETTB D 4 A_Scream
ETTB E 4 A_QueueCorpse
ETTB FGHIJK 4
ETTB L -1
Stop
Ice:
ETTN R 5 A_FreezeDeath
ETTN R 1 A_FreezeDeathChunks
Wait
}
}
// Ettin mace ---------------------------------------------------------------
ACTOR EttinMace
{
Radius 5
Height 5
+DROPOFF
+CORPSE
+NOTELEPORT
+FLOORCLIP
States
{
Spawn:
ETTB MNOP 5
Loop
Crash:
ETTB Q 5
ETTB R 5 A_QueueCorpse
ETTB S -1
Stop
}
}
// Ettin mash ---------------------------------------------------------------
ACTOR EttinMash : Ettin
{
Game Hexen
SpawnID 102
+NOBLOOD
+NOICEDEATH
RenderStyle Translucent
Alpha 0.4
States
{
Death:
XDeath:
Ice:
Stop
}
}

View file

@ -54,7 +54,7 @@ ACTOR ZombieSpawner 170
States
{
Spawn:
TNT1 A 175 A_SpawnItem("Zombie", 0.1, 0)
TNT1 A 175 A_SpawnItemEx("Zombie")
Loop
}
}

View file

@ -298,6 +298,8 @@ actors/hexen/mana.txt decorate/hexen/mana.txt
actors/hexen/puzzleitems.txt decorate/hexen/puzzleitems.txt
actors/hexen/scriptprojectiles.txt decorate/hexen/scriptprojectiles.txt
actors/hexen/speedboots.txt decorate/hexen/speedboots.txt
actors/hexen/ettin.txt decorate/hexen/ettin.txt
actors/hexen/centaur.txt decorate/hexen/centaur.txt
actors/strife/beggars.txt decorate/strife/beggars.txt
actors/strife/merchants.txt decorate/strife/merchants.txt

View file

@ -7920,42 +7920,6 @@
/>
</FileConfiguration>
</File>
<File
RelativePath=".\src\g_hexen\a_ettin.cpp"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="&quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; "
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="&quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; "
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="&quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; "
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
AdditionalOptions="&quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; &quot; /I /fmod/api/inc&quot; "
/>
</FileConfiguration>
</File>
<File
RelativePath=".\src\g_hexen\a_fighteraxe.cpp"
>