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.
348 lines
8.7 KiB
348 lines
8.7 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// |
|
//============================================================================= |
|
#include "cbase.h" |
|
#include "tf_weapon_revolver.h" |
|
#include "tf_fx_shared.h" |
|
#include "datamap.h" |
|
#include "tf_weaponbase_gun.h" |
|
|
|
// Client specific. |
|
#ifdef CLIENT_DLL |
|
#include "c_tf_player.h" |
|
// Server specific. |
|
#else |
|
#include "tf_player.h" |
|
#endif |
|
|
|
//============================================================================= |
|
// |
|
// Weapon Revolver tables. |
|
// |
|
IMPLEMENT_NETWORKCLASS_ALIASED( TFRevolver, DT_WeaponRevolver ) |
|
|
|
BEGIN_NETWORK_TABLE( CTFRevolver, DT_WeaponRevolver ) |
|
END_NETWORK_TABLE() |
|
|
|
#ifdef CLIENT_DLL |
|
BEGIN_PREDICTION_DATA( CTFRevolver ) |
|
DEFINE_PRED_FIELD( m_flLastAccuracyCheck, FIELD_FLOAT, 0 ), |
|
END_PREDICTION_DATA() |
|
#endif |
|
|
|
LINK_ENTITY_TO_CLASS( tf_weapon_revolver, CTFRevolver ); |
|
PRECACHE_WEAPON_REGISTER( tf_weapon_revolver ); |
|
|
|
// Server specific. |
|
#ifndef CLIENT_DLL |
|
BEGIN_DATADESC( CTFRevolver ) |
|
END_DATADESC() |
|
#endif |
|
|
|
#ifdef STAGING_ONLY |
|
CREATE_SIMPLE_WEAPON_TABLE( TFRevolver_Secondary, tf_weapon_revolver_secondary ) |
|
#endif |
|
|
|
//============================================================================= |
|
// |
|
// Weapon Revolver functions. |
|
// |
|
|
|
CTFRevolver::CTFRevolver() |
|
{ |
|
m_flLastAccuracyCheck = 0.f; |
|
m_flAccuracyCheckTime = 0.f; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool CTFRevolver::DefaultReload( int iClipSize1, int iClipSize2, int iActivity ) |
|
{ |
|
// The the owning local player. |
|
CTFPlayer *pPlayer = GetTFPlayerOwner(); |
|
if ( !pPlayer ) |
|
return false; |
|
|
|
if ( pPlayer->IsPlayerClass( TF_CLASS_SPY ) ) |
|
{ |
|
if ( pPlayer->m_Shared.InCond( TF_COND_STEALTHED ) ) |
|
{ |
|
return false; |
|
} |
|
} |
|
|
|
if ( pPlayer->m_Shared.IsFeignDeathReady() ) |
|
return false; // Can't reload if our feign death arm is up. |
|
|
|
return BaseClass::DefaultReload( iClipSize1, iClipSize2, iActivity ); |
|
|
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
int CTFRevolver::GetDamageType( void ) const |
|
{ |
|
if ( CanHeadshot() && (gpGlobals->curtime - m_flLastAccuracyCheck > 1.f) ) |
|
{ |
|
int iDamageType = BaseClass::GetDamageType() | DMG_USE_HITLOCATIONS; |
|
return iDamageType; |
|
} |
|
|
|
return BaseClass::GetDamageType(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool CTFRevolver::CanFireCriticalShot( bool bIsHeadshot ) |
|
{ |
|
if ( !BaseClass::CanFireCriticalShot( bIsHeadshot ) ) |
|
return false; |
|
|
|
CTFPlayer *pPlayer = GetTFPlayerOwner(); |
|
if ( pPlayer && pPlayer->m_Shared.IsCritBoosted() ) |
|
return true; |
|
|
|
// can only fire a crit shot if this is a headshot, unless we're critboosted |
|
if ( !bIsHeadshot ) |
|
{ |
|
// Base revolver still randomly crits. Ambassador doesn't. |
|
return !CanHeadshot(); |
|
} |
|
|
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFRevolver::PrimaryAttack( void ) |
|
{ |
|
// Check for ammunition. |
|
if ( m_iClip1 <= 0 && m_iClip1 != -1 ) |
|
return; |
|
|
|
// Are we capable of firing again? |
|
if ( m_flNextPrimaryAttack > gpGlobals->curtime ) |
|
return; |
|
|
|
// Get the player owning the weapon. |
|
CTFPlayer *pPlayer = ToTFPlayer( GetPlayerOwner() ); |
|
if ( !pPlayer ) |
|
return; |
|
|
|
if ( !CanAttack() ) |
|
return; |
|
|
|
BaseClass::PrimaryAttack(); |
|
|
|
if ( HasLastShotCritical() ) |
|
{ |
|
pPlayer->m_Shared.AddCond( TF_COND_CRITBOOSTED ); |
|
} |
|
else |
|
{ |
|
int iAttr = 0; |
|
CALL_ATTRIB_HOOK_INT( iAttr, last_shot_crits ); |
|
if ( iAttr ) |
|
{ |
|
pPlayer->m_Shared.RemoveCond( TF_COND_CRITBOOSTED ); |
|
} |
|
} |
|
|
|
m_flLastAccuracyCheck = gpGlobals->curtime; |
|
|
|
if ( SapperKillsCollectCrits() ) |
|
{ |
|
// Do this after the attack, so that we know if we are doing custom damage |
|
CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() ); |
|
if ( pOwner ) |
|
{ |
|
int iRevengeCrits = pOwner->m_Shared.GetRevengeCrits(); |
|
if ( iRevengeCrits > 0 ) |
|
{ |
|
pOwner->m_Shared.SetRevengeCrits( iRevengeCrits-1 ); |
|
} |
|
} |
|
} |
|
#ifdef GAME_DLL |
|
// Lower bonus for each attack |
|
int iExtraDamageOnHitPenalty = 0; |
|
CALL_ATTRIB_HOOK_INT( iExtraDamageOnHitPenalty, extra_damage_on_hit_penalty ); |
|
if ( iExtraDamageOnHitPenalty ) |
|
{ |
|
int iDecaps = pPlayer->m_Shared.GetDecapitations(); |
|
pPlayer->m_Shared.SetDecapitations( Max( 0, iDecaps - iExtraDamageOnHitPenalty ) ); |
|
} |
|
#endif |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
float CTFRevolver::GetWeaponSpread( void ) |
|
{ |
|
float fSpread = BaseClass::GetWeaponSpread(); |
|
|
|
if ( CanHeadshot() ) |
|
{ |
|
// We are highly accurate for our first shot. |
|
float flTimeSinceCheck = gpGlobals->curtime - m_flLastAccuracyCheck; |
|
fSpread = RemapValClamped( flTimeSinceCheck, 1.0f, 0.5f, 0.0f, fSpread+0.0f ); |
|
} |
|
|
|
return fSpread; |
|
} |
|
|
|
#ifdef CLIENT_DLL |
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CTFRevolver::GetWeaponCrosshairScale( float &flScale ) |
|
{ |
|
C_TFPlayer* pTFPlayer = ToTFPlayer( GetOwner() ); |
|
if ( !pTFPlayer ) |
|
return; |
|
|
|
if ( CanHeadshot() ) |
|
{ |
|
float curtime = pTFPlayer->GetFinalPredictedTime() + ( gpGlobals->interpolation_amount * TICK_INTERVAL ); |
|
float flTimeSinceCheck = curtime - m_flLastAccuracyCheck; |
|
flScale = RemapValClamped( flTimeSinceCheck, 1.0f, 0.5f, 0.75f, 2.5f ); |
|
} |
|
else |
|
{ |
|
BaseClass::GetWeaponCrosshairScale( flScale ); |
|
} |
|
} |
|
#endif |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
int CTFRevolver::GetCount( void ) |
|
{ |
|
CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() ); |
|
if ( !pOwner ) |
|
return 0; |
|
|
|
if ( SapperKillsCollectCrits() ) |
|
{ |
|
return pOwner->m_Shared.GetRevengeCrits(); |
|
} |
|
|
|
int iExtraDamageOnHit = 0; |
|
CALL_ATTRIB_HOOK_INT( iExtraDamageOnHit, extra_damage_on_hit ); |
|
if ( iExtraDamageOnHit ) |
|
{ |
|
return Min( 200, pOwner->m_Shared.GetDecapitations() ); |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
const char* CTFRevolver::GetEffectLabelText( void ) |
|
{ |
|
int iExtraDamageOnHit = 0; |
|
CALL_ATTRIB_HOOK_INT( iExtraDamageOnHit, extra_damage_on_hit ); |
|
if ( iExtraDamageOnHit ) |
|
{ |
|
return "#TF_BONUS"; |
|
} |
|
return "#TF_CRITS"; |
|
} |
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool CTFRevolver::Holster( CBaseCombatWeapon *pSwitchingTo ) |
|
{ |
|
#ifdef GAME_DLL |
|
CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() ); |
|
if ( pOwner ) |
|
{ |
|
if ( SapperKillsCollectCrits() ) |
|
{ |
|
if ( pOwner->m_Shared.GetRevengeCrits() ) |
|
{ |
|
pOwner->m_Shared.RemoveCond( TF_COND_CRITBOOSTED ); |
|
} |
|
} |
|
|
|
if ( HasLastShotCritical() ) |
|
{ |
|
pOwner->m_Shared.RemoveCond( TF_COND_CRITBOOSTED ); |
|
} |
|
} |
|
#endif |
|
|
|
return BaseClass::Holster( pSwitchingTo ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
bool CTFRevolver::Deploy( void ) |
|
{ |
|
#ifdef GAME_DLL |
|
CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() ); |
|
if ( pOwner ) |
|
{ |
|
if ( SapperKillsCollectCrits() ) |
|
{ |
|
if ( pOwner->m_Shared.GetRevengeCrits() ) |
|
{ |
|
pOwner->m_Shared.AddCond( TF_COND_CRITBOOSTED ); |
|
} |
|
} |
|
|
|
if ( HasLastShotCritical() ) |
|
{ |
|
pOwner->m_Shared.AddCond( TF_COND_CRITBOOSTED ); |
|
} |
|
} |
|
#endif |
|
|
|
return BaseClass::Deploy(); |
|
} |
|
|
|
#ifdef GAME_DLL |
|
//----------------------------------------------------------------------------- |
|
// Purpose: Reset revenge crits when the revolver is changed |
|
//----------------------------------------------------------------------------- |
|
void CTFRevolver::Detach( void ) |
|
{ |
|
if ( SapperKillsCollectCrits() ) |
|
{ |
|
CTFPlayer *pPlayer = GetTFPlayerOwner(); |
|
if ( pPlayer ) |
|
{ |
|
pPlayer->m_Shared.SetRevengeCrits( 0 ); |
|
pPlayer->m_Shared.RemoveCond( TF_COND_CRITBOOSTED ); |
|
} |
|
} |
|
|
|
BaseClass::Detach(); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
float CTFRevolver::GetProjectileDamage( void ) |
|
{ |
|
float flDamageMod = 1.0f; |
|
int iExtraDamageOnHit = 0; |
|
CALL_ATTRIB_HOOK_INT( iExtraDamageOnHit, extra_damage_on_hit ); |
|
if ( iExtraDamageOnHit ) |
|
{ |
|
CTFPlayer *pOwner = ToTFPlayer( GetOwner() ); |
|
if ( pOwner ) |
|
{ |
|
flDamageMod = 1.0f + ( Min( 200, pOwner->m_Shared.GetDecapitations() ) * 0.01f ); |
|
} |
|
} |
|
|
|
return BaseClass::GetProjectileDamage() * flDamageMod; |
|
} |
|
#endif
|
|
|