mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2025-09-20 12:36:05 +08:00
First version of the SOurce SDK 2013
This commit is contained in:
363
game/shared/sdk/sdk_weapon_melee.cpp
Normal file
363
game/shared/sdk/sdk_weapon_melee.cpp
Normal file
@ -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();
|
||||
}
|
||||
|
Reference in New Issue
Block a user