mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-08 05:51:09 +00:00
290 lines
8.7 KiB
C++
290 lines
8.7 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 "a_action.h"
|
||
|
#include "p_pspr.h"
|
||
|
#include "gstrings.h"
|
||
|
#include "a_hexenglobal.h"
|
||
|
|
||
|
const fixed_t HAMMER_RANGE = MELEERANGE+MELEERANGE/2;
|
||
|
|
||
|
static FRandom pr_atk ("FHammerAtk");
|
||
|
|
||
|
extern void AdjustPlayerAngle (AActor *pmo);
|
||
|
|
||
|
void A_FHammerAttack (AActor *actor);
|
||
|
void A_FHammerThrow (AActor *actor);
|
||
|
void A_HammerSound (AActor *);
|
||
|
void A_BeAdditive (AActor *);
|
||
|
|
||
|
// The Fighter's Hammer -----------------------------------------------------
|
||
|
|
||
|
class AFWeapHammer : public AFighterWeapon
|
||
|
{
|
||
|
DECLARE_ACTOR (AFWeapHammer, AFighterWeapon)
|
||
|
public:
|
||
|
const char *PickupMessage ()
|
||
|
{
|
||
|
return GStrings("TXT_WEAPON_F3");
|
||
|
}
|
||
|
};
|
||
|
|
||
|
FState AFWeapHammer::States[] =
|
||
|
{
|
||
|
#define S_HAMM 0
|
||
|
S_NORMAL (WFHM, 'A', -1, NULL , NULL),
|
||
|
|
||
|
#define S_FHAMMERREADY (S_HAMM+1)
|
||
|
S_NORMAL (FHMR, 'A', 1, A_WeaponReady , &States[S_FHAMMERREADY]),
|
||
|
|
||
|
#define S_FHAMMERDOWN (S_FHAMMERREADY+1)
|
||
|
S_NORMAL (FHMR, 'A', 1, A_Lower , &States[S_FHAMMERDOWN]),
|
||
|
|
||
|
#define S_FHAMMERUP (S_FHAMMERDOWN+1)
|
||
|
S_NORMAL (FHMR, 'A', 1, A_Raise , &States[S_FHAMMERUP]),
|
||
|
|
||
|
#define S_FHAMMERATK (S_FHAMMERUP+1)
|
||
|
S_NORMAL2 (FHMR, 'B', 6, NULL , &States[S_FHAMMERATK+1], 5, 0),
|
||
|
S_NORMAL2 (FHMR, 'C', 3, A_FHammerAttack , &States[S_FHAMMERATK+2], 5, 0),
|
||
|
S_NORMAL2 (FHMR, 'D', 3, NULL , &States[S_FHAMMERATK+3], 5, 0),
|
||
|
S_NORMAL2 (FHMR, 'E', 2, NULL , &States[S_FHAMMERATK+4], 5, 0),
|
||
|
S_NORMAL2 (FHMR, 'E', 10, A_FHammerThrow , &States[S_FHAMMERATK+5], 5, 150),
|
||
|
S_NORMAL2 (FHMR, 'A', 1, NULL , &States[S_FHAMMERATK+6], 0, 60),
|
||
|
S_NORMAL2 (FHMR, 'A', 1, NULL , &States[S_FHAMMERATK+7], 0, 55),
|
||
|
S_NORMAL2 (FHMR, 'A', 1, NULL , &States[S_FHAMMERATK+8], 0, 50),
|
||
|
S_NORMAL2 (FHMR, 'A', 1, NULL , &States[S_FHAMMERATK+9], 0, 45),
|
||
|
S_NORMAL2 (FHMR, 'A', 1, NULL , &States[S_FHAMMERATK+10], 0, 40),
|
||
|
S_NORMAL2 (FHMR, 'A', 1, NULL , &States[S_FHAMMERATK+11], 0, 35),
|
||
|
S_NORMAL (FHMR, 'A', 1, NULL , &States[S_FHAMMERREADY]),
|
||
|
};
|
||
|
|
||
|
IMPLEMENT_ACTOR (AFWeapHammer, Hexen, 123, 28)
|
||
|
PROP_Flags (MF_SPECIAL)
|
||
|
PROP_SpawnState (S_HAMM)
|
||
|
|
||
|
PROP_Weapon_SelectionOrder (900)
|
||
|
PROP_Weapon_Flags (WIF_AMMO_OPTIONAL|WIF_BOT_MELEE)
|
||
|
PROP_Weapon_AmmoUse1 (3)
|
||
|
PROP_Weapon_AmmoGive1 (25)
|
||
|
PROP_Weapon_UpState (S_FHAMMERUP)
|
||
|
PROP_Weapon_DownState (S_FHAMMERDOWN)
|
||
|
PROP_Weapon_ReadyState (S_FHAMMERREADY)
|
||
|
PROP_Weapon_AtkState (S_FHAMMERATK)
|
||
|
PROP_Weapon_HoldAtkState (S_FHAMMERATK)
|
||
|
PROP_Weapon_Kickback (150)
|
||
|
PROP_Weapon_YAdjust (0-10)
|
||
|
PROP_Weapon_MoveCombatDist (22000000)
|
||
|
PROP_Weapon_AmmoType1 ("Mana2")
|
||
|
PROP_Weapon_ProjectileType ("HammerMissile")
|
||
|
END_DEFAULTS
|
||
|
|
||
|
// Hammer Missile -----------------------------------------------------------
|
||
|
|
||
|
class AHammerMissile : public AActor
|
||
|
{
|
||
|
DECLARE_ACTOR (AHammerMissile, AActor)
|
||
|
public:
|
||
|
void GetExplodeParms (int &damage, int &dist, bool &hurtSource);
|
||
|
};
|
||
|
|
||
|
FState AHammerMissile::States[] =
|
||
|
{
|
||
|
#define S_HAMMER_MISSILE_1 0
|
||
|
S_BRIGHT (FHFX, 'A', 2, NULL , &States[S_HAMMER_MISSILE_1+1]),
|
||
|
S_BRIGHT (FHFX, 'B', 2, A_HammerSound , &States[S_HAMMER_MISSILE_1+2]),
|
||
|
S_BRIGHT (FHFX, 'C', 2, NULL , &States[S_HAMMER_MISSILE_1+3]),
|
||
|
S_BRIGHT (FHFX, 'D', 2, NULL , &States[S_HAMMER_MISSILE_1+4]),
|
||
|
S_BRIGHT (FHFX, 'E', 2, NULL , &States[S_HAMMER_MISSILE_1+5]),
|
||
|
S_BRIGHT (FHFX, 'F', 2, NULL , &States[S_HAMMER_MISSILE_1+6]),
|
||
|
S_BRIGHT (FHFX, 'G', 2, NULL , &States[S_HAMMER_MISSILE_1+7]),
|
||
|
S_BRIGHT (FHFX, 'H', 2, NULL , &States[S_HAMMER_MISSILE_1]),
|
||
|
|
||
|
#define S_HAMMER_MISSILE_X1 (S_HAMMER_MISSILE_1+8)
|
||
|
S_BRIGHT (FHFX, 'I', 3, A_BeAdditive , &States[S_HAMMER_MISSILE_X1+1]),
|
||
|
S_BRIGHT (FHFX, 'J', 3, NULL , &States[S_HAMMER_MISSILE_X1+2]),
|
||
|
S_BRIGHT (FHFX, 'K', 3, A_Explode , &States[S_HAMMER_MISSILE_X1+3]),
|
||
|
S_BRIGHT (FHFX, 'L', 3, NULL , &States[S_HAMMER_MISSILE_X1+4]),
|
||
|
S_BRIGHT (FHFX, 'M', 3, NULL , &States[S_HAMMER_MISSILE_X1+5]),
|
||
|
S_NORMAL (FHFX, 'N', 3, NULL , &States[S_HAMMER_MISSILE_X1+6]),
|
||
|
S_BRIGHT (FHFX, 'O', 3, NULL , &States[S_HAMMER_MISSILE_X1+7]),
|
||
|
S_BRIGHT (FHFX, 'P', 3, NULL , &States[S_HAMMER_MISSILE_X1+8]),
|
||
|
S_BRIGHT (FHFX, 'Q', 3, NULL , &States[S_HAMMER_MISSILE_X1+9]),
|
||
|
S_BRIGHT (FHFX, 'R', 3, NULL , NULL),
|
||
|
};
|
||
|
|
||
|
IMPLEMENT_ACTOR (AHammerMissile, Hexen, -1, 0)
|
||
|
PROP_SpeedFixed (25)
|
||
|
PROP_RadiusFixed (14)
|
||
|
PROP_HeightFixed (20)
|
||
|
PROP_Damage (10)
|
||
|
PROP_DamageType (MOD_FIRE)
|
||
|
PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE)
|
||
|
PROP_Flags2 (MF2_NOTELEPORT|MF2_IMPACT|MF2_PCROSS)
|
||
|
|
||
|
PROP_SpawnState (S_HAMMER_MISSILE_1)
|
||
|
PROP_DeathState (S_HAMMER_MISSILE_X1)
|
||
|
|
||
|
PROP_DeathSound ("FighterHammerExplode")
|
||
|
END_DEFAULTS
|
||
|
|
||
|
void AHammerMissile::GetExplodeParms (int &damage, int &dist, bool &hurtSource)
|
||
|
{
|
||
|
damage = 128;
|
||
|
hurtSource = false;
|
||
|
}
|
||
|
|
||
|
// Hammer Puff (also used by fist) ------------------------------------------
|
||
|
|
||
|
FState AHammerPuff::States[] =
|
||
|
{
|
||
|
S_NORMAL (FHFX, 'S', 4, NULL , &States[1]),
|
||
|
S_NORMAL (FHFX, 'T', 4, NULL , &States[2]),
|
||
|
S_NORMAL (FHFX, 'U', 4, NULL , &States[3]),
|
||
|
S_NORMAL (FHFX, 'V', 4, NULL , &States[4]),
|
||
|
S_NORMAL (FHFX, 'W', 4, NULL , NULL),
|
||
|
};
|
||
|
|
||
|
IMPLEMENT_ACTOR (AHammerPuff, Hexen, -1, 0)
|
||
|
PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY)
|
||
|
PROP_Flags3 (MF3_PUFFONACTORS)
|
||
|
PROP_RenderStyle (STYLE_Translucent)
|
||
|
PROP_Alpha (HX_SHADOW)
|
||
|
|
||
|
PROP_SpawnState (0)
|
||
|
|
||
|
PROP_SeeSound ("FighterHammerHitThing")
|
||
|
PROP_AttackSound ("FighterHammerHitWall")
|
||
|
PROP_ActiveSound ("FighterHammerMiss")
|
||
|
END_DEFAULTS
|
||
|
|
||
|
void AHammerPuff::BeginPlay ()
|
||
|
{
|
||
|
Super::BeginPlay ();
|
||
|
momz = FRACUNIT*8/10;
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
//
|
||
|
// A_FHammerAttack
|
||
|
//
|
||
|
//============================================================================
|
||
|
|
||
|
void A_FHammerAttack (AActor *actor)
|
||
|
{
|
||
|
angle_t angle;
|
||
|
int damage;
|
||
|
fixed_t power;
|
||
|
int slope;
|
||
|
int i;
|
||
|
player_t *player;
|
||
|
|
||
|
if (NULL == (player = actor->player))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
AActor *pmo=player->mo;
|
||
|
|
||
|
damage = 60+(pr_atk()&63);
|
||
|
power = 10*FRACUNIT;
|
||
|
for (i = 0; i < 16; i++)
|
||
|
{
|
||
|
angle = pmo->angle + i*(ANG45/32);
|
||
|
slope = P_AimLineAttack (pmo, angle, HAMMER_RANGE);
|
||
|
if (linetarget)
|
||
|
{
|
||
|
P_LineAttack (pmo, angle, HAMMER_RANGE, slope, damage, MOD_HIT, RUNTIME_CLASS(AHammerPuff));
|
||
|
AdjustPlayerAngle(pmo);
|
||
|
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
|
||
|
{
|
||
|
P_ThrustMobj (linetarget, angle, power);
|
||
|
}
|
||
|
pmo->special1 = false; // Don't throw a hammer
|
||
|
goto hammerdone;
|
||
|
}
|
||
|
angle = pmo->angle-i*(ANG45/32);
|
||
|
slope = P_AimLineAttack(pmo, angle, HAMMER_RANGE);
|
||
|
if(linetarget)
|
||
|
{
|
||
|
P_LineAttack(pmo, angle, HAMMER_RANGE, slope, damage, MOD_HIT, RUNTIME_CLASS(AHammerPuff));
|
||
|
AdjustPlayerAngle(pmo);
|
||
|
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
|
||
|
{
|
||
|
P_ThrustMobj(linetarget, angle, power);
|
||
|
}
|
||
|
pmo->special1 = false; // Don't throw a hammer
|
||
|
goto hammerdone;
|
||
|
}
|
||
|
}
|
||
|
// didn't find any targets in meleerange, so set to throw out a hammer
|
||
|
PuffSpawned = NULL;
|
||
|
angle = pmo->angle;
|
||
|
slope = P_AimLineAttack (pmo, angle, HAMMER_RANGE);
|
||
|
P_LineAttack (pmo, angle, HAMMER_RANGE, slope, damage, MOD_HIT, RUNTIME_CLASS(AHammerPuff));
|
||
|
if (PuffSpawned)
|
||
|
{
|
||
|
pmo->special1 = false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pmo->special1 = true;
|
||
|
}
|
||
|
hammerdone:
|
||
|
// Don't spawn a hammer if the player doesn't have enough mana
|
||
|
if (player->ReadyWeapon == NULL ||
|
||
|
!player->ReadyWeapon->CheckAmmo (player->ReadyWeapon->bAltFire ?
|
||
|
AWeapon::AltFire : AWeapon::PrimaryFire, false, true))
|
||
|
{
|
||
|
pmo->special1 = false;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
//
|
||
|
// A_FHammerThrow
|
||
|
//
|
||
|
//============================================================================
|
||
|
|
||
|
void A_FHammerThrow (AActor *actor)
|
||
|
{
|
||
|
AActor *mo;
|
||
|
player_t *player;
|
||
|
|
||
|
if (NULL == (player = actor->player))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!player->mo->special1)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
AWeapon *weapon = player->ReadyWeapon;
|
||
|
if (weapon != NULL)
|
||
|
{
|
||
|
if (!weapon->DepleteAmmo (weapon->bAltFire, false))
|
||
|
return;
|
||
|
}
|
||
|
mo = P_SpawnPlayerMissile (player->mo, RUNTIME_CLASS(AHammerMissile));
|
||
|
if (mo)
|
||
|
{
|
||
|
mo->special1 = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//============================================================================
|
||
|
//
|
||
|
// A_HammerSound
|
||
|
//
|
||
|
//============================================================================
|
||
|
|
||
|
void A_HammerSound (AActor *actor)
|
||
|
{
|
||
|
S_Sound (actor, CHAN_BODY, "FighterHammerContinuous", 1, ATTN_NORM);
|
||
|
}
|