diff options
Diffstat (limited to 'game/server/hl1/hl1_weapon_crowbar.cpp')
| -rw-r--r-- | game/server/hl1/hl1_weapon_crowbar.cpp | 379 |
1 files changed, 379 insertions, 0 deletions
diff --git a/game/server/hl1/hl1_weapon_crowbar.cpp b/game/server/hl1/hl1_weapon_crowbar.cpp new file mode 100644 index 0000000..f11f640 --- /dev/null +++ b/game/server/hl1/hl1_weapon_crowbar.cpp @@ -0,0 +1,379 @@ +//========= 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 ); +} |