mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-12-17 16:01:00 +00:00
a6a5821f04
powerup. - Changed: Weapons are no longer checked for the EXTREMEDEATH and NOEXTREMEDEATH flags. For all damage related actions it will always be the projectile (or puff for hitscan attacks) that is treated as the damage inflictor. - Fixed: Hexen's fourth weapons made extreme death depend on the weapon the player is holding, not the projectile that did the kill. The WIF_EXTREME_DEATH flag no longer exists as a result. - Expanded PowerSpeed so that subclasses can be derived that alter the speed factor. - Added an MF5_USESPECIAL flag that allows using things to execute their specials. - added MF4_FORCERADIUSDMG flag so that exploding items can be created which are able to hurt boss monsters. - moved ML_BLOCK_PLAYERS to the value 0x4000 to bring it in line with Skulltag's implementation. SVN r530 (trunk)
388 lines
13 KiB
C++
388 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);
|
|
};
|
|
|
|
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;
|
|
}
|
|
|
|
// 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);
|
|
}
|