mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-08 09:49:36 +00:00
1
This commit is contained in:
@@ -0,0 +1,685 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
//
|
||||
//=============================================================================
|
||||
#include "cbase.h"
|
||||
#include "tf_weapon_compound_bow.h"
|
||||
#include "tf_fx_shared.h"
|
||||
#include "tf_gamerules.h"
|
||||
#include "in_buttons.h"
|
||||
|
||||
// Client specific.
|
||||
#ifdef CLIENT_DLL
|
||||
#include "c_tf_player.h"
|
||||
#include "c_tf_gamestats.h"
|
||||
#include "prediction.h"
|
||||
// Server specific.
|
||||
#else
|
||||
#include "tf_player.h"
|
||||
#include "tf_gamestats.h"
|
||||
#include "tf_projectile_arrow.h"
|
||||
#endif
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Weapon tables.
|
||||
//
|
||||
IMPLEMENT_NETWORKCLASS_ALIASED( TFCompoundBow, DT_WeaponCompoundBow )
|
||||
|
||||
BEGIN_NETWORK_TABLE( CTFCompoundBow, DT_WeaponCompoundBow )
|
||||
#ifdef CLIENT_DLL
|
||||
RecvPropBool( RECVINFO( m_bArrowAlight ) ),
|
||||
RecvPropBool( RECVINFO( m_bNoFire ) ),
|
||||
#else
|
||||
SendPropBool( SENDINFO( m_bArrowAlight ) ),
|
||||
SendPropBool( SENDINFO( m_bNoFire ) ),
|
||||
#endif
|
||||
END_NETWORK_TABLE()
|
||||
|
||||
BEGIN_PREDICTION_DATA( CTFCompoundBow )
|
||||
#ifdef CLIENT_DLL
|
||||
DEFINE_PRED_FIELD( m_flChargeBeginTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
|
||||
DEFINE_PRED_FIELD( m_bNoFire, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ),
|
||||
#endif
|
||||
END_PREDICTION_DATA()
|
||||
|
||||
LINK_ENTITY_TO_CLASS( tf_weapon_compound_bow, CTFCompoundBow );
|
||||
PRECACHE_WEAPON_REGISTER( tf_weapon_compound_bow );
|
||||
|
||||
// Server specific.
|
||||
#ifndef CLIENT_DLL
|
||||
BEGIN_DATADESC( CTFCompoundBow )
|
||||
END_DATADESC()
|
||||
#endif
|
||||
|
||||
#define TF_ARROW_MAX_CHARGE_TIME 5.0f
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// Weapon functions.
|
||||
//
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CTFCompoundBow::CTFCompoundBow()
|
||||
{
|
||||
m_flLastDenySoundTime = 0.0f;
|
||||
m_bNoFire = false;
|
||||
m_bReloadsSingly = false;
|
||||
}
|
||||
|
||||
void CTFCompoundBow::Precache( void )
|
||||
{
|
||||
PrecacheScriptSound( "Weapon_CompoundBow.SinglePull" );
|
||||
PrecacheScriptSound( "ArrowLight" );
|
||||
|
||||
BaseClass::Precache();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFCompoundBow::WeaponReset( void )
|
||||
{
|
||||
BaseClass::WeaponReset();
|
||||
|
||||
// m_flChargeBeginTime = 0;
|
||||
m_bArrowAlight = false;
|
||||
m_bNoAutoRelease = true;
|
||||
m_bNoFire = false;
|
||||
}
|
||||
|
||||
#ifdef GAME_DLL
|
||||
|
||||
#ifdef STAGING_ONLY
|
||||
void CTFCompoundBow::CreateExtraArrow( CTFProjectile_Arrow* pMainArrow, const QAngle& qSpreadAngles, float flSpeed )
|
||||
{
|
||||
CTFProjectile_Arrow* pExtraArrow = CTFProjectile_Arrow::Create( pMainArrow->GetAbsOrigin(), qSpreadAngles, flSpeed, GetProjectileGravity(), (ProjectileType_t)GetWeaponProjectileType(), pMainArrow->GetOwnerEntity(), pMainArrow->GetOwnerEntity() );
|
||||
if ( pExtraArrow )
|
||||
{
|
||||
pExtraArrow->SetLauncher( this );
|
||||
pExtraArrow->SetCritical( IsCurrentAttackACrit() );
|
||||
pExtraArrow->SetDamage( 0.5f * GetProjectileDamage() );
|
||||
if ( pMainArrow->CanPenetrate() )
|
||||
{
|
||||
pExtraArrow->SetPenetrate( true );
|
||||
}
|
||||
pExtraArrow->SetCollisionGroup( pMainArrow->GetCollisionGroup() );
|
||||
}
|
||||
}
|
||||
|
||||
ConVar sv_arrow_spread_angle( "sv_arrow_spread_angle", "5.f" );
|
||||
ConVar sv_arrow_max_random_spread_angle( "sv_arrow_random_spread_angle", "5.f" );
|
||||
float CTFCompoundBow::GetRandomSpreadOffset( int iLevel )
|
||||
{
|
||||
float flMaxRandomSpread = sv_arrow_max_random_spread_angle.GetFloat();
|
||||
float flRandom = RemapValClamped( gpGlobals->curtime - m_flChargeBeginTime, 0.f, GetChargeMaxTime(), RandomFloat( -flMaxRandomSpread, flMaxRandomSpread ), 0.f );
|
||||
return sv_arrow_spread_angle.GetFloat() * iLevel + flRandom;
|
||||
}
|
||||
#endif // STAGING_ONLY
|
||||
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFCompoundBow::LaunchGrenade( void )
|
||||
{
|
||||
// Get the player owning the weapon.
|
||||
CTFPlayer *pPlayer = ToTFPlayer( GetPlayerOwner() );
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
CalcIsAttackCritical();
|
||||
|
||||
SendWeaponAnim( ACT_VM_PRIMARYATTACK );
|
||||
|
||||
pPlayer->SetAnimation( PLAYER_ATTACK1 );
|
||||
pPlayer->DoAnimationEvent( PLAYERANIMEVENT_ATTACK_PRIMARY );
|
||||
|
||||
m_bWantsToShoot = false;
|
||||
|
||||
#ifdef GAME_DLL
|
||||
CTFProjectile_Arrow *pMainArrow = assert_cast<CTFProjectile_Arrow*>( FireProjectile( pPlayer ) );
|
||||
if ( pMainArrow )
|
||||
{
|
||||
pMainArrow->SetArrowAlight( m_bArrowAlight );
|
||||
|
||||
#ifdef STAGING_ONLY
|
||||
if ( TFGameRules() && TFGameRules()->GameModeUsesUpgrades() )
|
||||
{
|
||||
Vector vecMainVelocity = pMainArrow->GetAbsVelocity();
|
||||
float flMainSpeed = vecMainVelocity.Length();
|
||||
int iArrowMastery = 0;
|
||||
CALL_ATTRIB_HOOK_INT( iArrowMastery, arrow_mastery );
|
||||
for ( int i=0; i<iArrowMastery; ++i )
|
||||
{
|
||||
QAngle qOffset1 = pMainArrow->GetAbsAngles() + QAngle( 0, GetRandomSpreadOffset( i + 1 ), 0 );
|
||||
CreateExtraArrow( pMainArrow, qOffset1, flMainSpeed );
|
||||
QAngle qOffset2 = pMainArrow->GetAbsAngles() + QAngle( 0, -GetRandomSpreadOffset( i + 1 ), 0 );
|
||||
CreateExtraArrow( pMainArrow, qOffset2, flMainSpeed );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
FireProjectile( pPlayer );
|
||||
#endif
|
||||
|
||||
#if !defined( CLIENT_DLL )
|
||||
pPlayer->SpeakWeaponFire();
|
||||
CTF_GameStats.Event_PlayerFiredWeapon( pPlayer, IsCurrentAttackACrit() );
|
||||
#endif
|
||||
#ifdef CLIENT_DLL
|
||||
C_CTF_GameStats.Event_PlayerFiredWeapon( pPlayer, IsCurrentAttackACrit() );
|
||||
#endif
|
||||
|
||||
// Set next attack times.
|
||||
float flBaseFireDelay = m_pWeaponInfo->GetWeaponData( m_iWeaponMode ).m_flTimeFireDelay;
|
||||
float flFireDelay = ApplyFireDelay( flBaseFireDelay );
|
||||
|
||||
ApplyRefireSpeedModifications( flFireDelay );
|
||||
|
||||
float flRateMultiplyer = flBaseFireDelay / flFireDelay;
|
||||
|
||||
// Speed up the reload animation built in to firing
|
||||
if ( pPlayer->GetViewModel(0) )
|
||||
{
|
||||
pPlayer->GetViewModel(0)->SetPlaybackRate( flRateMultiplyer );
|
||||
}
|
||||
if ( pPlayer->GetViewModel(1) )
|
||||
{
|
||||
pPlayer->GetViewModel(1)->SetPlaybackRate( flRateMultiplyer );
|
||||
}
|
||||
|
||||
m_flNextPrimaryAttack = gpGlobals->curtime + flFireDelay;
|
||||
m_flLastDenySoundTime = gpGlobals->curtime;
|
||||
|
||||
float flIdleDelay = 0.5f * flRateMultiplyer;
|
||||
SetWeaponIdleTime( m_flNextPrimaryAttack + flIdleDelay );
|
||||
|
||||
pPlayer->m_Shared.RemoveCond( TF_COND_AIMING );
|
||||
pPlayer->TeamFortress_SetSpeed();
|
||||
|
||||
m_flChargeBeginTime = 0;
|
||||
m_bArrowAlight = false;
|
||||
|
||||
// The bow doesn't actually reload, it instead uses the AE_WPN_INCREMENTAMMO anim event in the fire to reload the clip.
|
||||
// We need to reset this bool each time we fire so that anim event works.
|
||||
m_bReloadedThroughAnimEvent = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFCompoundBow::PrimaryAttack( void )
|
||||
{
|
||||
CTFPlayer *pPlayer = ToTFPlayer( GetPlayerOwner() );
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
// Check for ammunition.
|
||||
if ( m_iClip1 <= 0 && m_iClip1 != -1 )
|
||||
return;
|
||||
|
||||
// Are we capable of firing again?
|
||||
if ( m_flNextPrimaryAttack > gpGlobals->curtime )
|
||||
return;
|
||||
|
||||
if ( m_bNoFire )
|
||||
return;
|
||||
|
||||
if ( !CanAttack() )
|
||||
{
|
||||
m_flChargeBeginTime = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_flChargeBeginTime <= 0 )
|
||||
{
|
||||
// Set the weapon mode.
|
||||
m_iWeaponMode = TF_WEAPON_PRIMARY_MODE;
|
||||
|
||||
// save that we had the attack button down
|
||||
m_flChargeBeginTime = gpGlobals->curtime;
|
||||
|
||||
SendWeaponAnim( ACT_VM_PULLBACK );
|
||||
|
||||
float flRateMultiplyer = ApplyFireDelay( 1.0f );
|
||||
ApplyRefireSpeedModifications( flRateMultiplyer );
|
||||
if ( flRateMultiplyer > 0.0f )
|
||||
{
|
||||
flRateMultiplyer = 1.0f / flRateMultiplyer;
|
||||
}
|
||||
|
||||
// Speed up the reload animation built in to firing
|
||||
if ( pPlayer->GetViewModel(0) )
|
||||
{
|
||||
pPlayer->GetViewModel(0)->SetPlaybackRate( flRateMultiplyer );
|
||||
}
|
||||
if ( pPlayer->GetViewModel(1) )
|
||||
{
|
||||
pPlayer->GetViewModel(1)->SetPlaybackRate( flRateMultiplyer );
|
||||
}
|
||||
|
||||
bool bPlaySound = true;
|
||||
#ifdef CLIENT_DLL
|
||||
bPlaySound = prediction->IsFirstTimePredicted();
|
||||
#endif
|
||||
if ( bPlaySound )
|
||||
{
|
||||
// Increase the pitch of the pull sound when the fire rate is higher
|
||||
CSoundParameters params;
|
||||
if ( CBaseEntity::GetParametersForSound( "Weapon_CompoundBow.SinglePull", params, NULL ) )
|
||||
{
|
||||
CPASAttenuationFilter filter( pPlayer->GetAbsOrigin(), params.soundlevel );
|
||||
#ifdef GAME_DLL
|
||||
filter.RemoveRecipient( pPlayer );
|
||||
#endif
|
||||
EmitSound_t ep( params );
|
||||
ep.m_nPitch *= flRateMultiplyer;
|
||||
|
||||
pPlayer->EmitSound( filter, pPlayer->entindex(), ep );
|
||||
}
|
||||
}
|
||||
|
||||
// Slow down movement speed while the bow is pulled back.
|
||||
pPlayer->m_Shared.AddCond( TF_COND_AIMING );
|
||||
pPlayer->TeamFortress_SetSpeed();
|
||||
}
|
||||
else
|
||||
{
|
||||
float flTotalChargeTime = gpGlobals->curtime - m_flChargeBeginTime;
|
||||
|
||||
if ( flTotalChargeTime >= GetChargeMaxTime() )
|
||||
{
|
||||
flTotalChargeTime = GetChargeMaxTime();
|
||||
// LaunchGrenade();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
float CTFCompoundBow::GetChargeMaxTime( void )
|
||||
{
|
||||
// It takes less time to charge if the fire rate is higher
|
||||
float flChargeMaxTime = ApplyFireDelay( 1.0f );
|
||||
ApplyRefireSpeedModifications( flChargeMaxTime );
|
||||
|
||||
return flChargeMaxTime;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
float CTFCompoundBow::GetCurrentCharge( void )
|
||||
{
|
||||
if ( m_flChargeBeginTime == 0 )
|
||||
return 0;
|
||||
else
|
||||
return MIN( gpGlobals->curtime - m_flChargeBeginTime, 1.f );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
float CTFCompoundBow::GetProjectileDamage( void )
|
||||
{
|
||||
float flDamage = BaseClass::GetProjectileDamage();
|
||||
float flBaseDamage = 50.f;
|
||||
float flScale = MIN( GetCurrentCharge() / GetChargeMaxTime(), 1.f);
|
||||
float flScaleDamage = flDamage * flScale;
|
||||
|
||||
return (flBaseDamage + flScaleDamage);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
float CTFCompoundBow::GetProjectileSpeed( void )
|
||||
{
|
||||
return RemapValClamped( GetCurrentCharge(), 0.0f, 1.f, 1800, 2600 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
float CTFCompoundBow::GetProjectileGravity( void )
|
||||
{
|
||||
return RemapValClamped( GetCurrentCharge(), 0.0f, 1.f, 0.5, 0.1 );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFCompoundBow::AddPipeBomb( CTFGrenadePipebombProjectile *pBomb )
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFCompoundBow::SecondaryAttack( void )
|
||||
{
|
||||
LowerBow();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Un-nocks a ready arrow.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFCompoundBow::LowerBow( void )
|
||||
{
|
||||
if ( GetCurrentCharge() == 0.f )
|
||||
return; // No arrow nocked.
|
||||
|
||||
m_flChargeBeginTime = 0;
|
||||
|
||||
CTFPlayer *pPlayer = ToTFPlayer( GetPlayerOwner() );
|
||||
if ( pPlayer )
|
||||
{
|
||||
pPlayer->m_Shared.RemoveCond( TF_COND_AIMING );
|
||||
pPlayer->TeamFortress_SetSpeed();
|
||||
}
|
||||
|
||||
m_flNextPrimaryAttack = gpGlobals->curtime + 1.f;
|
||||
|
||||
m_bNoFire = true;
|
||||
m_bWantsToShoot = false;
|
||||
|
||||
SendWeaponAnim( ACT_ITEM2_VM_DRYFIRE );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CTFCompoundBow::DetonateRemotePipebombs( bool bFizzle )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CTFCompoundBow::OwnerCanJump( void )
|
||||
{
|
||||
if ( GetCurrentCharge() > 0.f )
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CTFCompoundBow::Holster( CBaseCombatWeapon *pSwitchingTo )
|
||||
{
|
||||
CTFPlayer *pPlayer = ToTFPlayer( GetPlayerOwner() );
|
||||
if ( pPlayer )
|
||||
{
|
||||
pPlayer->m_Shared.RemoveCond( TF_COND_AIMING );
|
||||
pPlayer->TeamFortress_SetSpeed();
|
||||
}
|
||||
m_bNoFire = false;
|
||||
SetArrowAlight( false );
|
||||
|
||||
return BaseClass::Holster( pSwitchingTo );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Play animation appropriate to ball status.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CTFCompoundBow::SendWeaponAnim( int iActivity )
|
||||
{
|
||||
CTFPlayer *pPlayer = GetTFPlayerOwner();
|
||||
if ( !pPlayer )
|
||||
return BaseClass::SendWeaponAnim( iActivity );
|
||||
|
||||
if ( iActivity == ACT_VM_PULLBACK )
|
||||
{
|
||||
iActivity = ACT_ITEM2_VM_CHARGE;
|
||||
}
|
||||
|
||||
float flTotalChargeTime = gpGlobals->curtime - m_flChargeBeginTime;
|
||||
if ( GetCurrentCharge() > 0 )
|
||||
{
|
||||
switch ( iActivity )
|
||||
{
|
||||
case ACT_VM_IDLE:
|
||||
if ( flTotalChargeTime >= TF_ARROW_MAX_CHARGE_TIME )
|
||||
{
|
||||
int iAct = GetActivity();
|
||||
if ( iAct == ACT_ITEM2_VM_IDLE_3 || iAct == ACT_ITEM2_VM_CHARGE_IDLE_3 )
|
||||
{
|
||||
iActivity = ACT_ITEM2_VM_IDLE_3;
|
||||
}
|
||||
else
|
||||
{
|
||||
iActivity = ACT_ITEM2_VM_CHARGE_IDLE_3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iActivity = ACT_ITEM2_VM_IDLE_2;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return BaseClass::SendWeaponAnim( iActivity );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Play animation appropriate to ball status.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFCompoundBow::ItemPostFrame( void )
|
||||
{
|
||||
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
|
||||
if ( !pOwner )
|
||||
return;
|
||||
|
||||
if ( !CanAttack() )
|
||||
{
|
||||
LowerBow();
|
||||
}
|
||||
|
||||
// If we just fired, and we're past the point at which we tried to reload ourselves,
|
||||
// and we don't have any ammo in the clip, switch away to another weapon to stop us
|
||||
// from playing the "draw another arrow from the quiver" animation.
|
||||
if ( m_bReloadedThroughAnimEvent && m_iClip1 <= 0 && pOwner->GetAmmoCount( m_iPrimaryAmmoType ) <= 0 )
|
||||
{
|
||||
g_pGameRules->SwitchToNextBestWeapon( pOwner, this );
|
||||
return;
|
||||
}
|
||||
|
||||
BaseClass::ItemPostFrame();
|
||||
|
||||
if ( !(pOwner->m_nButtons & IN_ATTACK) && !(pOwner->m_nButtons & IN_ATTACK2) )
|
||||
{
|
||||
// Both buttons released. The player can draw the bow again.
|
||||
m_bNoFire = false;
|
||||
|
||||
if ( GetActivity() == ACT_ITEM2_VM_PRIMARYATTACK && IsViewModelSequenceFinished() )
|
||||
{
|
||||
SendWeaponAnim( ACT_VM_IDLE );
|
||||
}
|
||||
}
|
||||
|
||||
if ( GetCurrentCharge() == 1.f && IsViewModelSequenceFinished() )
|
||||
{
|
||||
SendWeaponAnim( ACT_VM_IDLE );
|
||||
}
|
||||
|
||||
if ( m_bNoFire )
|
||||
{
|
||||
WeaponIdle();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Held the arrow drawn too long. Give up & play a fail animation.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFCompoundBow::ForceLaunchGrenade( void )
|
||||
{
|
||||
// LowerBow();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFCompoundBow::GetProjectileFireSetup( CTFPlayer *pPlayer, Vector vecOffset, Vector *vecSrc, QAngle *angForward, bool bHitTeammates, float flEndDist )
|
||||
{
|
||||
BaseClass::GetProjectileFireSetup( pPlayer, vecOffset, vecSrc, angForward, bHitTeammates, flEndDist );
|
||||
|
||||
float flTotalChargeTime = gpGlobals->curtime - m_flChargeBeginTime;
|
||||
if ( flTotalChargeTime >= TF_ARROW_MAX_CHARGE_TIME )
|
||||
{
|
||||
// We want to fire a really inaccurate shot.
|
||||
float frand = (float) rand() / VALVE_RAND_MAX;
|
||||
angForward->x += -6 + frand*12.f;
|
||||
frand = (float) rand() / VALVE_RAND_MAX;
|
||||
angForward->y += -6 + frand*12.f;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFCompoundBow::ApplyRefireSpeedModifications( float &flBaseRef )
|
||||
{
|
||||
CALL_ATTRIB_HOOK_FLOAT( flBaseRef, fast_reload );
|
||||
|
||||
// Prototype hack
|
||||
CTFPlayer *pPlayer = ToTFPlayer( GetOwner() );
|
||||
if ( pPlayer )
|
||||
{
|
||||
int iMaster = 0;
|
||||
CALL_ATTRIB_HOOK_INT_ON_OTHER( pPlayer, iMaster, ability_master_sniper );
|
||||
if ( iMaster )
|
||||
{
|
||||
flBaseRef *= RemapValClamped( iMaster, 1, 2, 0.6f, 0.3f );
|
||||
}
|
||||
else if ( pPlayer->m_Shared.GetCarryingRuneType() == RUNE_HASTE )
|
||||
{
|
||||
flBaseRef *= 0.4f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CLIENT_DLL
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFCompoundBow::StartBurningEffect( void )
|
||||
{
|
||||
// clear any old effect before adding a new one
|
||||
if ( m_pBurningArrowEffect )
|
||||
{
|
||||
StopBurningEffect();
|
||||
}
|
||||
|
||||
const char *pszEffect;
|
||||
m_hParticleEffectOwner = GetWeaponForEffect();
|
||||
if ( m_hParticleEffectOwner )
|
||||
{
|
||||
if ( m_hParticleEffectOwner != this )
|
||||
{
|
||||
// We're on the viewmodel
|
||||
pszEffect = "v_flaming_arrow";
|
||||
}
|
||||
else
|
||||
{
|
||||
pszEffect = "flaming_arrow";
|
||||
}
|
||||
|
||||
m_pBurningArrowEffect = m_hParticleEffectOwner->ParticleProp()->Create( pszEffect, PATTACH_POINT_FOLLOW, "muzzle" );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFCompoundBow::StopBurningEffect( void )
|
||||
{
|
||||
if ( m_pBurningArrowEffect )
|
||||
{
|
||||
if ( m_hParticleEffectOwner && m_hParticleEffectOwner->ParticleProp() )
|
||||
{
|
||||
m_hParticleEffectOwner->ParticleProp()->StopEmission( m_pBurningArrowEffect );
|
||||
}
|
||||
|
||||
m_pBurningArrowEffect = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFCompoundBow::UpdateOnRemove( void )
|
||||
{
|
||||
StopBurningEffect();
|
||||
BaseClass::UpdateOnRemove();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFCompoundBow::OnDataChanged( DataUpdateType_t type )
|
||||
{
|
||||
BaseClass::OnDataChanged( type );
|
||||
|
||||
// Handle particle effect creation / destruction
|
||||
if ( m_bArrowAlight && !m_pBurningArrowEffect )
|
||||
{
|
||||
StartBurningEffect();
|
||||
EmitSound( "ArrowLight" );
|
||||
}
|
||||
else if ( !m_bArrowAlight && m_pBurningArrowEffect )
|
||||
{
|
||||
StopBurningEffect();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CTFCompoundBow::Reload( void )
|
||||
{
|
||||
if ( m_flNextPrimaryAttack > gpGlobals->curtime )
|
||||
return false;
|
||||
return BaseClass::Reload();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CTFCompoundBow::CalcIsAttackCriticalHelper()
|
||||
{
|
||||
CTFPlayer *pPlayer = GetTFPlayerOwner();
|
||||
|
||||
// Crit boosted players fire all crits
|
||||
if ( pPlayer && pPlayer->m_Shared.IsCritBoosted() )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CTFCompoundBow::SetArrowAlight( bool bAlight )
|
||||
{
|
||||
// Don't light arrows if we're still firing one.
|
||||
if (GetActivity() != ACT_ITEM2_VM_PRIMARYATTACK )
|
||||
{
|
||||
m_bArrowAlight = bAlight;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user