mirror of
https://github.com/ValveSoftware/source-sdk-2013.git
synced 2025-03-27 12:49:23 +03:00
930 lines
26 KiB
C++
930 lines
26 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose:
|
|
//
|
|
//=============================================================================
|
|
|
|
#include "cbase.h"
|
|
#include "tf_weapon_rocketpack.h"
|
|
#include "tf_gamerules.h"
|
|
#include "in_buttons.h"
|
|
|
|
// Client specific.
|
|
#ifdef CLIENT_DLL
|
|
#include "c_tf_player.h"
|
|
#include "c_rope.h"
|
|
#include "prediction.h"
|
|
// Server specific.
|
|
#else
|
|
#include "tf_player.h"
|
|
#include "tf_ammo_pack.h"
|
|
#include "ilagcompensationmanager.h"
|
|
#include "tf_gamestats.h"
|
|
#include "tf_fx.h"
|
|
#include "tf_weapon_medigun.h"
|
|
#endif
|
|
|
|
//#define ROCKET_PACK_LAUNCH_EFFECT "rocketpack_exhaust_fire"
|
|
#define ROCKET_PACK_LAUNCH_EFFECT "rocketpack_exhaust_launch"
|
|
#define ROCKET_PACK_LAUNCH_EFFECT_TRAIL "rocketpack_exhaust"
|
|
|
|
// TFRocketPack --
|
|
IMPLEMENT_NETWORKCLASS_ALIASED( TFRocketPack, DT_TFWeaponRocketPack )
|
|
|
|
BEGIN_NETWORK_TABLE( CTFRocketPack, DT_TFWeaponRocketPack )
|
|
#ifdef CLIENT_DLL
|
|
RecvPropFloat( RECVINFO( m_flInitLaunchTime ) ),
|
|
RecvPropFloat( RECVINFO( m_flLaunchTime ) ),
|
|
RecvPropFloat( RECVINFO( m_flToggleEndTime ) ),
|
|
RecvPropBool( RECVINFO( m_bEnabled ) ),
|
|
#else
|
|
SendPropFloat( SENDINFO( m_flInitLaunchTime ) ),
|
|
SendPropFloat( SENDINFO( m_flLaunchTime ) ),
|
|
SendPropFloat( SENDINFO( m_flToggleEndTime ) ),
|
|
SendPropBool( SENDINFO( m_bEnabled ) ),
|
|
#endif
|
|
END_NETWORK_TABLE()
|
|
|
|
#ifdef CLIENT_DLL
|
|
BEGIN_PREDICTION_DATA( CTFRocketPack )
|
|
DEFINE_PRED_FIELD( m_flInitLaunchTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
|
|
DEFINE_PRED_FIELD( m_flLaunchTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
|
|
DEFINE_PRED_FIELD( m_flToggleEndTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ),
|
|
DEFINE_PRED_FIELD( m_flRefireTime, FIELD_FLOAT, 0 ),
|
|
DEFINE_PRED_FIELD( m_bLaunchedFromGround, FIELD_BOOLEAN, 0 ),
|
|
END_PREDICTION_DATA()
|
|
#endif // CLIENT_DLL
|
|
|
|
LINK_ENTITY_TO_CLASS( tf_weapon_rocketpack, CTFRocketPack );
|
|
PRECACHE_WEAPON_REGISTER( tf_weapon_rocketpack );
|
|
|
|
// Todo: Mark as cheat prior to shipping
|
|
ConVar tf_rocketpack_cost( "tf_rocketpack_cost", "50", FCVAR_REPLICATED | FCVAR_CHEAT | FCVAR_HIDDEN );
|
|
ConVar tf_rocketpack_launch_delay( "tf_rocketpack_launch_delay", "0.65", FCVAR_REPLICATED | FCVAR_CHEAT | FCVAR_HIDDEN );
|
|
ConVar tf_rocketpack_refire_delay( "tf_rocketpack_refire_delay", "1.2", FCVAR_REPLICATED | FCVAR_CHEAT | FCVAR_HIDDEN );
|
|
ConVar tf_rocketpack_toggle_duration( "tf_rocketpack_toggle_duration", "1.0", FCVAR_REPLICATED | FCVAR_CHEAT | FCVAR_HIDDEN );
|
|
ConVar tf_rocketpack_delay_launch( "tf_rocketpack_delay_launch", "0", FCVAR_REPLICATED | FCVAR_CHEAT | FCVAR_HIDDEN );
|
|
ConVar tf_rocketpack_launch_absvelocity_preserved( "tf_rocketpack_launch_absvelocity_preserved", "0", FCVAR_REPLICATED | FCVAR_CHEAT | FCVAR_HIDDEN );
|
|
ConVar tf_rocketpack_airborne_launch_absvelocity_preserved( "tf_rocketpack_airborne_launch_absvelocity_preserved", "0", FCVAR_REPLICATED | FCVAR_CHEAT | FCVAR_HIDDEN );
|
|
ConVar tf_rocketpack_impact_push_min( "tf_rocketpack_impact_push_min", "100", FCVAR_REPLICATED | FCVAR_CHEAT | FCVAR_HIDDEN );
|
|
ConVar tf_rocketpack_impact_push_max( "tf_rocketpack_impact_push_max", "300", FCVAR_REPLICATED | FCVAR_CHEAT | FCVAR_HIDDEN );
|
|
ConVar tf_rocketpack_launch_push( "tf_rocketpack_launch_push", "250", FCVAR_REPLICATED | FCVAR_CHEAT | FCVAR_HIDDEN );
|
|
|
|
#ifdef GAME_DLL
|
|
#define TF_ROCKETPACK_PASSENGER_DELAY_LAUNCH 0.2f
|
|
#endif // GAME_DLL
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
CTFRocketPack::CTFRocketPack()
|
|
{
|
|
m_flRefireTime = 0.f;
|
|
m_flInitLaunchTime = 0.f;
|
|
m_flLaunchTime = 0.f;
|
|
m_flToggleEndTime = -1.f;
|
|
|
|
m_bEnabled = false;
|
|
m_bLaunchedFromGround = false;
|
|
|
|
#ifdef GAME_DLL
|
|
|
|
#else
|
|
ListenForGameEvent( "rocketpack_landed" );
|
|
|
|
m_flOldInitLaunchTime = 0.f;
|
|
m_bWasEnabled = false;
|
|
#endif // CLIENT_DLL
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFRocketPack::WeaponReset( void )
|
|
{
|
|
BaseClass::WeaponReset();
|
|
|
|
CTFPlayer *pOwner = ToTFPlayer( GetOwner() );
|
|
if ( !pOwner )
|
|
return;
|
|
|
|
if ( m_flInitLaunchTime > 0.f )
|
|
{
|
|
pOwner->StopSound( "Weapon_LooseCannon.Charge" );
|
|
}
|
|
|
|
m_flRefireTime = 0.f;
|
|
m_flInitLaunchTime = 0.f;
|
|
|
|
ResetTransition();
|
|
|
|
#ifdef GAME_DLL
|
|
SetEnabled( false );
|
|
#endif // GAME_DLL
|
|
|
|
#ifdef CLIENT_DLL
|
|
m_flOldInitLaunchTime = 0.f;
|
|
m_bWasEnabled = false;
|
|
CleanupParticles();
|
|
#endif // CLIENT_DLL
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFRocketPack::Precache( void )
|
|
{
|
|
BaseClass::Precache();
|
|
|
|
PrecacheScriptSound( "Weapon_RocketPack.BoostersExtend" );
|
|
PrecacheScriptSound( "Weapon_RocketPack.BoostersReady" ); // ( after initial extend or heat bar returns to yellow )
|
|
PrecacheScriptSound( "Weapon_RocketPack.BoostersCharge" ); // ( mouse click but yet to take off )
|
|
PrecacheScriptSound( "Weapon_RocketPack.BoostersFire" ); // ( take off and fly, has a loop, we'll see how this sounds)
|
|
PrecacheScriptSound( "Weapon_RocketPack.BoostersShutdown" );// ( can play this when you land for now, will cut off the loop )
|
|
PrecacheScriptSound( "Weapon_RocketPack.Land" ); // ( also plays when you land, on a different channel )
|
|
PrecacheScriptSound( "Weapon_RocketPack.BoostersNotReady" );// ( attempt to use but heat bar is in the red )
|
|
PrecacheScriptSound( "Weapon_RocketPack.BoostersRetract" );
|
|
|
|
PrecacheParticleSystem( ROCKET_PACK_LAUNCH_EFFECT );
|
|
PrecacheParticleSystem( ROCKET_PACK_LAUNCH_EFFECT_TRAIL );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
bool CTFRocketPack::CanFire( void ) const
|
|
{
|
|
if ( !m_bEnabled )
|
|
return false;
|
|
|
|
CTFPlayer *pOwner = GetTFPlayerOwner();
|
|
if ( !pOwner )
|
|
return false;
|
|
|
|
if ( !pOwner->CanPlayerMove() )
|
|
return false;
|
|
|
|
if ( !TFGameRules() )
|
|
return false;
|
|
|
|
if ( TFGameRules()->State_Get() == GR_STATE_PREROUND )
|
|
return false;
|
|
|
|
if ( pOwner->m_Shared.IsLoser() )
|
|
return false;
|
|
|
|
/*if ( pOwner->m_Shared.InCond( TF_COND_STUNNED ) )
|
|
return false;*/
|
|
|
|
if ( pOwner->IsTaunting() )
|
|
return false;
|
|
|
|
if ( m_flRefireTime > gpGlobals->curtime )
|
|
return false;
|
|
|
|
if ( !pOwner->m_Shared.IsRocketPackReady() )
|
|
return false;
|
|
|
|
// Transitioning
|
|
if ( IsInTransition() && !IsTransitionCompleted() )
|
|
return false;
|
|
|
|
if ( m_flNextSecondaryAttack > gpGlobals->curtime )
|
|
return false;
|
|
|
|
if ( pOwner->m_Shared.InCond( TF_COND_ROCKETPACK ) )
|
|
{
|
|
int iAirLaunch = 0;
|
|
CALL_ATTRIB_HOOK_INT_ON_OTHER( pOwner, iAirLaunch, thermal_thruster_air_launch );
|
|
if ( !iAirLaunch )
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
bool CTFRocketPack::InitiateLaunch( void )
|
|
{
|
|
if ( !CanFire() )
|
|
return false;
|
|
|
|
CTFPlayer *pOwner = GetTFPlayerOwner();
|
|
if ( !pOwner->m_Shared.IsRocketPackReady() )
|
|
{
|
|
// note: this is never reached
|
|
#ifdef CLIENT_DLL
|
|
if ( prediction->IsFirstTimePredicted() )
|
|
{
|
|
pOwner->EmitSound( "Weapon_RocketPack.BoostersNotReady" );
|
|
}
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
if ( m_flInitLaunchTime > 0 )
|
|
{
|
|
m_flNextSecondaryAttack = gpGlobals->curtime + 0.1f;
|
|
return false;
|
|
}
|
|
|
|
#ifdef CLIENT_DLL
|
|
if ( prediction->IsFirstTimePredicted() )
|
|
#endif
|
|
{
|
|
CPASAttenuationFilter filter( pOwner );
|
|
filter.UsePredictionRules();
|
|
pOwner->EmitSound(
|
|
filter,
|
|
entindex(),
|
|
pOwner->m_Shared.IsLoser() ? "Weapon_RocketPack.BoostersNotReady" : "Weapon_RocketPack.BoostersCharge"
|
|
);
|
|
}
|
|
|
|
m_flInitLaunchTime = gpGlobals->curtime;
|
|
|
|
return true;
|
|
}
|
|
|
|
#ifdef CLIENT_DLL
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFRocketPack::OnPreDataChanged( DataUpdateType_t updateType )
|
|
{
|
|
BaseClass::OnPreDataChanged( updateType );
|
|
|
|
m_bWasEnabled = m_bEnabled;
|
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFRocketPack::OnDataChanged( DataUpdateType_t updateType )
|
|
{
|
|
BaseClass::OnDataChanged( updateType );
|
|
|
|
if ( m_flOldInitLaunchTime != m_flInitLaunchTime )
|
|
{
|
|
CleanupParticles();
|
|
|
|
CTFWearable *pWearable = m_hExtraWearable.Get();
|
|
if ( pWearable )
|
|
{
|
|
int iAttachL = pWearable->LookupAttachment( "charge_LA" );
|
|
int iAttachR = pWearable->LookupAttachment( "charge_RA" );
|
|
Assert( iAttachL != INVALID_PARTICLE_ATTACHMENT && iAttachR != INVALID_PARTICLE_ATTACHMENT );
|
|
m_hLeftTrail = pWearable->ParticleProp()->Create( ROCKET_PACK_LAUNCH_EFFECT_TRAIL, PATTACH_POINT_FOLLOW, iAttachL );
|
|
m_hRightTrail = pWearable->ParticleProp()->Create( ROCKET_PACK_LAUNCH_EFFECT_TRAIL, PATTACH_POINT_FOLLOW, iAttachR );
|
|
}
|
|
}
|
|
|
|
if ( m_bEnabled != m_bWasEnabled )
|
|
{
|
|
CTFWearable *pWearable = m_hExtraWearable.Get();
|
|
if ( pWearable )
|
|
{
|
|
if (m_bEnabled)
|
|
{
|
|
pWearable->ResetSequence( pWearable->LookupSequence( "deploy" ) );
|
|
}
|
|
else
|
|
{
|
|
pWearable->ResetSequence( pWearable->LookupSequence( "undeploy" ) );
|
|
}
|
|
pWearable->SetCycle( 0.f );
|
|
}
|
|
}
|
|
|
|
|
|
m_flOldInitLaunchTime = m_flInitLaunchTime;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFRocketPack::UpdateOnRemove( void )
|
|
{
|
|
BaseClass::UpdateOnRemove();
|
|
|
|
CleanupParticles();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFRocketPack::CleanupParticles( void )
|
|
{
|
|
CTFWearable *pWearable = m_hExtraWearable.Get();
|
|
if ( pWearable )
|
|
{
|
|
if ( m_hLeftBlast )
|
|
{
|
|
pWearable->ParticleProp()->StopEmission( m_hLeftBlast );
|
|
}
|
|
if ( m_hRightBlast )
|
|
{
|
|
pWearable->ParticleProp()->StopEmission( m_hRightBlast );
|
|
}
|
|
if ( m_hLeftTrail )
|
|
{
|
|
pWearable->ParticleProp()->StopEmission( m_hLeftTrail );
|
|
}
|
|
if ( m_hRightTrail )
|
|
{
|
|
pWearable->ParticleProp()->StopEmission( m_hRightTrail );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFRocketPack::FireGameEvent( IGameEvent *event )
|
|
{
|
|
CTFPlayer *pOwner = GetTFPlayerOwner();
|
|
if ( !pOwner )
|
|
return;
|
|
|
|
if ( FStrEq( event->GetName(), "rocketpack_landed" ) )
|
|
{
|
|
const int iUserID = event->GetInt( "userid" );
|
|
if ( pOwner->GetUserID() == iUserID )
|
|
{
|
|
CleanupParticles();
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
bool CTFRocketPack::ShouldDraw()
|
|
{
|
|
CTFPlayer *pOwner = GetTFPlayerOwner();
|
|
if ( pOwner && pOwner->IsTaunting() )
|
|
return BaseClass::ShouldDraw();
|
|
|
|
return false;
|
|
}
|
|
|
|
#endif // CLIENT_DLL
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
Vector CTFRocketPack::CalcRocketForceFromPlayer( CTFPlayer *pPlayer )
|
|
{
|
|
bool bOnGround = ( m_bLaunchedFromGround && abs( pPlayer->EyeAngles().x ) <= 15.f );
|
|
|
|
Vector vecDir;
|
|
Vector vecForce;
|
|
float flForce = 450.f;
|
|
const float flPushScale = 1.8f;
|
|
const float flVertPushScale = ( bOnGround ) ? 0.7f : 0.25f; // Less vertical force while airborne
|
|
|
|
Vector vecForward, vecRight;
|
|
QAngle angAim = pPlayer->EyeAngles();
|
|
AngleVectors( angAim, &vecForward, &vecRight, NULL );
|
|
bool bNone = !( pPlayer->m_nButtons & IN_FORWARD ) &&
|
|
!( pPlayer->m_nButtons & IN_BACK ) /* &&
|
|
!( pPlayer->m_nButtons & IN_MOVELEFT ) &&
|
|
!( pPlayer->m_nButtons & IN_MOVERIGHT ) */;
|
|
|
|
vecDir = vecForward;
|
|
|
|
if ( bNone || ( pPlayer->m_nButtons & IN_FORWARD ) )
|
|
{
|
|
//vecDir = vecForward;
|
|
}
|
|
else if ( pPlayer->m_nButtons & IN_BACK )
|
|
{
|
|
vecForward.Negate();
|
|
vecDir = vecForward;
|
|
}
|
|
|
|
// if ( pPlayer->m_nButtons & IN_MOVELEFT )
|
|
// {
|
|
// vecRight.Negate();
|
|
// vecDir += vecRight;
|
|
// }
|
|
// else if ( pPlayer->m_nButtons & IN_MOVERIGHT )
|
|
// {
|
|
// vecDir += vecRight;
|
|
// }
|
|
|
|
// Remove down if we're on the ground and aiming down
|
|
if ( bOnGround && vecDir.z < 0.f )
|
|
{
|
|
vecDir.z = 0.f;
|
|
}
|
|
|
|
vecForce = vecDir.Normalized() * flForce * flPushScale;
|
|
vecForce.z += 1.f * flForce * flVertPushScale;
|
|
|
|
// v1.0
|
|
// pPlayer->EyeVectors( &vecDir );
|
|
// Vector vecFlightDir = -vecDir;
|
|
// VectorNormalize( vecFlightDir );
|
|
//
|
|
// // Remove down if we're on the ground
|
|
// if ( bOnGround && vecDir.z < 0.f )
|
|
// {
|
|
// vecDir.z = 0.f;
|
|
// }
|
|
//
|
|
// vecForce = vecFlightDir * -flForce * flPushScale;
|
|
// vecForce.z += 1.f * flForce * flVertPushScale;
|
|
|
|
return vecForce;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFRocketPack::RocketLaunchPlayer( CTFPlayer *pPlayer, const Vector& vecForce, bool bIsPassenger )
|
|
{
|
|
if ( !pPlayer->m_Shared.InCond( TF_COND_ROCKETPACK ) )
|
|
{
|
|
pPlayer->m_Shared.AddCond( TF_COND_ROCKETPACK );
|
|
if ( bIsPassenger )
|
|
{
|
|
}
|
|
pPlayer->m_Shared.StunPlayer( 0.5f, 1.0f, TF_STUN_MOVEMENT );
|
|
UTIL_ScreenShake( pPlayer->GetAbsOrigin(), 100.f, 150, 0.5f, 128.f, SHAKE_START, true );
|
|
}
|
|
|
|
if ( pPlayer->GetFlags() & FL_ONGROUND )
|
|
{
|
|
if ( !tf_rocketpack_launch_absvelocity_preserved.GetBool() )
|
|
{
|
|
pPlayer->SetAbsVelocity( vec3_origin );
|
|
}
|
|
}
|
|
else if ( !tf_rocketpack_airborne_launch_absvelocity_preserved.GetBool() )
|
|
{
|
|
pPlayer->SetAbsVelocity( vec3_origin );
|
|
}
|
|
|
|
pPlayer->ApplyAbsVelocityImpulse( vecForce );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
bool CTFRocketPack::PreLaunch( void )
|
|
{
|
|
CTFPlayer *pOwner = GetTFPlayerOwner();
|
|
if ( !pOwner )
|
|
return false;
|
|
|
|
pOwner->DoAnimationEvent( PLAYERANIMEVENT_CUSTOM, ACT_MP_ATTACK_STAND_PRIMARYFIRE );
|
|
SendWeaponAnim( ACT_VM_PRIMARYATTACK );
|
|
|
|
// Negate any fall
|
|
Vector vecVel = pOwner->GetAbsVelocity();
|
|
if ( vecVel.z < 0.f )
|
|
{
|
|
vecVel.z = 0.f;
|
|
pOwner->SetAbsVelocity( vecVel );
|
|
}
|
|
|
|
// Pop them off the ground
|
|
Vector vForward( 0.f, 0.f, 350.f );
|
|
pOwner->ApplyAbsVelocityImpulse( vForward );
|
|
pOwner->m_Shared.AddCond( TF_COND_PARACHUTE_ACTIVE );
|
|
|
|
#ifdef GAME_DLL
|
|
const Vector &vecOrigin = pOwner->GetAbsOrigin();
|
|
CPVSFilter filter( vecOrigin );
|
|
TE_TFParticleEffect( filter, 0.f, "heavy_ring_of_fire", vecOrigin, vec3_angle );
|
|
DispatchParticleEffect( "rocketjump_smoke", PATTACH_POINT_FOLLOW, pOwner, "foot_L" );
|
|
DispatchParticleEffect( "rocketjump_smoke", PATTACH_POINT_FOLLOW, pOwner, "foot_R" );
|
|
#endif // GAME_DLL
|
|
|
|
m_flLaunchTime = gpGlobals->curtime + tf_rocketpack_launch_delay.GetFloat();
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
bool CTFRocketPack::Launch( void )
|
|
{
|
|
CTFPlayer *pOwner = GetTFPlayerOwner();
|
|
if ( !pOwner )
|
|
return false;
|
|
|
|
pOwner->StopSound( "Weapon_LooseCannon.Charge" );
|
|
|
|
m_flLaunchTime = 0.f;
|
|
pOwner->m_Shared.RemoveCond( TF_COND_PARACHUTE_ACTIVE );
|
|
|
|
#ifdef CLIENT_DLL
|
|
Vector m_vecLaunchDir;
|
|
#endif
|
|
// Launch
|
|
m_vecLaunchDir = CalcRocketForceFromPlayer( pOwner );
|
|
RocketLaunchPlayer( pOwner, m_vecLaunchDir, false );
|
|
|
|
#ifdef GAME_DLL
|
|
SetContextThink( &CTFRocketPack::PassengerDelayLaunchThink, gpGlobals->curtime + TF_ROCKETPACK_PASSENGER_DELAY_LAUNCH, "PassengerDelayLaunchThink" );
|
|
#endif
|
|
|
|
m_flRefireTime = gpGlobals->curtime + 0.5f;
|
|
|
|
{
|
|
pOwner->m_Shared.SetRocketPackCharge( pOwner->m_Shared.GetRocketPackCharge() - tf_rocketpack_cost.GetFloat() );
|
|
}
|
|
|
|
#ifdef GAME_DLL
|
|
// Knock-back nearby enemies
|
|
float flRadius = 150.f;
|
|
CUtlVector< CTFPlayer* > vecPushedPlayers;
|
|
TFGameRules()->PushAllPlayersAway( GetAbsOrigin(), flRadius, tf_rocketpack_launch_push.GetFloat(), GetEnemyTeam( GetTeamNumber() ), &vecPushedPlayers );
|
|
FOR_EACH_VEC( vecPushedPlayers, i )
|
|
{
|
|
IGameEvent *event = gameeventmanager->CreateEvent( "player_rocketpack_pushed" );
|
|
if ( event )
|
|
{
|
|
event->SetInt( "pusher", pOwner->GetUserID() );
|
|
event->SetInt( "pushed", vecPushedPlayers[ i ]->GetUserID() );
|
|
|
|
gameeventmanager->FireEvent( event, true );
|
|
}
|
|
}
|
|
|
|
// Extinguish teammates
|
|
CUtlVector< CTFPlayer * > vecPlayers;
|
|
CollectPlayers( &vecPlayers, pOwner->GetTeamNumber(), COLLECT_ONLY_LIVING_PLAYERS );
|
|
FOR_EACH_VEC( vecPlayers, i )
|
|
{
|
|
CTFPlayer *pPlayer = vecPlayers[i];
|
|
if ( !pPlayer )
|
|
continue;
|
|
|
|
if ( !pPlayer->m_Shared.InCond( TF_COND_BURNING ) )
|
|
continue;
|
|
|
|
if ( ( pPlayer->GetAbsOrigin() - GetAbsOrigin() ).LengthSqr() > ( flRadius * flRadius ) )
|
|
continue;
|
|
|
|
if ( !pOwner->FVisible( pPlayer, MASK_OPAQUE ) )
|
|
continue;
|
|
|
|
pPlayer->m_Shared.RemoveCond( TF_COND_BURNING );
|
|
pPlayer->EmitSound( "TFPlayer.FlameOut" );
|
|
CTF_GameStats.Event_PlayerAwardBonusPoints( pOwner, pPlayer, 10 );
|
|
|
|
// Event of this happening
|
|
IGameEvent *pEvent = gameeventmanager->CreateEvent( "player_extinguished" );
|
|
if ( pEvent )
|
|
{
|
|
pEvent->SetInt( "victim", pPlayer->entindex() );
|
|
pEvent->SetInt( "healer", pOwner->entindex() );
|
|
|
|
item_definition_index_t nDefIndex = INVALID_ITEM_DEF_INDEX;
|
|
if ( GetAttributeContainer() && GetAttributeContainer()->GetItem() )
|
|
{
|
|
nDefIndex = GetAttributeContainer()->GetItem()->GetItemDefinition()->GetDefinitionIndex();
|
|
}
|
|
|
|
pEvent->SetInt( "itemdefindex", nDefIndex );
|
|
|
|
gameeventmanager->FireEvent( pEvent, true );
|
|
}
|
|
}
|
|
|
|
CPASAttenuationFilter filter( pOwner );
|
|
filter.UsePredictionRules();
|
|
pOwner->EmitSound( filter, pOwner->entindex(), "Weapon_RocketPack.BoostersFire" );
|
|
|
|
IGameEvent *pEvent = gameeventmanager->CreateEvent( "rocketpack_launch" );
|
|
if ( pEvent )
|
|
{
|
|
pEvent->SetInt( "userid", pOwner->GetUserID() );
|
|
pEvent->SetBool( "playsound", true );
|
|
gameeventmanager->FireEvent( pEvent );
|
|
}
|
|
|
|
CTFWearable *pWearable = m_hExtraWearable.Get();
|
|
if ( pWearable )
|
|
{
|
|
DispatchParticleEffect( ROCKET_PACK_LAUNCH_EFFECT, PATTACH_POINT_FOLLOW, pWearable, "charge_LA" );
|
|
DispatchParticleEffect( ROCKET_PACK_LAUNCH_EFFECT, PATTACH_POINT_FOLLOW, pWearable, "charge_RA" );
|
|
}
|
|
#else
|
|
if ( prediction->IsFirstTimePredicted() )
|
|
{
|
|
pOwner->EmitSound( "Weapon_RocketPack.BoostersFire" );
|
|
}
|
|
#endif // CLIENT_DLL
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFRocketPack::ResetTransition( void )
|
|
{
|
|
m_flToggleEndTime = -1.f;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFRocketPack::StartTransition( void )
|
|
{
|
|
m_flToggleEndTime = gpGlobals->curtime + tf_rocketpack_toggle_duration.GetFloat();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
bool CTFRocketPack::IsInTransition( void ) const
|
|
{
|
|
return m_flToggleEndTime >= 0.f;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
bool CTFRocketPack::IsTransitionCompleted( void ) const
|
|
{
|
|
return gpGlobals->curtime >= m_flToggleEndTime;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFRocketPack::WaitToLaunch( void )
|
|
{
|
|
CTFPlayer *pOwner = GetTFPlayerOwner();
|
|
if ( !pOwner )
|
|
return;
|
|
|
|
#ifdef GAME_DLL
|
|
|
|
float flStunDutation = 0.1f;
|
|
|
|
// prevent the owner and passenger from moving for a bit while waiting to launch
|
|
pOwner->m_Shared.StunPlayer( flStunDutation, 1.f, TF_STUN_MOVEMENT, pOwner );
|
|
#endif // GAME_DLL
|
|
}
|
|
|
|
|
|
#ifdef GAME_DLL
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFRocketPack::SetEnabled( bool bEnabled )
|
|
{
|
|
if ( m_bEnabled == bEnabled )
|
|
return;
|
|
|
|
CTFPlayer *pOwner = GetTFPlayerOwner();
|
|
if ( !pOwner )
|
|
return;
|
|
|
|
StartTransition();
|
|
|
|
m_bEnabled = bEnabled;
|
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFRocketPack::PassengerDelayLaunchThink()
|
|
{
|
|
// Get the player owning the weapon.
|
|
CTFPlayer *pOwner = GetTFPlayerOwner();
|
|
if ( !pOwner )
|
|
return;
|
|
|
|
// Are we being healed by any QuickFix medics?
|
|
for ( int i = 0; i < pOwner->m_Shared.GetNumHealers(); i++ )
|
|
{
|
|
CTFPlayer *pMedic = ToTFPlayer( pOwner->m_Shared.GetHealerByIndex( i ) );
|
|
if ( !pMedic )
|
|
continue;
|
|
|
|
CTFWeaponBase *pWeapon = pMedic->GetActiveTFWeapon();
|
|
if ( !pWeapon )
|
|
continue;
|
|
|
|
if ( pWeapon->GetWeaponID() != TF_WEAPON_MEDIGUN )
|
|
continue;
|
|
|
|
// Share blast jump with them
|
|
CWeaponMedigun *pMedigun = assert_cast< CWeaponMedigun* >( pWeapon );
|
|
if ( pMedigun && pMedigun->GetMedigunType() == MEDIGUN_QUICKFIX )
|
|
{
|
|
RocketLaunchPlayer( pMedic, m_vecLaunchDir, true );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
#endif // GAME_DLL
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
void CTFRocketPack::ItemPostFrame( void )
|
|
{
|
|
// Get the player owning the weapon.
|
|
CTFPlayer *pOwner = GetTFPlayerOwner();
|
|
if ( !pOwner )
|
|
return;
|
|
|
|
// Transitioning
|
|
if ( IsInTransition() )
|
|
{
|
|
m_flLaunchTime = 0.f;
|
|
|
|
// Completed
|
|
if ( IsTransitionCompleted() )
|
|
{
|
|
ResetTransition();
|
|
#ifdef CLIENT_DLL
|
|
if ( pOwner == C_TFPlayer::GetLocalTFPlayer() && prediction->IsFirstTimePredicted() )
|
|
{
|
|
pOwner->EmitSound( "Weapon_RocketPack.BoostersReady" );
|
|
}
|
|
#endif // CLIENT_DLL
|
|
}
|
|
else if ( pOwner->m_afButtonPressed & IN_ATTACK2 )
|
|
{
|
|
#ifdef CLIENT_DLL
|
|
if ( pOwner == C_TFPlayer::GetLocalTFPlayer() && prediction->IsFirstTimePredicted() )
|
|
{
|
|
pOwner->EmitSound( "Player.DenyWeaponSelection" );
|
|
}
|
|
#endif // CLIENT_DLL
|
|
}
|
|
|
|
// disabled secondary attack while transitioning
|
|
pOwner->m_nButtons &= ~IN_ATTACK2;
|
|
}
|
|
|
|
// Toggle
|
|
// #ifdef GAME_DLL
|
|
// if ( ( pOwner->m_nButtons & IN_RELOAD ) && !IsInTransition() )
|
|
// {
|
|
// if ( m_bEnabled )
|
|
// {
|
|
// EmitSound( "Weapon_RocketPack.BoostersRetract" );
|
|
// }
|
|
// else
|
|
// {
|
|
// EmitSound( "Weapon_RocketPack.BoostersExtend" );
|
|
// }
|
|
//
|
|
// SetEnabled( !m_bEnabled );
|
|
// }
|
|
// #endif // GAME_DLL
|
|
|
|
if ( m_flInitLaunchTime > 0.f )
|
|
{
|
|
if ( !m_bEnabled || pOwner->m_afButtonPressed & IN_JUMP )
|
|
{
|
|
// rocketpack was disabled while waiting for player, just turn it off
|
|
m_flInitLaunchTime = 0.f;
|
|
m_flNextSecondaryAttack = gpGlobals->curtime + tf_rocketpack_launch_delay.GetFloat();
|
|
pOwner->m_Shared.RemoveCond( TF_COND_PARACHUTE_ACTIVE );
|
|
}
|
|
else
|
|
{
|
|
m_bLaunchedFromGround = ( pOwner->GetFlags() & FL_ONGROUND ) > 0;
|
|
PreLaunch();
|
|
m_flInitLaunchTime = 0.f;
|
|
m_flNextSecondaryAttack = gpGlobals->curtime + tf_rocketpack_refire_delay.GetFloat();
|
|
}
|
|
}
|
|
else if ( m_flLaunchTime > 0.f && m_flLaunchTime <= gpGlobals->curtime )
|
|
{
|
|
Launch();
|
|
}
|
|
else if ( ( pOwner->m_afButtonPressed & IN_ATTACK ) || ( pOwner->m_afButtonPressed & IN_ATTACK2 ) )
|
|
{
|
|
InitiateLaunch();
|
|
}
|
|
else
|
|
{
|
|
WeaponIdle();
|
|
}
|
|
|
|
// while enabled, disabled secondary attack so active weapon cannot use this
|
|
if ( m_bEnabled )
|
|
{
|
|
pOwner->m_nButtons &= ~IN_ATTACK2;
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
const CEconItemView *CTFRocketPack::GetTauntItem() const
|
|
{
|
|
if ( m_bEnabled )
|
|
{
|
|
return BaseClass::GetTauntItem();
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
//-----------------------------------------------------------------------------
|
|
bool CTFRocketPack::Deploy( void )
|
|
{
|
|
CTFPlayer *pOwner = GetTFPlayerOwner();
|
|
if ( pOwner )
|
|
{
|
|
#ifdef CLIENT_DLL
|
|
if ( prediction->IsFirstTimePredicted() )
|
|
#endif
|
|
{
|
|
CPASAttenuationFilter filter( pOwner );
|
|
filter.UsePredictionRules();
|
|
EmitSound( filter, entindex(), "Weapon_RocketPack.BoostersExtend" );
|
|
}
|
|
#ifdef GAME_DLL
|
|
SetEnabled( true );
|
|
#endif
|
|
}
|
|
|
|
return BaseClass::Deploy();
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// -----------------------------------------------------------------------------
|
|
void CTFRocketPack::StartHolsterAnim( void )
|
|
{
|
|
BaseClass::StartHolsterAnim();
|
|
|
|
CTFPlayer *pOwner = GetTFPlayerOwner();
|
|
if ( pOwner )
|
|
{
|
|
#ifdef CLIENT_DLL
|
|
if ( prediction->IsFirstTimePredicted() )
|
|
#endif
|
|
{
|
|
CPASAttenuationFilter filter( pOwner );
|
|
filter.UsePredictionRules();
|
|
EmitSound( filter, entindex(), "Weapon_RocketPack.BoostersRetract" );
|
|
}
|
|
#ifdef GAME_DLL
|
|
SetEnabled( false );
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// -----------------------------------------------------------------------------
|
|
bool CTFRocketPack::CanHolster( void ) const
|
|
{
|
|
if ( m_flLaunchTime > 0.f )
|
|
return false;
|
|
|
|
return BaseClass::CanHolster();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// -----------------------------------------------------------------------------
|
|
void CTFRocketPack::OnResourceMeterFilled()
|
|
{
|
|
#ifdef CLIENT_DLL
|
|
CBasePlayer *pPlayer = GetPlayerOwner();
|
|
if ( pPlayer->IsLocalPlayer() && prediction->IsFirstTimePredicted() )
|
|
{
|
|
pPlayer->EmitSound( "TFPlayer.ReCharged" );
|
|
}
|
|
#endif // CLIENT_DLL
|
|
}
|