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.
685 lines
19 KiB
685 lines
19 KiB
//========= 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; |
|
} |
|
} |