gzdoom-gles/src/g_hexen/a_fighterquietus.cpp
Christoph Oelckers b15767c26f - Fixed: The pointer cleanup code must also check a sector's sky box pointers.
- Fixed: Right after teleporting P_SlideMove could cause player movement.
  Added a check for reactiontime to prevent that.
- Fixed: PainChances and Damagefactors were never freed.
- Added option to A_Chase that prevents the monster from moving.
- Fixed: The stained glass shards were missing the HEXENBOUNCE flag.
- Added some NULL pointer checks to AActor::GiveAmmo.
- Fixed: The FSwordMissile was missing the special damage handling that
  reduces damage when hitting a player.

SVN r555 (trunk)
2007-10-29 20:27:40 +00:00

399 lines
13 KiB
C++

#include "actor.h"
#include "gi.h"
#include "m_random.h"
#include "s_sound.h"
#include "d_player.h"
#include "a_action.h"
#include "p_local.h"
#include "p_enemy.h"
#include "p_pspr.h"
#include "gstrings.h"
#include "a_hexenglobal.h"
static FRandom pr_quietusdrop ("QuietusDrop");
static FRandom pr_fswordflame ("FSwordFlame");
void A_FSwordAttack (AActor *actor);
void A_DropQuietusPieces (AActor *);
void A_FSwordFlames (AActor *);
//==========================================================================
class AFighterWeaponPiece : public AFourthWeaponPiece
{
DECLARE_STATELESS_ACTOR (AFighterWeaponPiece, AFourthWeaponPiece)
public:
void BeginPlay ();
protected:
bool MatchPlayerClass (AActor *toucher);
};
IMPLEMENT_STATELESS_ACTOR (AFighterWeaponPiece, Hexen, -1, 0)
PROP_Inventory_PickupMessage("$TXT_QUIETUS_PIECE")
END_DEFAULTS
bool AFighterWeaponPiece::MatchPlayerClass (AActor *toucher)
{
return !toucher->IsKindOf (PClass::FindClass(NAME_ClericPlayer)) &&
!toucher->IsKindOf (PClass::FindClass(NAME_MagePlayer));
}
//==========================================================================
class AFWeaponPiece1 : public AFighterWeaponPiece
{
DECLARE_ACTOR (AFWeaponPiece1, AFighterWeaponPiece)
public:
void BeginPlay ();
};
FState AFWeaponPiece1::States[] =
{
S_BRIGHT (WFR1, 'A', -1, NULL , NULL)
};
IMPLEMENT_ACTOR (AFWeaponPiece1, Hexen, 12, 29)
PROP_Flags (MF_SPECIAL)
PROP_Flags2 (MF2_FLOATBOB)
PROP_SpawnState (0)
END_DEFAULTS
void AFWeaponPiece1::BeginPlay ()
{
Super::BeginPlay ();
PieceValue = WPIECE1;
}
//==========================================================================
class AFWeaponPiece2 : public AFighterWeaponPiece
{
DECLARE_ACTOR (AFWeaponPiece2, AFighterWeaponPiece)
public:
void BeginPlay ();
};
FState AFWeaponPiece2::States[] =
{
S_BRIGHT (WFR2, 'A', -1, NULL , NULL)
};
IMPLEMENT_ACTOR (AFWeaponPiece2, Hexen, 13, 30)
PROP_Flags (MF_SPECIAL)
PROP_Flags2 (MF2_FLOATBOB)
PROP_SpawnState (0)
END_DEFAULTS
void AFWeaponPiece2::BeginPlay ()
{
Super::BeginPlay ();
PieceValue = WPIECE2;
}
//==========================================================================
class AFWeaponPiece3 : public AFighterWeaponPiece
{
DECLARE_ACTOR (AFWeaponPiece3, AFighterWeaponPiece)
public:
void BeginPlay ();
};
FState AFWeaponPiece3::States[] =
{
S_BRIGHT (WFR3, 'A', -1, NULL , NULL)
};
IMPLEMENT_ACTOR (AFWeaponPiece3, Hexen, 16, 31)
PROP_Flags (MF_SPECIAL)
PROP_Flags2 (MF2_FLOATBOB)
PROP_SpawnState (0)
END_DEFAULTS
void AFWeaponPiece3::BeginPlay ()
{
Super::BeginPlay ();
PieceValue = WPIECE3;
}
// An actor that spawns the three pieces of the fighter's fourth weapon -----
// This gets spawned if weapon drop is on so that other players can pick up
// this player's weapon.
class AQuietusDrop : public AActor
{
DECLARE_ACTOR (AQuietusDrop, AActor)
};
FState AQuietusDrop::States[] =
{
S_NORMAL (TNT1, 'A', 1, NULL, &States[1]),
S_NORMAL (TNT1, 'A', 1, A_DropQuietusPieces, NULL)
};
IMPLEMENT_ACTOR (AQuietusDrop, Hexen, -1, 0)
PROP_SpawnState (0)
END_DEFAULTS
// The Fighter's Sword (Quietus) --------------------------------------------
class AFWeapQuietus : public AFighterWeapon
{
DECLARE_ACTOR (AFWeapQuietus, AFighterWeapon)
};
FState AFWeapQuietus::States[] =
{
// Dummy state, because the fourth weapon does not appear in a level directly.
S_NORMAL (TNT1, 'A', -1, NULL , NULL),
#define S_FSWORDREADY (1)
S_BRIGHT (FSRD, 'A', 1, A_WeaponReady , &States[S_FSWORDREADY+1]), // S_FSWORDREADY
S_BRIGHT (FSRD, 'A', 1, A_WeaponReady , &States[S_FSWORDREADY+2]), // S_FSWORDREADY1
S_BRIGHT (FSRD, 'A', 1, A_WeaponReady , &States[S_FSWORDREADY+3]), // S_FSWORDREADY2
S_BRIGHT (FSRD, 'A', 1, A_WeaponReady , &States[S_FSWORDREADY+4]), // S_FSWORDREADY3
S_BRIGHT (FSRD, 'B', 1, A_WeaponReady , &States[S_FSWORDREADY+5]), // S_FSWORDREADY4
S_BRIGHT (FSRD, 'B', 1, A_WeaponReady , &States[S_FSWORDREADY+6]), // S_FSWORDREADY5
S_BRIGHT (FSRD, 'B', 1, A_WeaponReady , &States[S_FSWORDREADY+7]), // S_FSWORDREADY6
S_BRIGHT (FSRD, 'B', 1, A_WeaponReady , &States[S_FSWORDREADY+8]), // S_FSWORDREADY7
S_BRIGHT (FSRD, 'C', 1, A_WeaponReady , &States[S_FSWORDREADY+9]), // S_FSWORDREADY8
S_BRIGHT (FSRD, 'C', 1, A_WeaponReady , &States[S_FSWORDREADY+10]), // S_FSWORDREADY9
S_BRIGHT (FSRD, 'C', 1, A_WeaponReady , &States[S_FSWORDREADY+11]), // S_FSWORDREADY10
S_BRIGHT (FSRD, 'C', 1, A_WeaponReady , &States[S_FSWORDREADY]), // S_FSWORDREADY11
#define S_FSWORDDOWN (S_FSWORDREADY+12)
S_BRIGHT (FSRD, 'A', 1, A_Lower , &States[S_FSWORDDOWN]), // S_FSWORDDOWN
#define S_FSWORDUP (S_FSWORDDOWN+1)
S_BRIGHT (FSRD, 'A', 1, A_Raise , &States[S_FSWORDUP]), // S_FSWORDUP
#define S_FSWORDATK (S_FSWORDUP+1)
S_BRIGHT2 (FSRD, 'D', 3, NULL , &States[S_FSWORDATK+1], 5, 36), // S_FSWORDATK_1
S_BRIGHT2 (FSRD, 'E', 3, NULL , &States[S_FSWORDATK+2], 5, 36), // S_FSWORDATK_2
S_BRIGHT2 (FSRD, 'F', 2, NULL , &States[S_FSWORDATK+3], 5, 36), // S_FSWORDATK_3
S_BRIGHT2 (FSRD, 'G', 3, A_FSwordAttack , &States[S_FSWORDATK+4], 5, 36), // S_FSWORDATK_4
S_BRIGHT2 (FSRD, 'H', 2, NULL , &States[S_FSWORDATK+5], 5, 36), // S_FSWORDATK_5
S_BRIGHT2 (FSRD, 'I', 2, NULL , &States[S_FSWORDATK+6], 5, 36), // S_FSWORDATK_6
S_BRIGHT2 (FSRD, 'I', 10, NULL , &States[S_FSWORDATK+7], 5, 150), // S_FSWORDATK_7
S_BRIGHT2 (FSRD, 'A', 1, NULL , &States[S_FSWORDATK+8], 5, 60), // S_FSWORDATK_8
S_BRIGHT2 (FSRD, 'B', 1, NULL , &States[S_FSWORDATK+9], 5, 55), // S_FSWORDATK_9
S_BRIGHT2 (FSRD, 'C', 1, NULL , &States[S_FSWORDATK+10], 5, 50), // S_FSWORDATK_10
S_BRIGHT2 (FSRD, 'A', 1, NULL , &States[S_FSWORDATK+11], 5, 45), // S_FSWORDATK_11
S_BRIGHT2 (FSRD, 'B', 1, NULL , &States[S_FSWORDREADY], 5, 40), // S_FSWORDATK_12
};
IMPLEMENT_ACTOR (AFWeapQuietus, Hexen, -1, 0)
PROP_Flags (MF_SPECIAL)
PROP_SpawnState (0)
PROP_Weapon_SelectionOrder (2900)
PROP_Weapon_Flags (WIF_PRIMARY_USES_BOTH)
PROP_Weapon_AmmoUse1 (14)
PROP_Weapon_AmmoUse2 (14)
PROP_Weapon_AmmoGive1 (0)
PROP_Weapon_AmmoGive2 (0)
PROP_Weapon_UpState (S_FSWORDUP)
PROP_Weapon_DownState (S_FSWORDDOWN)
PROP_Weapon_ReadyState (S_FSWORDREADY)
PROP_Weapon_AtkState (S_FSWORDATK)
PROP_Weapon_Kickback (150)
PROP_Weapon_YAdjust (10)
PROP_Weapon_MoveCombatDist (20000000)
PROP_Weapon_AmmoType1 ("Mana1")
PROP_Weapon_AmmoType2 ("Mana2")
PROP_Weapon_ProjectileType ("FSwordMissile")
PROP_Inventory_PickupMessage("$TXT_WEAPON_F4")
END_DEFAULTS
// Fighter Sword Missile ----------------------------------------------------
class AFSwordMissile : public AActor
{
DECLARE_ACTOR (AFSwordMissile, AActor)
public:
void GetExplodeParms (int &damage, int &dist, bool &hurtSource);
int DoSpecialDamage(AActor *victim, AActor *source, int damage);
};
FState AFSwordMissile::States[] =
{
#define S_FSWORD_MISSILE1 0
S_BRIGHT (FSFX, 'A', 3, NULL , &States[S_FSWORD_MISSILE1+1]),
S_BRIGHT (FSFX, 'B', 3, NULL , &States[S_FSWORD_MISSILE1+2]),
S_BRIGHT (FSFX, 'C', 3, NULL , &States[S_FSWORD_MISSILE1]),
#define S_FSWORD_MISSILE_X1 (S_FSWORD_MISSILE1+3)
S_BRIGHT (FSFX, 'D', 4, NULL , &States[S_FSWORD_MISSILE_X1+1]),
S_BRIGHT (FSFX, 'E', 3, A_FSwordFlames , &States[S_FSWORD_MISSILE_X1+2]),
S_BRIGHT (FSFX, 'F', 4, A_Explode , &States[S_FSWORD_MISSILE_X1+3]),
S_BRIGHT (FSFX, 'G', 3, NULL , &States[S_FSWORD_MISSILE_X1+4]),
S_BRIGHT (FSFX, 'H', 4, NULL , &States[S_FSWORD_MISSILE_X1+5]),
S_BRIGHT (FSFX, 'I', 3, NULL , &States[S_FSWORD_MISSILE_X1+6]),
S_BRIGHT (FSFX, 'J', 4, NULL , &States[S_FSWORD_MISSILE_X1+7]),
S_BRIGHT (FSFX, 'K', 3, NULL , &States[S_FSWORD_MISSILE_X1+8]),
S_BRIGHT (FSFX, 'L', 3, NULL , &States[S_FSWORD_MISSILE_X1+9]),
S_BRIGHT (FSFX, 'M', 3, NULL , NULL),
};
IMPLEMENT_ACTOR (AFSwordMissile, Hexen, -1, 0)
PROP_SpeedFixed (30)
PROP_RadiusFixed (16)
PROP_HeightFixed (8)
PROP_Damage (8)
PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE)
PROP_Flags2 (MF2_NOTELEPORT|MF2_IMPACT|MF2_PCROSS)
PROP_Flags4 (MF4_EXTREMEDEATH)
PROP_RenderStyle (STYLE_Add)
PROP_SpawnState (S_FSWORD_MISSILE1)
PROP_DeathState (S_FSWORD_MISSILE_X1)
PROP_DeathSound ("FighterSwordExplode")
END_DEFAULTS
void AFSwordMissile::GetExplodeParms (int &damage, int &dist, bool &hurtSource)
{
damage = 64;
hurtSource = false;
}
int AFSwordMissile::DoSpecialDamage(AActor *victim, AActor *source, int damage)
{
if (victim->player)
{
damage -= damage >> 2;
}
return damage;
}
// Fighter Sword Flame ------------------------------------------------------
class AFSwordFlame : public AActor
{
DECLARE_ACTOR (AFSwordFlame, AActor)
};
FState AFSwordFlame::States[] =
{
S_BRIGHT (FSFX, 'N', 3, NULL , &States[1]),
S_BRIGHT (FSFX, 'O', 3, NULL , &States[2]),
S_BRIGHT (FSFX, 'P', 3, NULL , &States[3]),
S_BRIGHT (FSFX, 'Q', 3, NULL , &States[4]),
S_BRIGHT (FSFX, 'R', 3, NULL , &States[5]),
S_BRIGHT (FSFX, 'S', 3, NULL , &States[6]),
S_BRIGHT (FSFX, 'T', 3, NULL , &States[7]),
S_BRIGHT (FSFX, 'U', 3, NULL , &States[8]),
S_BRIGHT (FSFX, 'V', 3, NULL , &States[9]),
S_BRIGHT (FSFX, 'W', 3, NULL , NULL),
};
IMPLEMENT_ACTOR (AFSwordFlame, Hexen, -1, 0)
PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY)
PROP_RenderStyle (STYLE_Translucent)
PROP_Alpha (HX_SHADOW)
PROP_SpawnState (0)
END_DEFAULTS
//============================================================================
//
// A_FSwordAttack
//
//============================================================================
void A_FSwordAttack (AActor *actor)
{
player_t *player;
if (NULL == (player = actor->player))
{
return;
}
AWeapon *weapon = actor->player->ReadyWeapon;
if (weapon != NULL)
{
if (!weapon->DepleteAmmo (weapon->bAltFire))
return;
}
P_SpawnPlayerMissile (actor, 0, 0, -10*FRACUNIT, RUNTIME_CLASS(AFSwordMissile), actor->angle+ANGLE_45/4);
P_SpawnPlayerMissile (actor, 0, 0, -5*FRACUNIT, RUNTIME_CLASS(AFSwordMissile), actor->angle+ANGLE_45/8);
P_SpawnPlayerMissile (actor, 0, 0, 0, RUNTIME_CLASS(AFSwordMissile), actor->angle);
P_SpawnPlayerMissile (actor, 0, 0, 5*FRACUNIT, RUNTIME_CLASS(AFSwordMissile), actor->angle-ANGLE_45/8);
P_SpawnPlayerMissile (actor, 0, 0, 10*FRACUNIT, RUNTIME_CLASS(AFSwordMissile), actor->angle-ANGLE_45/4);
S_Sound (actor, CHAN_WEAPON, "FighterSwordFire", 1, ATTN_NORM);
}
//============================================================================
//
// A_FSwordAttack2
//
//============================================================================
void A_FSwordAttack2 (AActor *actor)
{
angle_t angle = actor->angle;
P_SpawnMissileAngle (actor, RUNTIME_CLASS(AFSwordMissile), angle+ANG45/4, 0);
P_SpawnMissileAngle (actor, RUNTIME_CLASS(AFSwordMissile), angle+ANG45/8, 0);
P_SpawnMissileAngle (actor, RUNTIME_CLASS(AFSwordMissile), angle, 0);
P_SpawnMissileAngle (actor, RUNTIME_CLASS(AFSwordMissile), angle-ANG45/8, 0);
P_SpawnMissileAngle (actor, RUNTIME_CLASS(AFSwordMissile), angle-ANG45/4, 0);
S_Sound (actor, CHAN_WEAPON, "FighterSwordFire", 1, ATTN_NORM);
}
//============================================================================
//
// A_FSwordFlames
//
//============================================================================
void A_FSwordFlames (AActor *actor)
{
int i;
for (i = 1+(pr_fswordflame()&3); i; i--)
{
fixed_t x = actor->x+((pr_fswordflame()-128)<<12);
fixed_t y = actor->y+((pr_fswordflame()-128)<<12);
fixed_t z = actor->z+((pr_fswordflame()-128)<<11);
Spawn<AFSwordFlame> (x, y, z, ALLOW_REPLACE);
}
}
//============================================================================
//
// A_DropQuietusPieces
//
//============================================================================
void A_DropQuietusPieces (AActor *actor)
{
static const PClass *pieces[3] =
{
RUNTIME_CLASS(AFWeaponPiece1),
RUNTIME_CLASS(AFWeaponPiece2),
RUNTIME_CLASS(AFWeaponPiece3)
};
for (int i = 0, j = 0, fineang = 0; i < 3; ++i)
{
AActor *piece = Spawn (pieces[j], actor->x, actor->y, actor->z, ALLOW_REPLACE);
if (piece != NULL)
{
piece->momx = actor->momx + finecosine[fineang];
piece->momy = actor->momy + finesine[fineang];
piece->momz = actor->momz;
piece->flags |= MF_DROPPED;
fineang += FINEANGLES/3;
j = (j == 0) ? (pr_quietusdrop() & 1) + 1 : 3-j;
}
}
}
void AFighterWeaponPiece::BeginPlay ()
{
Super::BeginPlay ();
FourthWeaponClass = RUNTIME_CLASS(AFWeapQuietus);
}