diff options
| author | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
|---|---|---|
| committer | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
| commit | 39ed87570bdb2f86969d4be821c94b722dc71179 (patch) | |
| tree | abc53757f75f40c80278e87650ea92808274aa59 /sp/src/game/shared/sdk/sdk_weapon_melee.cpp | |
| download | source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip | |
First version of the SOurce SDK 2013
Diffstat (limited to 'sp/src/game/shared/sdk/sdk_weapon_melee.cpp')
| -rw-r--r-- | sp/src/game/shared/sdk/sdk_weapon_melee.cpp | 363 |
1 files changed, 363 insertions, 0 deletions
diff --git a/sp/src/game/shared/sdk/sdk_weapon_melee.cpp b/sp/src/game/shared/sdk/sdk_weapon_melee.cpp new file mode 100644 index 00000000..76baa638 --- /dev/null +++ b/sp/src/game/shared/sdk/sdk_weapon_melee.cpp @@ -0,0 +1,363 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Base code for any melee based weapon
+//
+//=====================================================================================//
+
+#include "cbase.h"
+
+#include "weapon_sdkbase.h"
+#include "sdk_weapon_melee.h"
+
+#include "sdk_gamerules.h"
+#include "ammodef.h"
+#include "mathlib/mathlib.h"
+#include "in_buttons.h"
+#include "animation.h"
+
+#if defined( CLIENT_DLL )
+ #include "c_sdk_player.h"
+#else
+ #include "sdk_player.h"
+ #include "ndebugoverlay.h"
+ #include "te_effect_dispatch.h"
+ #include "ilagcompensationmanager.h"
+#endif
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+IMPLEMENT_NETWORKCLASS_ALIASED( WeaponSDKMelee, DT_WeaponSDKMelee )
+
+BEGIN_NETWORK_TABLE( CWeaponSDKMelee, DT_WeaponSDKMelee )
+END_NETWORK_TABLE()
+
+BEGIN_PREDICTION_DATA( CWeaponSDKMelee )
+END_PREDICTION_DATA()
+
+#define MELEE_HULL_DIM 16
+
+static const Vector g_meleeMins(-MELEE_HULL_DIM,-MELEE_HULL_DIM,-MELEE_HULL_DIM);
+static const Vector g_meleeMaxs(MELEE_HULL_DIM,MELEE_HULL_DIM,MELEE_HULL_DIM);
+
+//-----------------------------------------------------------------------------
+// Constructor
+//-----------------------------------------------------------------------------
+CWeaponSDKMelee::CWeaponSDKMelee()
+{
+ m_bFiresUnderwater = true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Spawn the weapon
+//-----------------------------------------------------------------------------
+void CWeaponSDKMelee::Spawn( void )
+{
+ m_fMinRange1 = 0;
+ m_fMinRange2 = 0;
+ m_fMaxRange1 = 64;
+ m_fMaxRange2 = 64;
+ //Call base class first
+ BaseClass::Spawn();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Precache the weapon
+//-----------------------------------------------------------------------------
+void CWeaponSDKMelee::Precache( void )
+{
+ //Call base class first
+ BaseClass::Precache();
+}
+
+//------------------------------------------------------------------------------
+// Purpose : Update weapon
+//------------------------------------------------------------------------------
+void CWeaponSDKMelee::ItemPostFrame( void )
+{
+ CSDKPlayer *pPlayer = GetPlayerOwner();
+ if ( pPlayer == NULL )
+ return;
+
+ if ( (pPlayer->m_nButtons & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime) && pPlayer->CanAttack() )
+ {
+ PrimaryAttack();
+ }
+ else if ( (pPlayer->m_nButtons & IN_ATTACK2) && (m_flNextSecondaryAttack <= gpGlobals->curtime) && pPlayer->CanAttack() )
+ {
+ SecondaryAttack();
+ }
+ else
+ {
+ WeaponIdle();
+ }
+}
+
+//------------------------------------------------------------------------------
+// Purpose :
+// Input :
+// Output :
+//------------------------------------------------------------------------------
+void CWeaponSDKMelee::PrimaryAttack()
+{
+
+#ifndef CLIENT_DLL
+ CSDKPlayer *pPlayer = ToSDKPlayer( GetPlayerOwner() );
+ // Move other players back to history positions based on local player's lag
+ lagcompensation->StartLagCompensation( pPlayer, pPlayer->GetCurrentCommand() );
+#endif
+ Swing( false );
+#ifndef CLIENT_DLL
+ // Move other players back to history positions based on local player's lag
+ lagcompensation->FinishLagCompensation( pPlayer );
+#endif
+
+}
+
+//------------------------------------------------------------------------------
+// Purpose :
+// Input :
+// Output :
+//------------------------------------------------------------------------------
+void CWeaponSDKMelee::SecondaryAttack()
+{
+ Swing( true );
+}
+
+
+//------------------------------------------------------------------------------
+// Purpose: Implement impact function
+//------------------------------------------------------------------------------
+void CWeaponSDKMelee::Hit( trace_t &traceHit, Activity nHitActivity )
+{
+ CSDKPlayer *pPlayer = ToSDKPlayer( GetOwner() );
+
+ //Do view kick
+// AddViewKick();
+
+ CBaseEntity *pHitEntity = traceHit.m_pEnt;
+
+ //Apply damage to a hit target
+ if ( pHitEntity != NULL )
+ {
+ Vector hitDirection;
+ pPlayer->EyeVectors( &hitDirection, NULL, NULL );
+ VectorNormalize( hitDirection );
+
+#ifndef CLIENT_DLL
+ CTakeDamageInfo info( GetOwner(), GetOwner(), GetDamageForActivity( nHitActivity ), DMG_CLUB );
+
+ if( pPlayer && pHitEntity->IsNPC() )
+ {
+ // If bonking an NPC, adjust damage.
+ info.AdjustPlayerDamageInflictedForSkillLevel();
+ }
+
+ CalculateMeleeDamageForce( &info, hitDirection, traceHit.endpos );
+
+ pHitEntity->DispatchTraceAttack( info, hitDirection, &traceHit );
+ ApplyMultiDamage();
+
+ // Now hit all triggers along the ray that...
+ TraceAttackToTriggers( info, traceHit.startpos, traceHit.endpos, hitDirection );
+#endif
+ WeaponSound( MELEE_HIT );
+ }
+
+ // Apply an impact effect
+ ImpactEffect( traceHit );
+}
+
+Activity CWeaponSDKMelee::ChooseIntersectionPointAndActivity( trace_t &hitTrace, const Vector &mins, const Vector &maxs, CSDKPlayer *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;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : &traceHit -
+//-----------------------------------------------------------------------------
+bool CWeaponSDKMelee::ImpactWater( const Vector &start, const Vector &end )
+{
+ //FIXME: This doesn't handle the case of trying to splash while being underwater, but that's not going to look good
+ // right now anyway...
+
+ // We must start outside the water
+ if ( UTIL_PointContents( start ) & (CONTENTS_WATER|CONTENTS_SLIME))
+ return false;
+
+ // We must end inside of water
+ if ( !(UTIL_PointContents( end ) & (CONTENTS_WATER|CONTENTS_SLIME)))
+ return false;
+
+ trace_t waterTrace;
+
+ UTIL_TraceLine( start, end, (CONTENTS_WATER|CONTENTS_SLIME), GetOwner(), COLLISION_GROUP_NONE, &waterTrace );
+
+ if ( waterTrace.fraction < 1.0f )
+ {
+#ifndef CLIENT_DLL
+ CEffectData data;
+
+ data.m_fFlags = 0;
+ data.m_vOrigin = waterTrace.endpos;
+ data.m_vNormal = waterTrace.plane.normal;
+ data.m_flScale = 8.0f;
+
+ // See if we hit slime
+ if ( waterTrace.contents & CONTENTS_SLIME )
+ {
+ data.m_fFlags |= FX_WATER_IN_SLIME;
+ }
+
+ DispatchEffect( "watersplash", data );
+#endif
+ }
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CWeaponSDKMelee::ImpactEffect( trace_t &traceHit )
+{
+ // See if we hit water (we don't do the other impact effects in this case)
+ if ( ImpactWater( traceHit.startpos, traceHit.endpos ) )
+ return;
+
+ //FIXME: need new decals
+ UTIL_ImpactTrace( &traceHit, DMG_CLUB );
+}
+
+
+//------------------------------------------------------------------------------
+// Purpose : Starts the swing of the weapon and determines the animation
+// Input : bIsSecondary - is this a secondary attack?
+//------------------------------------------------------------------------------
+void CWeaponSDKMelee::Swing( int bIsSecondary )
+{
+ trace_t traceHit;
+
+ // Try a ray
+ CSDKPlayer *pOwner = ToSDKPlayer( GetOwner() );
+ if ( !pOwner )
+ return;
+
+ Vector swingStart = pOwner->Weapon_ShootPosition( );
+ Vector forward;
+
+ pOwner->EyeVectors( &forward, NULL, NULL );
+
+ Vector swingEnd = swingStart + forward * GetRange();
+ UTIL_TraceLine( swingStart, swingEnd, MASK_SHOT_HULL, pOwner, COLLISION_GROUP_NONE, &traceHit );
+ Activity nHitActivity = ACT_VM_HITCENTER;
+
+#ifndef CLIENT_DLL
+ // Like bullets, melee traces have to trace against triggers.
+ CTakeDamageInfo triggerInfo( GetOwner(), GetOwner(), GetDamageForActivity( nHitActivity ), DMG_CLUB );
+ TraceAttackToTriggers( triggerInfo, traceHit.startpos, traceHit.endpos, vec3_origin );
+#endif
+
+ if ( traceHit.fraction == 1.0 )
+ {
+ float meleeHullRadius = 1.732f * MELEE_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 * meleeHullRadius;
+
+ UTIL_TraceHull( swingStart, swingEnd, g_meleeMins, g_meleeMaxs, 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
+ {
+ nHitActivity = ChooseIntersectionPointAndActivity( traceHit, g_meleeMins, g_meleeMaxs, pOwner );
+ }
+ }
+ }
+
+ WeaponSound( SINGLE );
+
+ // -------------------------
+ // Miss
+ // -------------------------
+ if ( traceHit.fraction == 1.0f )
+ {
+ nHitActivity = bIsSecondary ? ACT_VM_MISSCENTER2 : ACT_VM_MISSCENTER;
+
+ // We want to test the first swing again
+ Vector testEnd = swingStart + forward * GetRange();
+
+ // See if we happened to hit water
+ ImpactWater( swingStart, testEnd );
+ }
+ else
+ {
+ Hit( traceHit, nHitActivity );
+ }
+
+ // Send the anim
+ SendWeaponAnim( nHitActivity );
+
+ pOwner->DoAnimationEvent( PLAYERANIMEVENT_ATTACK_PRIMARY );
+
+ //Setup our next attack times
+ m_flNextPrimaryAttack = gpGlobals->curtime + GetFireRate();
+ m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
+}
+
|