You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
379 lines
10 KiB
379 lines
10 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: Crowbar - an old favorite |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "hl1mp_basecombatweapon_shared.h" |
|
|
|
#ifdef CLIENT_DLL |
|
#include "c_baseplayer.h" |
|
#include "fx_impact.h" |
|
#include "fx.h" |
|
#else |
|
#include "player.h" |
|
#include "soundent.h" |
|
#endif |
|
|
|
#include "gamerules.h" |
|
#include "ammodef.h" |
|
#include "mathlib/mathlib.h" |
|
#include "in_buttons.h" |
|
|
|
#include "vstdlib/random.h" |
|
|
|
extern ConVar sk_plr_dmg_crowbar; |
|
|
|
#define CROWBAR_RANGE 64.0f |
|
#define CROWBAR_REFIRE_MISS 0.5f |
|
#define CROWBAR_REFIRE_HIT 0.25f |
|
|
|
|
|
#ifdef CLIENT_DLL |
|
#define CWeaponCrowbar C_WeaponCrowbar |
|
#endif |
|
|
|
//----------------------------------------------------------------------------- |
|
// CWeaponCrowbar |
|
//----------------------------------------------------------------------------- |
|
|
|
class CWeaponCrowbar : public CBaseHL1MPCombatWeapon |
|
{ |
|
DECLARE_CLASS( CWeaponCrowbar, CBaseHL1MPCombatWeapon ); |
|
public: |
|
DECLARE_NETWORKCLASS(); |
|
DECLARE_PREDICTABLE(); |
|
#ifndef CLIENT_DLL |
|
DECLARE_DATADESC(); |
|
#endif |
|
|
|
CWeaponCrowbar(); |
|
|
|
void Precache( void ); |
|
virtual void ItemPostFrame( void ); |
|
void PrimaryAttack( void ); |
|
|
|
public: |
|
trace_t m_traceHit; |
|
Activity m_nHitActivity; |
|
|
|
private: |
|
virtual void Swing( void ); |
|
virtual void Hit( void ); |
|
virtual void ImpactEffect( void ); |
|
void ImpactSound( CBaseEntity *pHitEntity ); |
|
virtual Activity ChooseIntersectionPointAndActivity( trace_t &hitTrace, const Vector &mins, const Vector &maxs, CBasePlayer *pOwner ); |
|
|
|
public: |
|
|
|
}; |
|
|
|
IMPLEMENT_NETWORKCLASS_ALIASED( WeaponCrowbar, DT_WeaponCrowbar ); |
|
|
|
BEGIN_NETWORK_TABLE( CWeaponCrowbar, DT_WeaponCrowbar ) |
|
/// what |
|
END_NETWORK_TABLE() |
|
|
|
BEGIN_PREDICTION_DATA( CWeaponCrowbar ) |
|
END_PREDICTION_DATA() |
|
|
|
LINK_ENTITY_TO_CLASS( weapon_crowbar, CWeaponCrowbar ); |
|
PRECACHE_WEAPON_REGISTER( weapon_crowbar ); |
|
|
|
#ifndef CLIENT_DLL |
|
BEGIN_DATADESC( CWeaponCrowbar ) |
|
|
|
// DEFINE_FIELD( m_trLineHit, trace_t ), |
|
// DEFINE_FIELD( m_trHullHit, trace_t ), |
|
// DEFINE_FIELD( m_nHitActivity, FIELD_INTEGER ), |
|
// DEFINE_FIELD( m_traceHit, trace_t ), |
|
|
|
// Class CWeaponCrowbar: |
|
// DEFINE_FIELD( m_nHitActivity, FIELD_INTEGER ), |
|
|
|
// Function Pointers |
|
DEFINE_FUNCTION( Hit ), |
|
|
|
END_DATADESC() |
|
#endif |
|
|
|
#define BLUDGEON_HULL_DIM 16 |
|
|
|
static const Vector g_bludgeonMins(-BLUDGEON_HULL_DIM,-BLUDGEON_HULL_DIM,-BLUDGEON_HULL_DIM); |
|
static const Vector g_bludgeonMaxs(BLUDGEON_HULL_DIM,BLUDGEON_HULL_DIM,BLUDGEON_HULL_DIM); |
|
|
|
//----------------------------------------------------------------------------- |
|
// Constructor |
|
//----------------------------------------------------------------------------- |
|
CWeaponCrowbar::CWeaponCrowbar() |
|
{ |
|
m_bFiresUnderwater = true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Precache the weapon |
|
//----------------------------------------------------------------------------- |
|
void CWeaponCrowbar::Precache( void ) |
|
{ |
|
//Call base class first |
|
BaseClass::Precache(); |
|
} |
|
|
|
//------------------------------------------------------------------------------ |
|
// Purpose : Update weapon |
|
//------------------------------------------------------------------------------ |
|
void CWeaponCrowbar::ItemPostFrame( void ) |
|
{ |
|
CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); |
|
|
|
if ( pOwner == NULL ) |
|
return; |
|
|
|
if ( (pOwner->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime) ) |
|
{ |
|
PrimaryAttack(); |
|
} |
|
else |
|
{ |
|
WeaponIdle(); |
|
return; |
|
} |
|
} |
|
|
|
//------------------------------------------------------------------------------ |
|
// Purpose : |
|
// Input : |
|
// Output : |
|
//------------------------------------------------------------------------------ |
|
void CWeaponCrowbar::PrimaryAttack() |
|
{ |
|
Swing(); |
|
} |
|
|
|
|
|
//------------------------------------------------------------------------------ |
|
// Purpose: Implement impact function |
|
//------------------------------------------------------------------------------ |
|
void CWeaponCrowbar::Hit( void ) |
|
{ |
|
//Make sound for the AI |
|
#ifndef CLIENT_DLL |
|
|
|
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() ); |
|
|
|
CSoundEnt::InsertSound( SOUND_BULLET_IMPACT, m_traceHit.endpos, 400, 0.2f, pPlayer ); |
|
|
|
CBaseEntity *pHitEntity = m_traceHit.m_pEnt; |
|
|
|
//Apply damage to a hit target |
|
if ( pHitEntity != NULL ) |
|
{ |
|
Vector hitDirection; |
|
pPlayer->EyeVectors( &hitDirection, NULL, NULL ); |
|
VectorNormalize( hitDirection ); |
|
|
|
ClearMultiDamage(); |
|
CTakeDamageInfo info( GetOwner(), GetOwner(), sk_plr_dmg_crowbar.GetFloat(), DMG_CLUB ); |
|
CalculateMeleeDamageForce( &info, hitDirection, m_traceHit.endpos ); |
|
pHitEntity->DispatchTraceAttack( info, hitDirection, &m_traceHit ); |
|
ApplyMultiDamage(); |
|
|
|
// Now hit all triggers along the ray that... |
|
TraceAttackToTriggers( CTakeDamageInfo( GetOwner(), GetOwner(), sk_plr_dmg_crowbar.GetFloat(), DMG_CLUB ), m_traceHit.startpos, m_traceHit.endpos, hitDirection ); |
|
|
|
//Play an impact sound |
|
ImpactSound( pHitEntity ); |
|
} |
|
#endif |
|
|
|
//Apply an impact effect |
|
ImpactEffect(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Play the impact sound |
|
// Input : pHitEntity - entity that we hit |
|
// assumes pHitEntity is not null |
|
//----------------------------------------------------------------------------- |
|
void CWeaponCrowbar::ImpactSound( CBaseEntity *pHitEntity ) |
|
{ |
|
bool bIsWorld = ( pHitEntity->entindex() == 0 ); |
|
#ifndef CLIENT_DLL |
|
if ( !bIsWorld ) |
|
{ |
|
bIsWorld |= pHitEntity->Classify() == CLASS_NONE || pHitEntity->Classify() == CLASS_MACHINE; |
|
} |
|
#endif |
|
|
|
if( bIsWorld ) |
|
{ |
|
WeaponSound( MELEE_HIT_WORLD ); |
|
} |
|
else |
|
{ |
|
WeaponSound( MELEE_HIT ); |
|
} |
|
} |
|
|
|
Activity CWeaponCrowbar::ChooseIntersectionPointAndActivity( trace_t &hitTrace, const Vector &mins, const Vector &maxs, CBasePlayer *pOwner ) |
|
{ |
|
int i, j, k; |
|
float distance; |
|
const float *minmaxs[2] = {mins.Base(), maxs.Base()}; |
|
trace_t tmpTrace; |
|
Vector vecHullEnd = hitTrace.endpos; |
|
Vector vecEnd; |
|
|
|
distance = 1e6f; |
|
Vector vecSrc = hitTrace.startpos; |
|
|
|
vecHullEnd = vecSrc + ((vecHullEnd - vecSrc)*2); |
|
UTIL_TraceLine( vecSrc, vecHullEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &tmpTrace ); |
|
if ( tmpTrace.fraction == 1.0 ) |
|
{ |
|
for ( i = 0; i < 2; i++ ) |
|
{ |
|
for ( j = 0; j < 2; j++ ) |
|
{ |
|
for ( k = 0; k < 2; k++ ) |
|
{ |
|
vecEnd.x = vecHullEnd.x + minmaxs[i][0]; |
|
vecEnd.y = vecHullEnd.y + minmaxs[j][1]; |
|
vecEnd.z = vecHullEnd.z + minmaxs[k][2]; |
|
|
|
UTIL_TraceLine( vecSrc, vecEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &tmpTrace ); |
|
if ( tmpTrace.fraction < 1.0 ) |
|
{ |
|
float thisDistance = (tmpTrace.endpos - vecSrc).Length(); |
|
if ( thisDistance < distance ) |
|
{ |
|
hitTrace = tmpTrace; |
|
distance = thisDistance; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
hitTrace = tmpTrace; |
|
} |
|
|
|
|
|
return ACT_VM_HITCENTER; |
|
} |
|
|
|
#ifdef HL1MP_CLIENT_DLL |
|
//----------------------------------------------------------------------------- |
|
// Purpose: Handle jeep impacts |
|
//----------------------------------------------------------------------------- |
|
void ImpactCrowbarCallback( const CEffectData &data ) |
|
{ |
|
trace_t tr; |
|
Vector vecOrigin, vecStart, vecShotDir; |
|
int iMaterial, iDamageType, iHitbox; |
|
short nSurfaceProp; |
|
C_BaseEntity *pEntity = ParseImpactData( data, &vecOrigin, &vecStart, &vecShotDir, nSurfaceProp, iMaterial, iDamageType, iHitbox ); |
|
|
|
bool bIsWorld = ( pEntity->entindex() == 0 ); |
|
|
|
if ( !pEntity ) |
|
{ |
|
// This happens for impacts that occur on an object that's then destroyed. |
|
// Clear out the fraction so it uses the server's data |
|
tr.fraction = 1.0; |
|
GetActiveWeapon()->WeaponSound( bIsWorld ? MELEE_HIT_WORLD : MELEE_HIT ); |
|
return; |
|
} |
|
|
|
// If we hit, perform our custom effects and play the sound |
|
if ( Impact( vecOrigin, vecStart, iMaterial, iDamageType, iHitbox, pEntity, tr ) ) |
|
{ |
|
// Check for custom effects based on the Decal index |
|
PerformCustomEffects( vecOrigin, tr, vecShotDir, iMaterial, 2 ); |
|
} |
|
|
|
GetActiveWeapon()->WeaponSound( bIsWorld ? MELEE_HIT_WORLD : MELEE_HIT ); |
|
} |
|
|
|
DECLARE_CLIENT_EFFECT( "ImpactCrowbar", ImpactCrowbarCallback ); |
|
|
|
#endif |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CWeaponCrowbar::ImpactEffect( void ) |
|
{ |
|
//FIXME: need new decals |
|
#ifdef HL1MP_CLIENT_DLL |
|
// in hl1mp force the basic crowbar sound |
|
UTIL_ImpactTrace( &m_traceHit, DMG_CLUB, "ImpactCrowbar" ); |
|
#else |
|
UTIL_ImpactTrace( &m_traceHit, DMG_CLUB ); |
|
#endif |
|
} |
|
|
|
//------------------------------------------------------------------------------ |
|
// Purpose : Starts the swing of the weapon and determines the animation |
|
//------------------------------------------------------------------------------ |
|
void CWeaponCrowbar::Swing( void ) |
|
{ |
|
// Try a ray |
|
CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); |
|
if ( !pOwner ) |
|
return; |
|
|
|
Vector swingStart = pOwner->Weapon_ShootPosition( ); |
|
Vector forward; |
|
|
|
pOwner->EyeVectors( &forward, NULL, NULL ); |
|
|
|
Vector swingEnd = swingStart + forward * CROWBAR_RANGE; |
|
|
|
UTIL_TraceLine( swingStart, swingEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &m_traceHit ); |
|
m_nHitActivity = ACT_VM_HITCENTER; |
|
|
|
if ( m_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, &m_traceHit ); |
|
if ( m_traceHit.fraction < 1.0 ) |
|
{ |
|
m_nHitActivity = ChooseIntersectionPointAndActivity( m_traceHit, g_bludgeonMins, g_bludgeonMaxs, pOwner ); |
|
} |
|
} |
|
|
|
|
|
// ------------------------- |
|
// Miss |
|
// ------------------------- |
|
if ( m_traceHit.fraction == 1.0f ) |
|
{ |
|
m_nHitActivity = ACT_VM_MISSCENTER; |
|
|
|
//Play swing sound |
|
WeaponSound( SINGLE ); |
|
|
|
//Setup our next attack times |
|
m_flNextPrimaryAttack = gpGlobals->curtime + CROWBAR_REFIRE_MISS; |
|
} |
|
else |
|
{ |
|
Hit(); |
|
|
|
//Setup our next attack times |
|
m_flNextPrimaryAttack = gpGlobals->curtime + CROWBAR_REFIRE_HIT; |
|
} |
|
|
|
//Send the anim |
|
SendWeaponAnim( m_nHitActivity ); |
|
pOwner->SetAnimation( PLAYER_ATTACK1 ); |
|
}
|
|
|