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.
237 lines
6.3 KiB
237 lines
6.3 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "weapon_dodbasemelee.h" |
|
#include "dod_gamerules.h" |
|
|
|
#if defined( CLIENT_DLL ) |
|
#include "c_dod_player.h" |
|
#else |
|
#include "dod_player.h" |
|
#include "ilagcompensationmanager.h" |
|
#endif |
|
|
|
#include "effect_dispatch_data.h" |
|
|
|
|
|
#define KNIFE_BODYHIT_VOLUME 128 |
|
#define KNIFE_WALLHIT_VOLUME 512 |
|
|
|
// ----------------------------------------------------------------------------- // |
|
// CWeaponDODBaseMelee tables. |
|
// ----------------------------------------------------------------------------- // |
|
|
|
IMPLEMENT_NETWORKCLASS_ALIASED( WeaponDODBaseMelee, DT_WeaponDODBaseMelee ) |
|
|
|
BEGIN_NETWORK_TABLE_NOBASE( CWeaponDODBaseMelee, DT_LocalActiveWeaponBaseMeleeData ) |
|
END_NETWORK_TABLE() |
|
|
|
BEGIN_NETWORK_TABLE( CWeaponDODBaseMelee, DT_WeaponDODBaseMelee ) |
|
END_NETWORK_TABLE() |
|
|
|
#ifdef CLIENT_DLL |
|
BEGIN_PREDICTION_DATA( CWeaponDODBaseMelee ) |
|
DEFINE_PRED_FIELD( m_flSmackTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), |
|
END_PREDICTION_DATA() |
|
#endif |
|
|
|
LINK_ENTITY_TO_CLASS( weapon_dod_base_melee, CWeaponDODBaseMelee ); |
|
|
|
#ifndef CLIENT_DLL |
|
|
|
BEGIN_DATADESC( CWeaponDODBaseMelee ) |
|
DEFINE_FUNCTION( Smack ) |
|
END_DATADESC() |
|
|
|
#endif |
|
|
|
// ----------------------------------------------------------------------------- // |
|
// CWeaponDODBaseMelee implementation. |
|
// ----------------------------------------------------------------------------- // |
|
|
|
CWeaponDODBaseMelee::CWeaponDODBaseMelee() |
|
{ |
|
} |
|
|
|
void CWeaponDODBaseMelee::Spawn() |
|
{ |
|
Precache(); |
|
|
|
WEAPON_FILE_INFO_HANDLE hWpnInfo = LookupWeaponInfoSlot( GetClassname() ); |
|
|
|
Assert( hWpnInfo != GetInvalidWeaponInfoHandle() ); |
|
|
|
CDODWeaponInfo *pWeaponInfo = dynamic_cast< CDODWeaponInfo* >( GetFileWeaponInfoFromHandle( hWpnInfo ) ); |
|
|
|
Assert( pWeaponInfo && "Failed to get CDODWeaponInfo in melee weapon spawn" ); |
|
|
|
m_pWeaponInfo = pWeaponInfo; |
|
|
|
Assert( m_pWeaponInfo ); |
|
|
|
m_iClip1 = -1; |
|
BaseClass::Spawn(); |
|
} |
|
|
|
void CWeaponDODBaseMelee::WeaponIdle( void ) |
|
{ |
|
if ( m_flTimeWeaponIdle > gpGlobals->curtime ) |
|
return; |
|
|
|
SendWeaponAnim( ACT_VM_IDLE ); |
|
|
|
m_flTimeWeaponIdle = gpGlobals->curtime + SequenceDuration(); |
|
} |
|
|
|
void CWeaponDODBaseMelee::PrimaryAttack() |
|
{ |
|
MeleeAttack( 60, MELEE_DMG_EDGE, 0.2f, 0.4f ); |
|
} |
|
|
|
CBaseEntity *CWeaponDODBaseMelee::MeleeAttack( int iDamageAmount, int iDamageType, float flDmgDelay, float flAttackDelay ) |
|
{ |
|
if ( !CanAttack() ) |
|
return NULL; |
|
|
|
CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() ); |
|
|
|
#if !defined (CLIENT_DLL) |
|
// Move other players back to history positions based on local player's lag |
|
lagcompensation->StartLagCompensation( pPlayer, pPlayer->GetCurrentCommand() ); |
|
#endif |
|
|
|
Vector vForward, vRight, vUp; |
|
AngleVectors( pPlayer->EyeAngles(), &vForward, &vRight, &vUp ); |
|
Vector vecSrc = pPlayer->Weapon_ShootPosition(); |
|
Vector vecEnd = vecSrc + vForward * 48; |
|
|
|
CTraceFilterSimple filter( pPlayer, COLLISION_GROUP_NONE ); |
|
|
|
int iTraceMask = MASK_SOLID | CONTENTS_HITBOX | CONTENTS_DEBRIS; |
|
|
|
trace_t tr; |
|
UTIL_TraceLine( vecSrc, vecEnd, iTraceMask, &filter, &tr ); |
|
|
|
const float rayExtension = 40.0f; |
|
UTIL_ClipTraceToPlayers( vecSrc, vecEnd + vForward * rayExtension, iTraceMask, &filter, &tr ); |
|
|
|
if ( tr.fraction >= 1.0 ) |
|
{ |
|
Vector head_hull_mins( -16, -16, -18 ); |
|
Vector head_hull_maxs( 16, 16, 18 ); |
|
|
|
UTIL_TraceHull( vecSrc, vecEnd, head_hull_mins, head_hull_maxs, MASK_SOLID, &filter, &tr ); |
|
if ( tr.fraction < 1.0 ) |
|
{ |
|
// Calculate the point of intersection of the line (or hull) and the object we hit |
|
// This is and approximation of the "best" intersection |
|
CBaseEntity *pHit = tr.m_pEnt; |
|
if ( !pHit || pHit->IsBSPModel() ) |
|
FindHullIntersection( vecSrc, tr, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, pPlayer ); |
|
vecEnd = tr.endpos; // This is the point on the actual surface (the hull could have hit space) |
|
|
|
// Make sure it is in front of us |
|
Vector vecToEnd = vecEnd - vecSrc; |
|
VectorNormalize( vecToEnd ); |
|
|
|
// if zero length, always hit |
|
if ( vecToEnd.Length() > 0 ) |
|
{ |
|
float dot = DotProduct( vForward, vecToEnd ); |
|
|
|
// sanity that our hit is within range |
|
if ( abs(dot) < 0.95 ) |
|
{ |
|
// fake that we actually missed |
|
tr.fraction = 1.0; |
|
} |
|
} |
|
} |
|
} |
|
|
|
bool bDidHit = ( tr.fraction < 1.0f ); |
|
|
|
bool bDoStrongAttack = false; |
|
|
|
if ( bDidHit && tr.m_pEnt->IsPlayer() && tr.m_pEnt->m_takedamage != DAMAGE_YES ) |
|
{ |
|
bDidHit = 0; // still play the animation, we just dont attempt to damage this player |
|
} |
|
|
|
if ( bDidHit ) //if the swing hit |
|
{ |
|
// delay the decal a bit |
|
m_trHit = tr; |
|
|
|
// Store the ent in an EHANDLE, just in case it goes away by the time we get into our think function. |
|
m_pTraceHitEnt = tr.m_pEnt; |
|
|
|
m_iSmackDamage = iDamageAmount; |
|
m_iSmackDamageType = iDamageType; |
|
|
|
m_flSmackTime = gpGlobals->curtime + flDmgDelay; |
|
|
|
int iOwnerTeam = pPlayer->GetTeamNumber(); |
|
int iVictimTeam = tr.m_pEnt->GetTeamNumber(); |
|
|
|
// do the mega attack if its a player, and we would do damage |
|
if ( tr.m_pEnt->IsPlayer() && |
|
tr.m_pEnt->m_takedamage == DAMAGE_YES && |
|
( iVictimTeam != iOwnerTeam || ( iVictimTeam == iOwnerTeam && friendlyfire.GetBool() ) ) ) |
|
{ |
|
CDODPlayer *pVictim = ToDODPlayer( tr.m_pEnt ); |
|
|
|
Vector victimForward; |
|
AngleVectors( pVictim->GetAbsAngles(), &victimForward ); |
|
|
|
if ( DotProduct( victimForward, vForward ) > 0.3 ) |
|
{ |
|
bDoStrongAttack = true; |
|
} |
|
} |
|
} |
|
|
|
if ( bDoStrongAttack ) |
|
{ |
|
m_iSmackDamage = 300; |
|
flAttackDelay = 0.9f; |
|
m_flSmackTime = gpGlobals->curtime + 0.4f; |
|
|
|
m_iSmackDamageType = MELEE_DMG_EDGE | MELEE_DMG_STRONGATTACK; |
|
|
|
// play a "Strong" attack |
|
SendWeaponAnim( ACT_VM_SECONDARYATTACK ); |
|
} |
|
else |
|
{ |
|
WeaponSound( MELEE_MISS ); |
|
SendWeaponAnim( GetMeleeActivity() ); |
|
} |
|
|
|
// player animation |
|
pPlayer->DoAnimationEvent( PLAYERANIMEVENT_SECONDARY_ATTACK ); |
|
|
|
m_flNextPrimaryAttack = gpGlobals->curtime + flAttackDelay; |
|
m_flNextSecondaryAttack = gpGlobals->curtime + flAttackDelay; |
|
m_flTimeWeaponIdle = gpGlobals->curtime + SequenceDuration(); |
|
|
|
|
|
#ifndef CLIENT_DLL |
|
IGameEvent * event = gameeventmanager->CreateEvent( "dod_stats_weapon_attack" ); |
|
if ( event ) |
|
{ |
|
event->SetInt( "attacker", pPlayer->GetUserID() ); |
|
event->SetInt( "weapon", GetStatsWeaponID() ); |
|
|
|
gameeventmanager->FireEvent( event ); |
|
} |
|
|
|
lagcompensation->FinishLagCompensation( pPlayer ); |
|
#endif //CLIENT_DLL |
|
|
|
return tr.m_pEnt; |
|
} |