mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2025-02-07 13:41:02 +00:00
- 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:
parent
d840d9b68a
commit
a90ba9deb6
20 changed files with 648 additions and 701 deletions
|
@ -1,4 +1,14 @@
|
||||||
November 26, 2006 (Changes by Graf Zahl)
|
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
|
- Added random2 function to DECORATE's expression evaluator. This is to
|
||||||
better emulate some calculation of internal code pointers.
|
better emulate some calculation of internal code pointers.
|
||||||
- Added named RNG support to DECORATE's expression evaluator. Just use
|
- Added named RNG support to DECORATE's expression evaluator. Just use
|
||||||
|
|
|
@ -418,6 +418,7 @@ enum
|
||||||
AMETA_FastSpeed, // Speed in fast mode
|
AMETA_FastSpeed, // Speed in fast mode
|
||||||
AMETA_RDFactor, // Radius damage factor
|
AMETA_RDFactor, // Radius damage factor
|
||||||
AMETA_CameraHeight, // Height of camera when used as such
|
AMETA_CameraHeight, // Height of camera when used as such
|
||||||
|
AMETA_HowlSound, // Sound being played when electrocuted or poisoned
|
||||||
};
|
};
|
||||||
|
|
||||||
// Map Object definition.
|
// Map Object definition.
|
||||||
|
@ -476,7 +477,8 @@ public:
|
||||||
virtual int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype);
|
virtual int TakeSpecialDamage (AActor *inflictor, AActor *source, int damage, FName damagetype);
|
||||||
|
|
||||||
// Centaurs and ettins squeal when electrocuted, poisoned, or "holy"-ed
|
// 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
|
// Called by A_NoBlocking in case the actor wants to drop some presents
|
||||||
virtual void NoBlockingSet ();
|
virtual void NoBlockingSet ();
|
||||||
|
@ -504,9 +506,6 @@ public:
|
||||||
// Called by RoughBlockCheck
|
// Called by RoughBlockCheck
|
||||||
virtual bool IsOkayToAttack (AActor *target);
|
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.
|
// Plays the actor's ActiveSound if its voice isn't already making noise.
|
||||||
void PlayActiveSound ();
|
void PlayActiveSound ();
|
||||||
|
|
||||||
|
|
|
@ -1,326 +1,10 @@
|
||||||
#include "actor.h"
|
#include "actor.h"
|
||||||
#include "info.h"
|
|
||||||
#include "p_local.h"
|
|
||||||
#include "s_sound.h"
|
|
||||||
#include "p_enemy.h"
|
#include "p_enemy.h"
|
||||||
#include "a_action.h"
|
#include "a_action.h"
|
||||||
#include "m_random.h"
|
#include "m_random.h"
|
||||||
#include "a_hexenglobal.h"
|
|
||||||
|
|
||||||
static FRandom pr_centaurdefend ("CentaurDefend");
|
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
|
// A_CentaurDefend
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -52,13 +52,6 @@ public:
|
||||||
void BeginPlay ();
|
void BeginPlay ();
|
||||||
};
|
};
|
||||||
|
|
||||||
class ACentaur : public AActor
|
|
||||||
{
|
|
||||||
DECLARE_ACTOR (ACentaur, AActor)
|
|
||||||
public:
|
|
||||||
void Howl ();
|
|
||||||
};
|
|
||||||
|
|
||||||
class AFourthWeaponPiece : public AInventory
|
class AFourthWeaponPiece : public AInventory
|
||||||
{
|
{
|
||||||
DECLARE_STATELESS_ACTOR (AFourthWeaponPiece, AInventory)
|
DECLARE_STATELESS_ACTOR (AFourthWeaponPiece, AInventory)
|
||||||
|
|
|
@ -683,10 +683,6 @@ AActor *P_SpawnKoraxMissile (fixed_t x, fixed_t y, fixed_t z,
|
||||||
|
|
||||||
z -= source->floorclip;
|
z -= source->floorclip;
|
||||||
th = Spawn (type, x, y, z, ALLOW_REPLACE);
|
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
|
th->target = source; // Originator
|
||||||
an = R_PointToAngle2(x, y, dest->x, dest->y);
|
an = R_PointToAngle2(x, y, dest->x, dest->y);
|
||||||
if (dest->flags & MF_SHADOW)
|
if (dest->flags & MF_SHADOW)
|
||||||
|
|
|
@ -130,7 +130,11 @@ int ALightning::SpecialMissileHit (AActor *thing)
|
||||||
if ((!thing->player && !(thing->flags2&MF2_BOSS))
|
if ((!thing->player && !(thing->flags2&MF2_BOSS))
|
||||||
|| !(level.time&1))
|
|| !(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
|
{ // Lightning does more damage to centaurs
|
||||||
P_DamageMobj(thing, this, target, 9, NAME_Electric);
|
P_DamageMobj(thing, this, target, 9, NAME_Electric);
|
||||||
}
|
}
|
||||||
|
|
|
@ -321,7 +321,6 @@ void A_FreezeDeathChunks (AActor *actor)
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Corpse queue for monsters - this should be saved out
|
// Corpse queue for monsters - this should be saved out
|
||||||
#define CORPSEQUEUESIZE 64
|
|
||||||
|
|
||||||
class DCorpsePointer : public DThinker
|
class DCorpsePointer : public DThinker
|
||||||
{
|
{
|
||||||
|
@ -340,7 +339,23 @@ private:
|
||||||
IMPLEMENT_POINTY_CLASS(DCorpsePointer)
|
IMPLEMENT_POINTY_CLASS(DCorpsePointer)
|
||||||
DECLARE_POINTER(Corpse)
|
DECLARE_POINTER(Corpse)
|
||||||
END_POINTERS
|
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)
|
DCorpsePointer::DCorpsePointer (AActor *ptr)
|
||||||
: DThinker (STAT_CORPSEPOINTER), Corpse (ptr)
|
: DThinker (STAT_CORPSEPOINTER), Corpse (ptr)
|
||||||
|
@ -354,7 +369,7 @@ DCorpsePointer::DCorpsePointer (AActor *ptr)
|
||||||
|
|
||||||
if (first != this)
|
if (first != this)
|
||||||
{
|
{
|
||||||
if (first->Count >= CORPSEQUEUESIZE)
|
if (first->Count >= (DWORD)sv_corpsequeuesize)
|
||||||
{
|
{
|
||||||
DCorpsePointer *next = iterator.Next ();
|
DCorpsePointer *next = iterator.Next ();
|
||||||
next->Count = first->Count;
|
next->Count = first->Count;
|
||||||
|
@ -399,7 +414,8 @@ void DCorpsePointer::Serialize (FArchive &arc)
|
||||||
// throw another corpse on the queue
|
// throw another corpse on the queue
|
||||||
void A_QueueCorpse (AActor *actor)
|
void A_QueueCorpse (AActor *actor)
|
||||||
{
|
{
|
||||||
new DCorpsePointer (actor);
|
if (sv_corpsequeuesize > 0)
|
||||||
|
new DCorpsePointer (actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove an actor from the queue (for resurrection)
|
// Remove an actor from the queue (for resurrection)
|
||||||
|
|
|
@ -2319,6 +2319,11 @@ int AActor::GetMissileDamage (int mask, int add)
|
||||||
|
|
||||||
void AActor::Howl ()
|
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 ()
|
void AActor::NoBlockingSet ()
|
||||||
|
@ -2433,17 +2438,6 @@ bool AActor::IsOkayToAttack (AActor *link)
|
||||||
return false;
|
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)
|
void AActor::SetShade (DWORD rgb)
|
||||||
{
|
{
|
||||||
PalEntry *entry = (PalEntry *)&rgb;
|
PalEntry *entry = (PalEntry *)&rgb;
|
||||||
|
|
|
@ -140,6 +140,9 @@ static int DoomSpecificInfo (char *buffer, char *end)
|
||||||
|
|
||||||
int main (int argc, char **argv)
|
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 };
|
int s[4] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS };
|
||||||
cc_install_handlers(4, s, "zdoom-crash.log", DoomSpecificInfo);
|
cc_install_handlers(4, s, "zdoom-crash.log", DoomSpecificInfo);
|
||||||
|
|
|
@ -348,7 +348,7 @@ int I_PickIWad (WadStuff *wads, int numwads, bool queryiwad, int defaultiwad)
|
||||||
{
|
{
|
||||||
int i;
|
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)
|
for (i = 0; i < numwads; ++i)
|
||||||
{
|
{
|
||||||
const char *filepart = strrchr (wads[i].Path, '/');
|
const char *filepart = strrchr (wads[i].Path, '/');
|
||||||
|
|
|
@ -132,6 +132,7 @@ static flagdef ActorFlags[]=
|
||||||
DEFINE_FLAG2(MF2_LOGRAV, LOWGRAVITY, AActor, flags2),
|
DEFINE_FLAG2(MF2_LOGRAV, LOWGRAVITY, AActor, flags2),
|
||||||
DEFINE_FLAG(MF2, WINDTHRUST, AActor, flags2),
|
DEFINE_FLAG(MF2, WINDTHRUST, AActor, flags2),
|
||||||
DEFINE_FLAG(MF2, HERETICBOUNCE , AActor, flags2),
|
DEFINE_FLAG(MF2, HERETICBOUNCE , AActor, flags2),
|
||||||
|
DEFINE_FLAG(MF2, BLASTED, AActor, flags2),
|
||||||
DEFINE_FLAG(MF2, FLOORCLIP, AActor, flags2),
|
DEFINE_FLAG(MF2, FLOORCLIP, AActor, flags2),
|
||||||
DEFINE_FLAG(MF2, SPAWNFLOAT, AActor, flags2),
|
DEFINE_FLAG(MF2, SPAWNFLOAT, AActor, flags2),
|
||||||
DEFINE_FLAG(MF2, NOTELEPORT, AActor, flags2),
|
DEFINE_FLAG(MF2, NOTELEPORT, AActor, flags2),
|
||||||
|
@ -477,6 +478,7 @@ ACTOR(LightInverse)
|
||||||
ACTOR(GiveInventory)
|
ACTOR(GiveInventory)
|
||||||
ACTOR(TakeInventory)
|
ACTOR(TakeInventory)
|
||||||
ACTOR(SpawnItem)
|
ACTOR(SpawnItem)
|
||||||
|
ACTOR(SpawnItemEx)
|
||||||
ACTOR(ThrowGrenade)
|
ACTOR(ThrowGrenade)
|
||||||
ACTOR(Recoil)
|
ACTOR(Recoil)
|
||||||
ACTOR(SelectWeapon)
|
ACTOR(SelectWeapon)
|
||||||
|
@ -506,6 +508,7 @@ ACTOR(TakeFromTarget)
|
||||||
ACTOR(JumpIfInTargetInventory)
|
ACTOR(JumpIfInTargetInventory)
|
||||||
ACTOR(CountdownArg)
|
ACTOR(CountdownArg)
|
||||||
ACTOR(CustomMeleeAttack)
|
ACTOR(CustomMeleeAttack)
|
||||||
|
ACTOR(CustomComboAttack)
|
||||||
ACTOR(Light)
|
ACTOR(Light)
|
||||||
ACTOR(Burst)
|
ACTOR(Burst)
|
||||||
ACTOR(SkullPop)
|
ACTOR(SkullPop)
|
||||||
|
@ -517,6 +520,7 @@ ACTOR(SPosAttackUseAtkSound)
|
||||||
ACTOR(Respawn)
|
ACTOR(Respawn)
|
||||||
ACTOR(BarrelDestroy)
|
ACTOR(BarrelDestroy)
|
||||||
ACTOR(PlayerSkinCheck)
|
ACTOR(PlayerSkinCheck)
|
||||||
|
ACTOR(QueueCorpse)
|
||||||
|
|
||||||
|
|
||||||
#include "d_dehackedactions.h"
|
#include "d_dehackedactions.h"
|
||||||
|
@ -697,6 +701,7 @@ AFuncDesc AFTable[]=
|
||||||
FUNC(A_GiveInventory, "Mx" )
|
FUNC(A_GiveInventory, "Mx" )
|
||||||
FUNC(A_TakeInventory, "Mx" )
|
FUNC(A_TakeInventory, "Mx" )
|
||||||
FUNC(A_SpawnItem, "Mxxyx" )
|
FUNC(A_SpawnItem, "Mxxyx" )
|
||||||
|
FUNC(A_SpawnItemEx, "Mxxxxxxxx" )
|
||||||
FUNC(A_ThrowGrenade, "Mxxxy" )
|
FUNC(A_ThrowGrenade, "Mxxxy" )
|
||||||
FUNC(A_SelectWeapon, "M")
|
FUNC(A_SelectWeapon, "M")
|
||||||
FUNC(A_Print, "Txt")
|
FUNC(A_Print, "Txt")
|
||||||
|
@ -728,12 +733,14 @@ AFuncDesc AFTable[]=
|
||||||
FUNC(A_TakeFromTarget, "Mx" )
|
FUNC(A_TakeFromTarget, "Mx" )
|
||||||
FUNC(A_CountdownArg, "X")
|
FUNC(A_CountdownArg, "X")
|
||||||
FUNC(A_CustomMeleeAttack, "Xssty" )
|
FUNC(A_CustomMeleeAttack, "Xssty" )
|
||||||
|
FUNC(A_CustomComboAttack, "MXXsty" )
|
||||||
FUNC(A_Burst, "M")
|
FUNC(A_Burst, "M")
|
||||||
FUNC(A_RadiusThrust, "xxy")
|
FUNC(A_RadiusThrust, "xxy")
|
||||||
{"A_Explode", A_ExplodeParms, "xxy" },
|
{"A_Explode", A_ExplodeParms, "xxy" },
|
||||||
FUNC(A_Stop, NULL)
|
FUNC(A_Stop, NULL)
|
||||||
FUNC(A_Respawn, "y")
|
FUNC(A_Respawn, "y")
|
||||||
FUNC(A_BarrelDestroy, NULL)
|
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);
|
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) },
|
{ "health.lowmessage", (apf)HealthLowMessage, RUNTIME_CLASS(AHealth) },
|
||||||
{ "height", ActorHeight, RUNTIME_CLASS(AActor) },
|
{ "height", ActorHeight, RUNTIME_CLASS(AActor) },
|
||||||
{ "hitobituary", ActorHitObituary, RUNTIME_CLASS(AActor) },
|
{ "hitobituary", ActorHitObituary, RUNTIME_CLASS(AActor) },
|
||||||
|
{ "howlsound", ActorHowlSound, RUNTIME_CLASS(AActor) },
|
||||||
{ "ice", ActorIceState, RUNTIME_CLASS(AActor) },
|
{ "ice", ActorIceState, RUNTIME_CLASS(AActor) },
|
||||||
{ "inventory.amount", (apf)InventoryAmount, RUNTIME_CLASS(AInventory) },
|
{ "inventory.amount", (apf)InventoryAmount, RUNTIME_CLASS(AInventory) },
|
||||||
{ "inventory.defmaxamount", (apf)InventoryDefMaxAmount, RUNTIME_CLASS(AInventory) },
|
{ "inventory.defmaxamount", (apf)InventoryDefMaxAmount, RUNTIME_CLASS(AInventory) },
|
||||||
|
|
|
@ -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
|
// State jump function
|
||||||
|
@ -1228,6 +1285,71 @@ void A_TakeFromTarget(AActor * self)
|
||||||
DoTakeInventory(self, self->target);
|
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
|
// A_SpawnItem
|
||||||
|
@ -1235,6 +1357,7 @@ void A_TakeFromTarget(AActor * self)
|
||||||
// Spawns an item in front of the caller like Heretic's time bomb
|
// Spawns an item in front of the caller like Heretic's time bomb
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
void A_SpawnItem(AActor * self)
|
void A_SpawnItem(AActor * self)
|
||||||
{
|
{
|
||||||
FState * CallingState;
|
FState * CallingState;
|
||||||
|
@ -1276,60 +1399,88 @@ void A_SpawnItem(AActor * self)
|
||||||
self->y + FixedMul(distance, finesine[self->angle>>ANGLETOFINESHIFT]),
|
self->y + FixedMul(distance, finesine[self->angle>>ANGLETOFINESHIFT]),
|
||||||
self->z - self->floorclip + zheight, ALLOW_REPLACE);
|
self->z - self->floorclip + zheight, ALLOW_REPLACE);
|
||||||
|
|
||||||
|
InitSpawnedItem(self, mo, transfer_translation, useammo);
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// A_SpawnItemEx
|
||||||
|
//
|
||||||
|
// Enhanced spawning function
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
enum SIX_Flags
|
||||||
|
{
|
||||||
|
SIXF_TRANSFERTRANSLATION=1,
|
||||||
|
SIXF_ABSOLUTEPOSITION=2,
|
||||||
|
SIXF_ABSOLUTEANGLE=4,
|
||||||
|
SIXF_ABSOLUTEMOMENTUM=8,
|
||||||
|
SIXF_SETMASTER=16
|
||||||
|
};
|
||||||
|
|
||||||
|
void A_SpawnItemEx(AActor * self)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (pStateCall != NULL) pStateCall->Result=false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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))
|
||||||
|
{
|
||||||
|
Angle += self->angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
angle_t ang = Angle >> ANGLETOFINESHIFT;
|
||||||
|
|
||||||
|
if (flags & SIXF_ABSOLUTEPOSITION)
|
||||||
|
{
|
||||||
|
x = self->x + xofs;
|
||||||
|
y = self->y + yofs;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 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)
|
if (mo)
|
||||||
{
|
{
|
||||||
AActor * originator = self;
|
mo->momx=xmom;
|
||||||
|
mo->momy=ymom;
|
||||||
if (transfer_translation)
|
mo->momz=zmom;
|
||||||
{
|
mo->angle=Angle;
|
||||||
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 (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)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="Windows-1252"?>
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
<VisualStudioProject
|
<VisualStudioProject
|
||||||
ProjectType="Visual C++"
|
ProjectType="Visual C++"
|
||||||
Version="8.00"
|
Version="8,00"
|
||||||
Name="updaterevision"
|
Name="updaterevision"
|
||||||
ProjectGUID="{6077B7D6-349F-4077-B552-3BC302EF5859}"
|
ProjectGUID="{6077B7D6-349F-4077-B552-3BC302EF5859}"
|
||||||
RootNamespace="updaterevision"
|
RootNamespace="updaterevision"
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
>
|
>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCPreBuildEventTool"
|
Name="VCPreBuildEventTool"
|
||||||
CommandLine="echo ------------------- VERY IMPORTANT: --------------------
echo You must copy the mt.exe from
echo $(VSINSTALLDIR)\Common7\Tools\bin
echo on top of the version in
echo $(VSINSTALLDIR)\VC\bin
echo or your computer may restart while building."
|
CommandLine="echo ------------------- VERY IMPORTANT: --------------------
echo You must copy the mt.exe from
echo $(VSINSTALLDIR)\Common7\Tools\bin
echo on top of the version in
echo $(VSINSTALLDIR)\VC\bin
echo or your computer may restart while building.
"
|
||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCustomBuildTool"
|
Name="VCCustomBuildTool"
|
||||||
|
@ -96,6 +96,83 @@
|
||||||
Name="VCPostBuildEventTool"
|
Name="VCPostBuildEventTool"
|
||||||
/>
|
/>
|
||||||
</Configuration>
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="1"
|
||||||
|
WholeProgramOptimization="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
CommandLine="echo ------------------- VERY IMPORTANT: --------------------
echo You must copy the mt.exe from
echo $(VSINSTALLDIR)\Common7\Tools\bin
echo on top of the version in
echo $(VSINSTALLDIR)\VC\bin
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
|
<Configuration
|
||||||
Name="Debug|x64"
|
Name="Debug|x64"
|
||||||
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
|
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
|
||||||
|
@ -172,83 +249,6 @@
|
||||||
Name="VCPostBuildEventTool"
|
Name="VCPostBuildEventTool"
|
||||||
/>
|
/>
|
||||||
</Configuration>
|
</Configuration>
|
||||||
<Configuration
|
|
||||||
Name="Release|Win32"
|
|
||||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ConfigurationName)"
|
|
||||||
ConfigurationType="1"
|
|
||||||
CharacterSet="1"
|
|
||||||
WholeProgramOptimization="1"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"
|
|
||||||
CommandLine="echo ------------------- VERY IMPORTANT: --------------------
echo You must copy the mt.exe from
echo $(VSINSTALLDIR)\Common7\Tools\bin
echo on top of the version in
echo $(VSINSTALLDIR)\VC\bin
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
|
<Configuration
|
||||||
Name="Release|x64"
|
Name="Release|x64"
|
||||||
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
|
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
|
||||||
|
|
|
@ -55,6 +55,8 @@
|
||||||
#include "actors/hexen/puzzleitems.txt"
|
#include "actors/hexen/puzzleitems.txt"
|
||||||
#include "actors/hexen/scriptprojectiles.txt"
|
#include "actors/hexen/scriptprojectiles.txt"
|
||||||
#include "actors/hexen/speedboots.txt"
|
#include "actors/hexen/speedboots.txt"
|
||||||
|
#include "actors/hexen/ettin.txt"
|
||||||
|
#include "actors/hexen/centaur.txt"
|
||||||
|
|
||||||
#include "actors/strife/beggars.txt"
|
#include "actors/strife/beggars.txt"
|
||||||
#include "actors/strife/merchants.txt"
|
#include "actors/strife/merchants.txt"
|
||||||
|
|
188
wadsrc/decorate/hexen/centaur.txt
Normal file
188
wadsrc/decorate/hexen/centaur.txt
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
109
wadsrc/decorate/hexen/ettin.txt
Normal file
109
wadsrc/decorate/hexen/ettin.txt
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ ACTOR ZombieSpawner 170
|
||||||
States
|
States
|
||||||
{
|
{
|
||||||
Spawn:
|
Spawn:
|
||||||
TNT1 A 175 A_SpawnItem("Zombie", 0.1, 0)
|
TNT1 A 175 A_SpawnItemEx("Zombie")
|
||||||
Loop
|
Loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -298,6 +298,8 @@ actors/hexen/mana.txt decorate/hexen/mana.txt
|
||||||
actors/hexen/puzzleitems.txt decorate/hexen/puzzleitems.txt
|
actors/hexen/puzzleitems.txt decorate/hexen/puzzleitems.txt
|
||||||
actors/hexen/scriptprojectiles.txt decorate/hexen/scriptprojectiles.txt
|
actors/hexen/scriptprojectiles.txt decorate/hexen/scriptprojectiles.txt
|
||||||
actors/hexen/speedboots.txt decorate/hexen/speedboots.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/beggars.txt decorate/strife/beggars.txt
|
||||||
actors/strife/merchants.txt decorate/strife/merchants.txt
|
actors/strife/merchants.txt decorate/strife/merchants.txt
|
||||||
|
|
36
zdoom.vcproj
36
zdoom.vcproj
|
@ -7920,42 +7920,6 @@
|
||||||
/>
|
/>
|
||||||
</FileConfiguration>
|
</FileConfiguration>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath=".\src\g_hexen\a_ettin.cpp"
|
|
||||||
>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Release|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalOptions="" /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" "
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalOptions="" /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" "
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Release|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalOptions="" /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" "
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
<FileConfiguration
|
|
||||||
Name="Debug|x64"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalOptions="" /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" " /I /fmod/api/inc" "
|
|
||||||
/>
|
|
||||||
</FileConfiguration>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath=".\src\g_hexen\a_fighteraxe.cpp"
|
RelativePath=".\src\g_hexen\a_fighteraxe.cpp"
|
||||||
>
|
>
|
||||||
|
|
Loading…
Reference in a new issue