diff --git a/src/game/server/tf/tf_player.cpp b/src/game/server/tf/tf_player.cpp index 940b946ad..0e373ed9b 100644 --- a/src/game/server/tf/tf_player.cpp +++ b/src/game/server/tf/tf_player.cpp @@ -126,7 +126,6 @@ #include "tf_revive.h" #include "tf_logic_halloween_2014.h" #include "tf_logic_player_destruction.h" -#include "tf_weapon_rocketpack.h" #include "tf_weapon_slap.h" #include "func_croc.h" #include "tf_weapon_bonesaw.h" @@ -1453,35 +1452,6 @@ void CTFPlayer::TFPlayerThink() else { m_iLeftGroundHealth = -1; - if ( GetFlags() & FL_ONGROUND ) - { - // Airborne conditions end on ground contact - m_Shared.RemoveCond( TF_COND_KNOCKED_INTO_AIR ); - m_Shared.RemoveCond( TF_COND_AIR_CURRENT ); - - if ( m_Shared.InCond( TF_COND_ROCKETPACK ) ) - { - // Make sure we're still not dealing with launch, where it's possible - // to hit your head and fall to the ground before the second stage. - CTFWeaponBase *pRocketPack = Weapon_OwnsThisID( TF_WEAPON_ROCKETPACK ); - if ( pRocketPack ) - { - if ( gpGlobals->curtime > ( static_cast< CTFRocketPack* >( pRocketPack )->GetRefireTime() ) ) - { - EmitSound( "Weapon_RocketPack.BoostersShutdown" ); - EmitSound( "Weapon_RocketPack.Land" ); - m_Shared.RemoveCond( TF_COND_ROCKETPACK ); - - IGameEvent *pEvent = gameeventmanager->CreateEvent( "rocketpack_landed" ); - if ( pEvent ) - { - pEvent->SetInt( "userid", GetUserID() ); - gameeventmanager->FireEvent( pEvent ); - } - } - } - } - } if ( m_iBlastJumpState ) { diff --git a/src/game/shared/tf/tf_player_shared.cpp b/src/game/shared/tf/tf_player_shared.cpp index a2db00580..84eeee03f 100644 --- a/src/game/shared/tf/tf_player_shared.cpp +++ b/src/game/shared/tf/tf_player_shared.cpp @@ -31,6 +31,7 @@ #include "tf_mapinfo.h" #include "tf_dropped_weapon.h" #include "tf_weapon_passtime_gun.h" +#include "tf_weapon_rocketpack.h" #include // Client specific. @@ -471,7 +472,10 @@ BEGIN_PREDICTION_DATA_NO_BASE( CTFPlayerShared ) DEFINE_PRED_FIELD( m_bHasPasstimeBall, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), DEFINE_PRED_FIELD( m_bIsTargetedForPasstimePass, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE ), // does this belong here? DEFINE_PRED_FIELD( m_askForBallTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), + DEFINE_PRED_FIELD( m_flHolsterAnimTime, FIELD_FLOAT, FTYPEDESC_INSENDTABLE ), DEFINE_PRED_ARRAY( m_flItemChargeMeter, FIELD_FLOAT, LAST_LOADOUT_SLOT_WITH_CHARGE_METER, FTYPEDESC_INSENDTABLE ), + DEFINE_PRED_FIELD( m_iStunIndex, FIELD_INTEGER, FTYPEDESC_INSENDTABLE ), + DEFINE_PRED_FIELD( m_bScattergunJump, FIELD_BOOLEAN, 0 ), END_PREDICTION_DATA() // Server specific. @@ -1005,7 +1009,6 @@ void CTFPlayerShared::Spawn( void ) SetRevengeCrits( 0 ); m_PlayerStuns.RemoveAll(); - m_iStunIndex = -1; m_iPasstimeThrowAnimState = PASSTIME_THROW_ANIM_NONE; m_bHasPasstimeBall = false; @@ -1014,6 +1017,7 @@ void CTFPlayerShared::Spawn( void ) #else m_bSyncingConditions = false; #endif + m_iStunIndex = -1; m_bKingRuneBuffActive = false; // Reset our assist here incase something happens before we get killed @@ -3090,9 +3094,48 @@ void CTFPlayerShared::ConditionThink( void ) VehicleThink(); - if ( m_pOuter->GetFlags() & FL_ONGROUND && InCond( TF_COND_PARACHUTE_ACTIVE ) ) + if ( m_pOuter->GetFlags() & FL_ONGROUND ) { - RemoveCond( TF_COND_PARACHUTE_ACTIVE ); + // Airborne conditions end on ground contact + RemoveCond( TF_COND_KNOCKED_INTO_AIR ); + RemoveCond( TF_COND_AIR_CURRENT ); + + if ( InCond( TF_COND_PARACHUTE_ACTIVE ) ) + { + RemoveCond( TF_COND_PARACHUTE_ACTIVE ); + } + + if ( InCond( TF_COND_ROCKETPACK ) ) + { + // Make sure we're still not dealing with launch, where it's possible + // to hit your head and fall to the ground before the second stage. + CTFWeaponBase *pRocketPack = m_pOuter->Weapon_OwnsThisID( TF_WEAPON_ROCKETPACK ); + if ( pRocketPack ) + { + if ( gpGlobals->curtime > ( static_cast< CTFRocketPack* >( pRocketPack )->GetRefireTime() ) ) + { +#ifdef CLIENT_DLL + if ( prediction->IsFirstTimePredicted() ) +#endif + { + CPASAttenuationFilter filter( m_pOuter ); + filter.UsePredictionRules(); + m_pOuter->EmitSound( filter, m_pOuter->entindex(), "Weapon_RocketPack.BoostersShutdown" ); + m_pOuter->EmitSound( filter, m_pOuter->entindex(), "Weapon_RocketPack.Land" ); + } + RemoveCond( TF_COND_ROCKETPACK ); + +#ifdef GAME_DLL + IGameEvent *pEvent = gameeventmanager->CreateEvent( "rocketpack_landed" ); + if ( pEvent ) + { + pEvent->SetInt( "userid", m_pOuter->GetUserID() ); + gameeventmanager->FireEvent( pEvent ); + } +#endif + } + } + } } // See if we should be pulsing our radius heal @@ -7301,6 +7344,8 @@ void CTFPlayerShared::OnRemoveStunned( void ) m_iStunFlags = 0; m_hStunner = NULL; + m_iStunIndex = -1; + #ifdef CLIENT_DLL if ( m_pOuter->m_pStunnedEffect ) { @@ -7310,7 +7355,6 @@ void CTFPlayerShared::OnRemoveStunned( void ) m_pOuter->m_pStunnedEffect = NULL; } #else - m_iStunIndex = -1; m_PlayerStuns.RemoveAll(); #endif @@ -9624,15 +9668,16 @@ bool CTFPlayerShared::AddToSpyCloakMeter( float val, bool bForce ) #endif -#ifdef GAME_DLL //----------------------------------------------------------------------------- // Purpose: Stun & Snare Application //----------------------------------------------------------------------------- void CTFPlayerShared::StunPlayer( float flTime, float flReductionAmount, int iStunFlags, CTFPlayer* pAttacker ) { +#ifdef GAME_DLL // Insanity prevention if ( ( m_PlayerStuns.Count() + 1 ) >= 250 ) return; +#endif if ( InCond( TF_COND_PHASE ) || InCond( TF_COND_PASSTIME_INTERCEPTION ) ) return; @@ -9643,11 +9688,13 @@ void CTFPlayerShared::StunPlayer( float flTime, float flReductionAmount, int iSt if ( InCond( TF_COND_INVULNERABLE_HIDE_UNLESS_DAMAGED ) && !InCond( TF_COND_MVM_BOT_STUN_RADIOWAVE ) ) return; +#ifdef GAME_DLL if ( pAttacker && TFGameRules() && TFGameRules()->IsTruceActive() && pAttacker->IsTruceValidForEnt() ) { if ( ( pAttacker->GetTeamNumber() == TF_TEAM_RED ) || ( pAttacker->GetTeamNumber() == TF_TEAM_BLUE ) ) return; } +#endif float flRemapAmount = RemapValClamped( flReductionAmount, 0.0, 1.0, 0, 255 ); @@ -9674,10 +9721,13 @@ void CTFPlayerShared::StunPlayer( float flTime, float flReductionAmount, int iSt } else if ( GetActiveStunInfo() ) { +#ifdef GAME_DLL // Something yanked our TF_COND_STUNNED in an unexpected way if ( !HushAsserts() ) Assert( !"Something yanked out TF_COND_STUNNED." ); m_PlayerStuns.RemoveAll(); +#endif + m_iStunIndex = -1; return; } @@ -9699,7 +9749,16 @@ void CTFPlayerShared::StunPlayer( float flTime, float flReductionAmount, int iSt // This can happen when stuns use TF_STUN_CONTROLS or TF_STUN_LOSER_STATE. float flOldStun = GetActiveStunInfo() ? GetActiveStunInfo()->flStunAmount : 0.f; +#ifdef GAME_DLL m_iStunIndex = m_PlayerStuns.AddToTail( stunEvent ); +#else + m_iStunIndex = 0; + + if ( prediction->IsFirstTimePredicted() ) + { + m_ActiveStunInfo = stunEvent; + } +#endif if ( flOldStun > flRemapAmount ) { @@ -9709,10 +9768,18 @@ void CTFPlayerShared::StunPlayer( float flTime, float flReductionAmount, int iSt else { // Done for now +#ifdef GAME_DLL m_PlayerStuns.AddToTail( stunEvent ); +#else + if ( prediction->IsFirstTimePredicted() ) + { + m_ActiveStunInfo = stunEvent; + } +#endif return; } +#ifdef GAME_DLL // Add in extra time when TF_STUN_CONTROLS if ( GetActiveStunInfo()->iStunFlags & TF_STUN_CONTROLS ) { @@ -9766,10 +9833,10 @@ void CTFPlayerShared::StunPlayer( float flTime, float flReductionAmount, int iSt m_pOuter->ClearExpression(); m_pOuter->ClearWeaponFireScene(); } +#endif AddCond( TF_COND_STUNNED, -1.f, pAttacker ); } -#endif // GAME_DLL //----------------------------------------------------------------------------- // Purpose: Returns the intensity of the current stun effect, if we have the type of stun indicated. diff --git a/src/game/shared/tf/tf_player_shared.h b/src/game/shared/tf/tf_player_shared.h index a4cbfca1f..06acecfc6 100644 --- a/src/game/shared/tf/tf_player_shared.h +++ b/src/game/shared/tf/tf_player_shared.h @@ -560,9 +560,7 @@ public: // Stuns stun_struct_t *GetActiveStunInfo( void ) const; -#ifdef GAME_DLL void StunPlayer( float flTime, float flReductionAmount, int iStunFlags = TF_STUN_MOVEMENT, CTFPlayer* pAttacker = NULL ); -#endif // GAME_DLL float GetAmountStunned( int iStunFlags ); bool IsLoserStateStunned( void ) const; bool IsControlStunned( void ); diff --git a/src/game/shared/tf/tf_weapon_rocketpack.cpp b/src/game/shared/tf/tf_weapon_rocketpack.cpp index b3202a37f..38d5bbcef 100644 --- a/src/game/shared/tf/tf_weapon_rocketpack.cpp +++ b/src/game/shared/tf/tf_weapon_rocketpack.cpp @@ -13,6 +13,7 @@ #ifdef CLIENT_DLL #include "c_tf_player.h" #include "c_rope.h" +#include "prediction.h" // Server specific. #else #include "tf_player.h" @@ -47,7 +48,10 @@ 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 @@ -211,10 +215,13 @@ bool CTFRocketPack::InitiateLaunch( void ) CTFPlayer *pOwner = GetTFPlayerOwner(); if ( !pOwner->m_Shared.IsRocketPackReady() ) { -#ifdef GAME_DLL - CPVSFilter filter( WorldSpaceCenter() ); - pOwner->EmitSound( filter, entindex(), "Weapon_RocketPack.BoostersNotReady" ); -#endif // GAME_DLL + // note: this is never reached +#ifdef CLIENT_DLL + if ( prediction->IsFirstTimePredicted() ) + { + pOwner->EmitSound( "Weapon_RocketPack.BoostersNotReady" ); + } +#endif return false; } @@ -224,16 +231,18 @@ bool CTFRocketPack::InitiateLaunch( void ) return false; } -#ifdef GAME_DLL - if ( pOwner->m_Shared.IsLoser() ) +#ifdef CLIENT_DLL + if ( prediction->IsFirstTimePredicted() ) +#endif { - pOwner->EmitSound( "Weapon_RocketPack.BoostersNotReady" ); + CPASAttenuationFilter filter( pOwner ); + filter.UsePredictionRules(); + pOwner->EmitSound( + filter, + entindex(), + pOwner->m_Shared.IsLoser() ? "Weapon_RocketPack.BoostersNotReady" : "Weapon_RocketPack.BoostersCharge" + ); } - else - { - pOwner->EmitSound( "Weapon_RocketPack.BoostersCharge" ); - } -#endif // GAME_DLL m_flInitLaunchTime = gpGlobals->curtime; @@ -369,7 +378,6 @@ bool CTFRocketPack::ShouldDraw() #endif // CLIENT_DLL -#ifdef GAME_DLL //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- @@ -384,7 +392,7 @@ Vector CTFRocketPack::CalcRocketForceFromPlayer( CTFPlayer *pPlayer ) const float flVertPushScale = ( bOnGround ) ? 0.7f : 0.25f; // Less vertical force while airborne Vector vecForward, vecRight; - QAngle angAim = ( bOnGround ) ? pPlayer->GetAbsAngles() : pPlayer->EyeAngles(); + QAngle angAim = pPlayer->EyeAngles(); AngleVectors( angAim, &vecForward, &vecRight, NULL ); bool bNone = !( pPlayer->m_nButtons & IN_FORWARD ) && !( pPlayer->m_nButtons & IN_BACK ) /* && @@ -468,7 +476,6 @@ void CTFRocketPack::RocketLaunchPlayer( CTFPlayer *pPlayer, const Vector& vecFor pPlayer->ApplyAbsVelocityImpulse( vecForce ); } -#endif // GAME_DLL //----------------------------------------------------------------------------- // Purpose: @@ -482,7 +489,6 @@ bool CTFRocketPack::PreLaunch( void ) pOwner->DoAnimationEvent( PLAYERANIMEVENT_CUSTOM, ACT_MP_ATTACK_STAND_PRIMARYFIRE ); SendWeaponAnim( ACT_VM_PRIMARYATTACK ); -#ifdef GAME_DLL // Negate any fall Vector vecVel = pOwner->GetAbsVelocity(); if ( vecVel.z < 0.f ) @@ -496,14 +502,15 @@ bool CTFRocketPack::PreLaunch( void ) 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(); -#endif // GAME_DLL return true; } @@ -519,16 +526,19 @@ bool CTFRocketPack::Launch( void ) pOwner->StopSound( "Weapon_LooseCannon.Charge" ); -#ifdef GAME_DLL 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; @@ -536,6 +546,7 @@ bool CTFRocketPack::Launch( void ) 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; @@ -594,6 +605,7 @@ bool CTFRocketPack::Launch( void ) } CPASAttenuationFilter filter( pOwner ); + filter.UsePredictionRules(); pOwner->EmitSound( filter, pOwner->entindex(), "Weapon_RocketPack.BoostersFire" ); IGameEvent *pEvent = gameeventmanager->CreateEvent( "rocketpack_launch" ); @@ -610,7 +622,12 @@ bool CTFRocketPack::Launch( void ) DispatchParticleEffect( ROCKET_PACK_LAUNCH_EFFECT, PATTACH_POINT_FOLLOW, pWearable, "charge_LA" ); DispatchParticleEffect( ROCKET_PACK_LAUNCH_EFFECT, PATTACH_POINT_FOLLOW, pWearable, "charge_RA" ); } -#endif // GAME_DLL +#else + if ( prediction->IsFirstTimePredicted() ) + { + pOwner->EmitSound( "Weapon_RocketPack.BoostersFire" ); + } +#endif // CLIENT_DLL return true; } @@ -748,7 +765,7 @@ void CTFRocketPack::ItemPostFrame( void ) { ResetTransition(); #ifdef CLIENT_DLL - if ( pOwner == C_TFPlayer::GetLocalTFPlayer() ) + if ( pOwner == C_TFPlayer::GetLocalTFPlayer() && prediction->IsFirstTimePredicted() ) { pOwner->EmitSound( "Weapon_RocketPack.BoostersReady" ); } @@ -757,7 +774,7 @@ void CTFRocketPack::ItemPostFrame( void ) else if ( pOwner->m_afButtonPressed & IN_ATTACK2 ) { #ifdef CLIENT_DLL - if ( pOwner == C_TFPlayer::GetLocalTFPlayer() ) + if ( pOwner == C_TFPlayer::GetLocalTFPlayer() && prediction->IsFirstTimePredicted() ) { pOwner->EmitSound( "Player.DenyWeaponSelection" ); } @@ -841,14 +858,21 @@ const CEconItemView *CTFRocketPack::GetTauntItem() const //----------------------------------------------------------------------------- bool CTFRocketPack::Deploy( void ) { -#ifdef GAME_DLL CTFPlayer *pOwner = GetTFPlayerOwner(); if ( pOwner ) { - EmitSound( "Weapon_RocketPack.BoostersExtend" ); +#ifdef CLIENT_DLL + if ( prediction->IsFirstTimePredicted() ) +#endif + { + CPASAttenuationFilter filter( pOwner ); + filter.UsePredictionRules(); + EmitSound( filter, entindex(), "Weapon_RocketPack.BoostersExtend" ); + } +#ifdef GAME_DLL SetEnabled( true ); +#endif } -#endif // GAME_DLL return BaseClass::Deploy(); } @@ -861,14 +885,21 @@ void CTFRocketPack::StartHolsterAnim( void ) { BaseClass::StartHolsterAnim(); -#ifdef GAME_DLL CTFPlayer *pOwner = GetTFPlayerOwner(); if ( pOwner ) { - EmitSound( "Weapon_RocketPack.BoostersRetract" ); +#ifdef CLIENT_DLL + if ( prediction->IsFirstTimePredicted() ) +#endif + { + CPASAttenuationFilter filter( pOwner ); + filter.UsePredictionRules(); + EmitSound( filter, entindex(), "Weapon_RocketPack.BoostersRetract" ); + } +#ifdef GAME_DLL SetEnabled( false ); +#endif } -#endif // GAME_DLL } @@ -890,7 +921,7 @@ void CTFRocketPack::OnResourceMeterFilled() { #ifdef CLIENT_DLL CBasePlayer *pPlayer = GetPlayerOwner(); - if ( pPlayer->IsLocalPlayer() ) + if ( pPlayer->IsLocalPlayer() && prediction->IsFirstTimePredicted() ) { pPlayer->EmitSound( "TFPlayer.ReCharged" ); } diff --git a/src/game/shared/tf/tf_weapon_rocketpack.h b/src/game/shared/tf/tf_weapon_rocketpack.h index 9c1e6ec3d..f2de5574c 100644 --- a/src/game/shared/tf/tf_weapon_rocketpack.h +++ b/src/game/shared/tf/tf_weapon_rocketpack.h @@ -71,14 +71,14 @@ private: bool IsTransitionCompleted( void ) const; void WaitToLaunch( void ); + void RocketLaunchPlayer( CTFPlayer *pPlayer, const Vector& vecForce, bool bIsPassenger ); + Vector CalcRocketForceFromPlayer( CTFPlayer *pPlayer ); #ifdef GAME_DLL void SetEnabled( bool bEnabled ); void PassengerDelayLaunchThink( void ); - void RocketLaunchPlayer( CTFPlayer *pPlayer, const Vector& vecForce, bool bIsPassenger ); - Vector CalcRocketForceFromPlayer( CTFPlayer *pPlayer ); #else void CleanupParticles( void ); -#endif // GAME_DLL +#endif // CLIENT_DLL CNetworkVar( float, m_flInitLaunchTime ); CNetworkVar( float, m_flLaunchTime );