More features for custom melee weapon

This commit is contained in:
Peter Covington 2022-04-20 03:41:32 -04:00
parent fa41a327e7
commit 31cd394cb7
3 changed files with 182 additions and 21 deletions

View File

@ -28,6 +28,15 @@
IMPLEMENT_SERVERCLASS_ST( CBaseHLBludgeonWeapon, DT_BaseHLBludgeonWeapon )
END_SEND_TABLE()
#ifdef MAPBASE
BEGIN_DATADESC(CBaseHLBludgeonWeapon)
DEFINE_FIELD(m_flDelayedFire, FIELD_TIME),
DEFINE_FIELD(m_bShotDelayed, FIELD_BOOLEAN),
END_DATADESC()
#endif // MAPBASE
#define BLUDGEON_HULL_DIM 16
static const Vector g_bludgeonMins(-BLUDGEON_HULL_DIM,-BLUDGEON_HULL_DIM,-BLUDGEON_HULL_DIM);
@ -39,6 +48,9 @@ static const Vector g_bludgeonMaxs(BLUDGEON_HULL_DIM,BLUDGEON_HULL_DIM,BLUDGEON_
CBaseHLBludgeonWeapon::CBaseHLBludgeonWeapon()
{
m_bFiresUnderwater = true;
#ifdef MAPBASE
m_bShotDelayed = false;
#endif // MAPBASE
}
//-----------------------------------------------------------------------------
@ -96,11 +108,19 @@ void CBaseHLBludgeonWeapon::ItemPostFrame( void )
#ifdef MAPBASE
if (pOwner->HasSpawnFlags( SF_PLAYER_SUPPRESS_FIRING ))
{
m_bShotDelayed = false;
WeaponIdle();
return;
}
#endif
// See if we need to fire off our secondary round
if (m_bShotDelayed)
{
if (gpGlobals->curtime > m_flDelayedFire)
DelayedAttack();
}
else
#endif
if ( (pOwner->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime) )
{
PrimaryAttack();
@ -239,7 +259,7 @@ Activity CBaseHLBludgeonWeapon::ChooseIntersectionPointAndActivity( trace_t &hit
}
return ACT_VM_HITCENTER;
return GetPrimaryAttackActivity();
}
//-----------------------------------------------------------------------------
@ -297,7 +317,6 @@ void CBaseHLBludgeonWeapon::ImpactEffect( trace_t &traceHit )
UTIL_ImpactTrace( &traceHit, DMG_CLUB );
}
//------------------------------------------------------------------------------
// Purpose : Starts the swing of the weapon and determines the animation
// Input : bIsSecondary - is this a secondary attack?
@ -320,10 +339,14 @@ void CBaseHLBludgeonWeapon::Swing( int bIsSecondary )
Vector swingEnd = swingStart + forward * GetRange();
UTIL_TraceLine( swingStart, swingEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &traceHit );
Activity nHitActivity = ACT_VM_HITCENTER;
Activity nHitActivity = GetPrimaryAttackActivity();
// Like bullets, bludgeon traces have to trace against triggers.
CTakeDamageInfo triggerInfo( GetOwner(), GetOwner(), GetDamageForActivity( nHitActivity ), DMG_CLUB );
#ifdef MAPBASE
CTakeDamageInfo triggerInfo(GetOwner(), GetOwner(), GetDamageForActivity(nHitActivity), GetDamageType());
#else
CTakeDamageInfo triggerInfo(GetOwner(), GetOwner(), GetDamageForActivity(nHitActivity), DMG_CLUB);
#endif // MAPBASE
triggerInfo.SetDamagePosition( traceHit.startpos );
triggerInfo.SetDamageForce( forward );
TraceAttackToTriggers( triggerInfo, traceHit.startpos, traceHit.endpos, forward );
@ -374,31 +397,20 @@ void CBaseHLBludgeonWeapon::Swing( int bIsSecondary )
{
nHitActivity = bIsSecondary ? ACT_VM_MISSCENTER2 : ACT_VM_MISSCENTER;
#ifndef MAPBASE
// We want to test the first swing again
Vector testEnd = swingStart + forward * GetRange();
#ifdef MAPBASE
// Sound has been moved here since we're using the other melee sounds now
WeaponSound( SINGLE );
#endif
// See if we happened to hit water
ImpactWater( swingStart, testEnd );
ImpactWater(swingStart, testEnd);
#endif // !MAPBASE
}
#ifndef MAPBASE
else
{
#ifdef MAPBASE
// Other melee sounds
if (traceHit.m_pEnt && traceHit.m_pEnt->IsWorld())
WeaponSound(MELEE_HIT_WORLD);
else if (traceHit.m_pEnt && !traceHit.m_pEnt->PassesDamageFilter(triggerInfo))
WeaponSound(MELEE_MISS);
else
WeaponSound(MELEE_HIT);
#endif
Hit( traceHit, nHitActivity, bIsSecondary ? true : false );
}
#endif
// Send the anim
SendWeaponAnim( nHitActivity );
@ -414,5 +426,125 @@ void CBaseHLBludgeonWeapon::Swing( int bIsSecondary )
#ifdef MAPBASE
pOwner->SetAnimation( PLAYER_ATTACK1 );
if (GetHitDelay() > 0.f)
{
//Play swing sound
WeaponSound(SINGLE);
m_flDelayedFire = gpGlobals->curtime + GetHitDelay();
m_bShotDelayed = true;
}
else
{
if (traceHit.fraction == 1.0f)
{
// We want to test the first swing again
Vector testEnd = swingStart + forward * GetRange();
//Play swing sound
WeaponSound(SINGLE);
// See if we happened to hit water
ImpactWater(swingStart, testEnd);
}
else
{
// Other melee sounds
if (traceHit.m_pEnt && traceHit.m_pEnt->IsWorld())
WeaponSound(MELEE_HIT_WORLD);
else if (traceHit.m_pEnt && !traceHit.m_pEnt->PassesDamageFilter(triggerInfo))
WeaponSound(MELEE_MISS);
else
WeaponSound(MELEE_HIT);
Hit(traceHit, nHitActivity, bIsSecondary ? true : false);
}
}
#endif
}
#ifdef MAPBASE
void CBaseHLBludgeonWeapon::DelayedAttack(void)
{
m_bShotDelayed = false;
trace_t traceHit;
// Try a ray
CBasePlayer* pOwner = ToBasePlayer(GetOwner());
if (!pOwner)
return;
pOwner->RumbleEffect(RUMBLE_CROWBAR_SWING, 0, RUMBLE_FLAG_RESTART);
Vector swingStart = pOwner->Weapon_ShootPosition();
Vector forward;
forward = pOwner->GetAutoaimVector(AUTOAIM_SCALE_DEFAULT, GetRange());
Vector swingEnd = swingStart + forward * GetRange();
UTIL_TraceLine(swingStart, swingEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &traceHit);
if (traceHit.fraction == 1.0)
{
float bludgeonHullRadius = 1.732f * BLUDGEON_HULL_DIM; // hull is +/- 16, so use cuberoot of 2 to determine how big the hull is from center to the corner point
// Back off by hull "radius"
swingEnd -= forward * bludgeonHullRadius;
UTIL_TraceHull(swingStart, swingEnd, g_bludgeonMins, g_bludgeonMaxs, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &traceHit);
if (traceHit.fraction < 1.0 && traceHit.m_pEnt)
{
Vector vecToTarget = traceHit.m_pEnt->GetAbsOrigin() - swingStart;
VectorNormalize(vecToTarget);
float dot = vecToTarget.Dot(forward);
// YWB: Make sure they are sort of facing the guy at least...
if (dot < 0.70721f)
{
// Force amiss
traceHit.fraction = 1.0f;
}
else
{
ChooseIntersectionPointAndActivity(traceHit, g_bludgeonMins, g_bludgeonMaxs, pOwner);
}
}
}
if (traceHit.fraction == 1.0f)
{
// We want to test the first swing again
Vector testEnd = swingStart + forward * GetRange();
// See if we happened to hit water
ImpactWater(swingStart, testEnd);
}
else
{
CTakeDamageInfo triggerInfo(GetOwner(), GetOwner(), GetDamageForActivity(GetActivity()), GetDamageType());
triggerInfo.SetDamagePosition(traceHit.startpos);
triggerInfo.SetDamageForce(forward);
// Other melee sounds
if (traceHit.m_pEnt && traceHit.m_pEnt->IsWorld())
WeaponSound(MELEE_HIT_WORLD);
else if (traceHit.m_pEnt && !traceHit.m_pEnt->PassesDamageFilter(triggerInfo))
WeaponSound(MELEE_MISS);
else
WeaponSound(MELEE_HIT);
Hit(traceHit, GetActivity(), false);
}
}
bool CBaseHLBludgeonWeapon::CanHolster(void)
{
if (m_bShotDelayed)
return false;
return BaseClass::CanHolster();
}
#endif // MAPBASE

