diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/server/tf/tf_projectile_flare.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/server/tf/tf_projectile_flare.cpp')
| -rw-r--r-- | game/server/tf/tf_projectile_flare.cpp | 625 |
1 files changed, 625 insertions, 0 deletions
diff --git a/game/server/tf/tf_projectile_flare.cpp b/game/server/tf/tf_projectile_flare.cpp new file mode 100644 index 0000000..ecf1779 --- /dev/null +++ b/game/server/tf/tf_projectile_flare.cpp @@ -0,0 +1,625 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// TF Nail +// +//============================================================================= +#include "cbase.h" +#include "tf_projectile_flare.h" +#include "soundent.h" +#include "tf_fx.h" +#include "tf_player.h" +#include "tf_weapon_flaregun.h" +#include "tf_gamerules.h" + +//============================================================================= +// +// TF Flare Projectile functions (Server specific). +// +#define FLARE_MODEL "models/weapons/w_models/w_flaregun_shell.mdl" +#define FLARE_GRAVITY 0.3f +#define FLARE_SPEED 2000.0f + +#define FLARE_THINK_CONTEXT "CTFProjectile_FlareThink" + +LINK_ENTITY_TO_CLASS( tf_projectile_flare, CTFProjectile_Flare ); +PRECACHE_WEAPON_REGISTER( tf_projectile_flare ); + +IMPLEMENT_NETWORKCLASS_ALIASED( TFProjectile_Flare, DT_TFProjectile_Flare ) + +BEGIN_NETWORK_TABLE( CTFProjectile_Flare, DT_TFProjectile_Flare ) + SendPropBool( SENDINFO( m_bCritical ) ), +END_NETWORK_TABLE() + +BEGIN_DATADESC( CTFProjectile_Flare ) +DEFINE_THINKFUNC( ImpactThink ), +END_DATADESC() + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CTFProjectile_Flare::CTFProjectile_Flare() +{ + m_bIsFromTaunt = false; + m_bCritical = false; + m_bImpact = false; + m_flImpactTime = 0.0f; + m_flNextSeekUpdate = 0.0f; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CTFProjectile_Flare::~CTFProjectile_Flare() +{ + +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CTFProjectile_Flare *CTFProjectile_Flare::Create( CBaseEntity *pLauncher, const Vector &vecOrigin, const QAngle &vecAngles, CBaseEntity *pOwner, CBaseEntity *pScorer ) +{ + CTFProjectile_Flare *pFlare = static_cast<CTFProjectile_Flare*>( CBaseEntity::CreateNoSpawn( "tf_projectile_flare", vecOrigin, vecAngles, pOwner ) ); + if ( !pFlare ) + return NULL; + + pFlare->SetLauncher( pLauncher ); + + // Initialize the owner. + pFlare->SetOwnerEntity( pOwner ); + + // Set team. + pFlare->ChangeTeam( pOwner->GetTeamNumber() ); + + // Save the scoring player. + pFlare->SetScorer( pScorer ); + + // Spawn. + DispatchSpawn( pFlare ); + + // Setup the initial velocity. + Vector vecForward, vecRight, vecUp; + AngleVectors( vecAngles, &vecForward, &vecRight, &vecUp ); + + float flLaunchSpeed = pFlare->GetProjectileSpeed(); + + Vector vecVelocity = vecForward * flLaunchSpeed; + pFlare->SetAbsVelocity( vecVelocity ); + pFlare->SetupInitialTransmittedGrenadeVelocity( vecVelocity ); + + float flGravity = FLARE_GRAVITY; + CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( pLauncher, flGravity, mult_projectile_speed ); + pFlare->SetGravity( flGravity ); + + // Setup the initial angles. + QAngle angles; + VectorAngles( vecVelocity, angles ); + pFlare->SetAbsAngles( angles ); + + return pFlare; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFProjectile_Flare::Spawn() +{ + SetModel( FLARE_MODEL ); + BaseClass::Spawn(); + + float flHeatSeekPower = GetHeatSeekPower(); + + if ( flHeatSeekPower > 0.0f ) + { + SetMoveType( MOVETYPE_CUSTOM, MOVECOLLIDE_DEFAULT ); + SetGravity( FLARE_GRAVITY ); + } + else + { + SetMoveType( MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_CUSTOM ); + SetGravity( FLARE_GRAVITY ); + } + + // Set team. + m_nSkin = ( GetTeamNumber() == TF_TEAM_BLUE ) ? 1 : 0; + + m_flCreationTime = gpGlobals->curtime; + + CTFPlayer *pScorer = ToTFPlayer( GetScorer() ); + if ( pScorer && pScorer->IsTaunting() && m_flCreationTime >= pScorer->GetTauntAttackTime() ) + { + m_bIsFromTaunt = true; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFProjectile_Flare::Precache() +{ + PrecacheModel( FLARE_MODEL ); + PrecacheParticleSystem( "flaregun_trail_red" ); + PrecacheParticleSystem( "flaregun_trail_crit_red" ); + PrecacheParticleSystem( "flaregun_trail_blue" ); + PrecacheParticleSystem( "flaregun_trail_crit_blue" ); + PrecacheParticleSystem( "drg_manmelter_projectile" ); + PrecacheParticleSystem( "scorchshot_trail_red" ); + PrecacheParticleSystem( "scorchshot_trail_crit_red" ); + PrecacheParticleSystem( "scorchshot_trail_blue" ); + PrecacheParticleSystem( "scorchshot_trail_crit_blue" ); + PrecacheParticleSystem( "Explosions_MA_FlyingEmbers" ); + + PrecacheParticleSystem( "pyrovision_flaregun_trail_blue" ); + PrecacheParticleSystem( "pyrovision_flaregun_trail_red" ); + PrecacheParticleSystem( "pyrovision_flaregun_trail_crit_blue" ); + PrecacheParticleSystem( "pyrovision_flaregun_trail_crit_red" ); + PrecacheParticleSystem( "pyrovision_scorchshot_trail_blue" ); + PrecacheParticleSystem( "pyrovision_scorchshot_trail_red" ); + PrecacheParticleSystem( "pyrovision_scorchshot_trail_crit_blue" ); + PrecacheParticleSystem( "pyrovision_scorchshot_trail_crit_red" ); + + BaseClass::Precache(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFProjectile_Flare::SetScorer( CBaseEntity *pScorer ) +{ + m_Scorer = pScorer; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CBasePlayer *CTFProjectile_Flare::GetScorer( void ) +{ + return dynamic_cast<CBasePlayer *>( m_Scorer.Get() ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +int CTFProjectile_Flare::GetDamageType() +{ + int iDmgType = BaseClass::GetDamageType(); + if ( m_bCritical ) + { + iDmgType |= DMG_CRITICAL; + } + + return iDmgType; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFProjectile_Flare::Explode( trace_t *pTrace, CBaseEntity *pOther ) +{ + Vector vecOrigin = GetAbsOrigin(); + + CBaseEntity *pAttacker = GetOwnerEntity(); + IScorer *pScorerInterface = dynamic_cast<IScorer*>( pAttacker ); + if ( pScorerInterface ) + { + pAttacker = pScorerInterface->GetScorer(); + } + + CTFPlayer *pTFVictim = ToTFPlayer( pOther ); + + CTFFlareGun *pFlareGun = dynamic_cast< CTFFlareGun* >( GetLauncher() ); + if ( pFlareGun ) + { + if ( pFlareGun->GetFlareGunType() == FLAREGUN_SCORCHSHOT ) + { + // When the scorch shot hits a player... + if ( pTFVictim ) + { + // Now it only collides with the world + SetCollisionGroup( COLLISION_GROUP_DEBRIS ); + + Vector vVelocity = GetAbsVelocity(); + + // Check if burning before damage + bool bIsBurningVictim = pTFVictim->m_Shared.InCond( TF_COND_BURNING ); + int iDamageType = GetDamageType(); + + // Prevent the normal push force cause we are going to add it + iDamageType |= DMG_PREVENT_PHYSICS_FORCE; + + // Damage the player to push them back + CTakeDamageInfo info( this, pAttacker, m_hLauncher, vec3_origin, vecOrigin, GetDamage(), iDamageType, m_bIsFromTaunt ? TF_DMG_CUSTOM_FLARE_PELLET : 0 ); + pTFVictim->TakeDamage( info ); + + bool bIsEnemy = pAttacker && pTFVictim->GetTeamNumber() != pAttacker->GetTeamNumber(); + + // Quick Fix Uber and teammates are immune to the force + if ( !pTFVictim->m_Shared.InCond( TF_COND_MEGAHEAL ) && bIsEnemy ) + { + Vector vecToTarget; + vecToTarget = vVelocity; + VectorNormalize( vecToTarget ); + vecToTarget.z = 1.0; + + // apply airblast - Apply stun if they are effectively grounded so we can knock them up + if ( !pTFVictim->m_Shared.InCond( TF_COND_KNOCKED_INTO_AIR ) ) + { + pTFVictim->m_Shared.StunPlayer( 0.5, 1.f, TF_STUN_MOVEMENT, ToTFPlayer( pAttacker ) ); + } + + float flForce = bIsBurningVictim ? 400.0f : 100.0f; + pTFVictim->ApplyAirBlastImpulse( vecToTarget * flForce ); + } + + // It loses almost all of its speed and pops into the air + vVelocity.x *= 0.07f; + vVelocity.y *= 0.07f; + vVelocity.z = 100.0f; + SetAbsVelocity( vVelocity + RandomVector( -2.0f, 2.0f ) ); + + // Point the new direction and randomly flip + QAngle angForward; + VectorAngles( vVelocity, angForward ); + SetAbsAngles( angForward ); + + QAngle angRotation = RandomAngle( 180.0f, 720.0f ); + angRotation.x *= ( RandomInt( 0, 1 ) == 0 ? 1 : -1 ); + angRotation.y *= ( RandomInt( 0, 1 ) == 0 ? 1 : -1 ); + angRotation.z *= ( RandomInt( 0, 1 ) == 0 ? 1 : -1 ); + + SetLocalAngularVelocity( angRotation ); + + CPVSFilter filter( vecOrigin ); + EmitSound( filter, entindex(), "Rubber.BulletImpact" ); + + // Save this entity as enemy, they will take 100% damage. + if ( m_hEnemy.Get() == NULL ) + { + m_hEnemy = pTFVictim; + } + + return; + } + } + } + + // If we've already got an impact time, don't impact again. + if ( m_flImpactTime > 0.0 ) + return; + + // Save this entity as enemy, they will take 100% damage. + if ( m_hEnemy.Get() == NULL ) + { + m_hEnemy = pOther; + } + + if ( !pTFVictim ) + { + m_bImpact = true; + } + + // Invisible. + AddSolidFlags( FSOLID_NOT_SOLID ); + m_takedamage = DAMAGE_NO; + + bool bDetonate = false; + bool bNoRandomCrit = false; + if ( pFlareGun ) + { + switch ( pFlareGun->GetFlareGunType() ) + { + case FLAREGUN_DETONATE: + bDetonate = true; + break; + + case FLAREGUN_GRORDBORT: + bNoRandomCrit = true; + break; + + case FLAREGUN_SCORCHSHOT: + bDetonate = true; + bNoRandomCrit = true; + break; + } + } + + // Flares that hit a burning player crit, unless it's a detonate flare - they mini-crit + if ( pTFVictim && pTFVictim->m_Shared.InCond( TF_COND_BURNING ) && !bDetonate && !bNoRandomCrit ) + { + m_bCritical = true; + } + + CTakeDamageInfo info( this, pAttacker, m_hLauncher, vec3_origin, vecOrigin, GetDamage(), GetDamageType(), TF_DMG_CUSTOM_BURNING_FLARE ); + pOther->TakeDamage( info ); + + // Remove the flare. + if ( m_bImpact ) + { + SetMoveType( MOVETYPE_FLY ); + SetAbsVelocity( vec3_origin ); + + m_vecImpactNormal = pTrace->plane.normal; + m_flImpactTime = gpGlobals->curtime + 0.1f; + + // Stick into and object and fizzle a little while. + SetContextThink( &CTFProjectile_Flare::ImpactThink, gpGlobals->curtime, FLARE_THINK_CONTEXT ); + + // Only do this for the Detonator + if ( bDetonate ) + { + // Scorch Shot can still light others in this case + Detonate( pFlareGun->GetFlareGunType() != FLAREGUN_SCORCHSHOT ); + } + } + else + { + // Impact player sound. + CPVSFilter filter( vecOrigin ); + EmitSound( filter, pOther->entindex(), "TFPlayer.FlareImpact" ); + + SendDeathNotice(); + UTIL_Remove( this ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: Custom explode for air burst flare +//----------------------------------------------------------------------------- +void CTFProjectile_Flare::Explode_Air( trace_t *pTrace, int bitsDamageType, bool bSelfOnly ) +{ + // Invisible. + AddSolidFlags( FSOLID_NOT_SOLID ); + m_takedamage = DAMAGE_NO; + + // Play explosion sound and effect. + Vector vecOrigin = GetAbsOrigin(); + CPVSFilter filter( vecOrigin ); + + CBaseEntity *pAttacker = GetOwnerEntity(); + int nDefID = -1; + WeaponSound_t nSound = SPECIAL1; + if ( pAttacker ) + { + CTFFlareGun *pFlareGun = dynamic_cast<CTFFlareGun*>( ToTFPlayer( pAttacker )->GetActiveWeapon() ); + if ( pFlareGun ) + { + CEconItemView *pItem = pFlareGun->GetAttributeContainer()->GetItem(); + nDefID = pItem->GetItemDefIndex(); + } + + // Damage. + IScorer *pScorerInterface = dynamic_cast<IScorer*>( pAttacker ); + if ( pScorerInterface ) + { + pAttacker = pScorerInterface->GetScorer(); + } + + float flRadius = bSelfOnly ? 0.f : GetRadius(); + + if ( bSelfOnly ) + { + bitsDamageType |= DMG_BLAST; + nSound = SPECIAL2; + } + +#if defined( _DEBUG ) && defined( STAGING_ONLY ) + // Debug! + ConVarRef tf_rocket_show_radius( "tf_rocket_show_radius" ); + if ( tf_rocket_show_radius.GetBool() ) + { + DrawRadius( flRadius ); + } +#endif + CTakeDamageInfo info( this, pAttacker, m_hLauncher, vec3_origin, vecOrigin, GetDamage(), bitsDamageType | DMG_HALF_FALLOFF, TF_DMG_CUSTOM_FLARE_EXPLOSION ); + CTFRadiusDamageInfo radiusinfo( &info, vecOrigin, flRadius, NULL, TF_FLARE_RADIUS_FOR_FJS ); + TFGameRules()->RadiusDamage( radiusinfo ); + } + + const char *pszParticle = bSelfOnly ? "Explosions_MA_FlyingEmbers" : "ExplosionCore_MidAir_Flare"; + TE_TFExplosion( filter, 0.0f, vecOrigin, pTrace->plane.normal, GetWeaponID(), entindex(), nDefID, nSound ); + TE_TFParticleEffect( filter, 0.0f, pszParticle, vecOrigin, pTrace->plane.normal, vec3_angle ); + CSoundEnt::InsertSound ( SOUND_COMBAT, vecOrigin, 1024, 3.0 ); + + SendDeathNotice(); + UTIL_Remove( this ); +} + +//----------------------------------------------------------------------------- +// Purpose: Alt-fire air burst flare +//----------------------------------------------------------------------------- +void CTFProjectile_Flare::Detonate( bool bSelfOnly ) +{ + trace_t tr; + Vector vecSpot; + + SetThink( NULL ); + + vecSpot = GetAbsOrigin() + Vector ( 0 , 0 , 8 ); + UTIL_TraceLine ( vecSpot, vecSpot + Vector ( 0, 0, -32 ), MASK_SHOT_HULL, this, COLLISION_GROUP_NONE, & tr); + + Explode_Air( &tr, GetDamageType(), bSelfOnly ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +float CTFProjectile_Flare::GetRadius( void ) +{ + float flRadius = TF_FLARE_DET_RADIUS; + CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( m_hLauncher, flRadius, mult_explosion_radius ); + return flRadius; +} + +//----------------------------------------------------------------------------- +// Purpose: Let the flaregun know we're gone +//----------------------------------------------------------------------------- +void CTFProjectile_Flare::SendDeathNotice( void ) +{ + CBaseEntity *pAttacker = GetOwnerEntity(); + if ( !pAttacker ) + return; + + CTFFlareGun *pFlareGun = dynamic_cast<CTFFlareGun*>( ToTFPlayer( pAttacker )->GetActiveWeapon() ); + if ( pFlareGun && pFlareGun->GetFlareGunType() == FLAREGUN_DETONATE ) + { + pFlareGun->DeathNotice( this ); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CTFProjectile_Flare::ImpactThink( void ) +{ + if ( gpGlobals->curtime > m_flImpactTime ) + { + // If we hit anything other than the player create an impact - effect, sound, etc. + if ( m_hEnemy.Get() ) + { + Vector vecOrigin = GetAbsOrigin(); + CPVSFilter filter( vecOrigin ); + TE_TFExplosion( filter, 0.0f, vecOrigin, m_vecImpactNormal, GetWeaponID(), m_hEnemy.Get()->entindex() ); + } + + SendDeathNotice(); + UTIL_Remove( this ); + SetContextThink( NULL, 0, FLARE_THINK_CONTEXT ); + } + else + { + SetContextThink( &CTFProjectile_Flare::ImpactThink, gpGlobals->curtime + 0.1f, FLARE_THINK_CONTEXT ); + } +} + +void CTFProjectile_Flare::PerformCustomPhysics( Vector *pNewPosition, Vector *pNewVelocity, QAngle *pNewAngles, QAngle *pNewAngVelocity ) +{ + if ( m_flNextSeekUpdate < gpGlobals->curtime ) + { + CTFPlayer *pBestTarget = NULL; + const float flMaxSeekDistanceSqr = ( 1024.0f * 1024.0f ); + float flBestDistance = flMaxSeekDistanceSqr; + + // Loop through players and attempt to find a seek target + int i; + for ( i = 1; i <= gpGlobals->maxClients; i++ ) + { + CTFPlayer *pPlayer = ToTFPlayer( UTIL_PlayerByIndex( i ) ); + if ( !pPlayer ) + continue; + + bool bBurning = pPlayer->m_Shared.InCond( TF_COND_BURNING ); + + if ( !bBurning || + pPlayer->InSameTeam( this ) || + ( pPlayer->m_Shared.GetDisguiseTeam() == GetTeamNumber() && !bBurning ) || + ( pPlayer->m_Shared.IsStealthed() && !bBurning ) || + pPlayer->GetTeamNumber() == TEAM_SPECTATOR || + !pPlayer->IsAlive() ) + { + continue; + } + + Vector vToTarget = pPlayer->WorldSpaceCenter() - GetAbsOrigin(); + VectorNormalize( vToTarget ); + + Vector vForward = *pNewVelocity; + VectorNormalize( vForward ); + + if ( vToTarget.Dot( vForward ) < -0.25f ) + continue; + + float flDistanceSqr = pPlayer->WorldSpaceCenter().DistToSqr( GetAbsOrigin() ); + if ( flBestDistance > flDistanceSqr ) + { + trace_t tr; + UTIL_TraceLine( pPlayer->WorldSpaceCenter(), GetAbsOrigin(), MASK_SOLID_BRUSHONLY, pPlayer, COLLISION_GROUP_NONE, &tr ); + if ( !tr.DidHit() || tr.m_pEnt == this ) + { + flBestDistance = flDistanceSqr; + pBestTarget = pPlayer; + } + } + } + + float flHeatSeekPower = GetHeatSeekPower(); + + QAngle angToTarget = *pNewAngles; + + if ( pBestTarget ) + { + Vector vToTarget = pBestTarget->WorldSpaceCenter() - GetAbsOrigin(); + VectorAngles( vToTarget, angToTarget ); + } + + const float flUpdatesPerSecond = 4.0f; + + if ( angToTarget != *pNewAngles ) + { + pNewAngVelocity->x = Approach( UTIL_AngleDiff( angToTarget.x, pNewAngles->x ) * flUpdatesPerSecond, pNewAngVelocity->x, flHeatSeekPower ); + pNewAngVelocity->y = Approach( UTIL_AngleDiff( angToTarget.y, pNewAngles->y ) * flUpdatesPerSecond, pNewAngVelocity->y, flHeatSeekPower ); + pNewAngVelocity->z = Approach( UTIL_AngleDiff( angToTarget.z, pNewAngles->z ) * flUpdatesPerSecond, pNewAngVelocity->z, flHeatSeekPower ); + + const float flMaxAngularVelocity = 360.0f; + pNewAngVelocity->x = clamp( pNewAngVelocity->x, -flMaxAngularVelocity, flMaxAngularVelocity ); + pNewAngVelocity->y = clamp( pNewAngVelocity->y, -flMaxAngularVelocity, flMaxAngularVelocity ); + pNewAngVelocity->z = clamp( pNewAngVelocity->z, -flMaxAngularVelocity, flMaxAngularVelocity ); + } + + m_flNextSeekUpdate = gpGlobals->curtime + ( 1.0f / flUpdatesPerSecond ); + } + + *pNewAngles += *pNewAngVelocity * gpGlobals->frametime; + + Vector vForward; + AngleVectors( *pNewAngles, &vForward ); + *pNewVelocity = vForward * GetProjectileSpeed(); + + *pNewPosition += *pNewVelocity * gpGlobals->frametime; +} + +//----------------------------------------------------------------------------- +// Purpose: Flare was deflected. +//----------------------------------------------------------------------------- +void CTFProjectile_Flare::Deflected( CBaseEntity *pDeflectedBy, Vector &vecDir ) +{ + CTFPlayer *pTFDeflector = ToTFPlayer( pDeflectedBy ); + if ( !pTFDeflector ) + return; + + ChangeTeam( pTFDeflector->GetTeamNumber() ); + SetLauncher( pTFDeflector->GetActiveWeapon() ); + + CTFPlayer* pOldOwner = ToTFPlayer( GetOwnerEntity() ); + SetOwnerEntity( pTFDeflector ); + + if ( pOldOwner ) + { + pOldOwner->SpeakConceptIfAllowed( MP_CONCEPT_DEFLECTED, "projectile:1,victim:1" ); + } + + if ( pTFDeflector->m_Shared.IsCritBoosted() ) + { + SetCritical( true ); + } + + CTFWeaponBase::SendObjectDeflectedEvent( pTFDeflector, pOldOwner, GetWeaponID(), this ); + + IncrementDeflected(); + SetScorer( pTFDeflector ); +} + +float CTFProjectile_Flare::GetProjectileSpeed( void ) const +{ + float flLaunchSpeed = FLARE_SPEED; + CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( m_hLauncher, flLaunchSpeed, mult_projectile_speed ); + + return flLaunchSpeed; +} + +float CTFProjectile_Flare::GetHeatSeekPower( void ) const +{ + float flHeatSeekPower = 0.0; + CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( m_hLauncher, flHeatSeekPower, mod_projectile_heat_seek_power ); + + return flHeatSeekPower; +}
\ No newline at end of file |