View File

@ -23,6 +23,9 @@ public:
CBaseHLBludgeonWeapon();
DECLARE_SERVERCLASS();
#ifdef MAPBASE
DECLARE_DATADESC();
#endif // MAPBASE
virtual void Spawn( void );
virtual void Precache( void );
@ -30,6 +33,9 @@ public:
//Attack functions
virtual void PrimaryAttack( void );
virtual void SecondaryAttack( void );
#ifdef MAPBASE
void DelayedAttack(void);
#endif // MAPBASE
virtual void ItemPostFrame( void );
@ -46,6 +52,8 @@ public:
#ifdef MAPBASE
virtual int GetDamageType() { return DMG_CLUB; }
virtual float GetHitDelay() { return 0.f; }
virtual bool CanHolster(void);
#endif // MAPBASE
protected:
@ -56,6 +64,11 @@ private:
void Swing( int bIsSecondary );
void Hit( trace_t &traceHit, Activity nHitActivity, bool bIsSecondary );
Activity ChooseIntersectionPointAndActivity( trace_t &hitTrace, const Vector &mins, const Vector &maxs, CBasePlayer *pOwner );
#ifdef MAPBASE
float m_flDelayedFire;
bool m_bShotDelayed;
#endif // MAPBASE
};
#endif

View File

@ -55,6 +55,8 @@ typedef struct HL2CustomMeleeData_s
float m_flRefireRate;
float m_flDamage;
float m_flNPCDamage;
float m_flHitDelay;
Activity m_nHitActivity = ACT_INVALID;
byte m_nDamageClass;
bool Parse(KeyValues*);
@ -72,6 +74,7 @@ public:
float GetRange(void) { return m_CustomData.m_flMeleeRange; }
float GetFireRate(void) { return m_CustomData.m_flRefireRate; }
float GetHitDelay() { return m_CustomData.m_flHitDelay; }
void AddViewKick(void);
float GetDamageForActivity(Activity hitActivity);
@ -86,6 +89,9 @@ public:
acttable_t* GetBackupActivityList() { return NULL; }
int GetBackupActivityListCount() { return 0; }
//Functions to select animation sequences
virtual Activity GetPrimaryAttackActivity(void) { return m_CustomData.m_nHitActivity; }
const char* GetWeaponScriptName() { return m_iszWeaponScriptName.Get(); }
virtual int GetDamageType() { return g_nDamageClassTypeBits[m_CustomData.m_nDamageClass]; }
@ -116,6 +122,16 @@ bool HL2CustomMeleeData_s::Parse(KeyValues* pKVWeapon)
m_flNPCDamage = pkvData->GetFloat("damage_npc", m_flDamage);
m_flMeleeRange = pkvData->GetFloat("range", 70.f);
m_flRefireRate = pkvData->GetFloat("rate", 0.7f);
m_flHitDelay = pkvData->GetFloat("hitdelay");
if (pkvData->FindKey("activity_hit"))
{
m_nHitActivity = (Activity)ActivityList_IndexForName(pkvData->GetString("activity_hit"));
}
if (m_nHitActivity == ACT_INVALID)
{
m_nHitActivity = ACT_VM_HITCENTER;
}
const char* pszDamageClass = pkvData->GetString("damage_type", nullptr);
if (pszDamageClass)