From d1e67cffcef6e728d079bd3b982b18ffd146c778 Mon Sep 17 00:00:00 2001 From: ficool2 <34815548+ficool2@users.noreply.github.com> Date: Sat, 1 Nov 2025 17:00:57 +0000 Subject: [PATCH] Fix spy watch hiding prediction --- src/game/shared/tf/tf_weapon_invis.cpp | 46 ++++++++++++++++++++++---- src/game/shared/tf/tf_weapon_invis.h | 3 ++ 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/src/game/shared/tf/tf_weapon_invis.cpp b/src/game/shared/tf/tf_weapon_invis.cpp index 4663ea7ce..3333739f4 100644 --- a/src/game/shared/tf/tf_weapon_invis.cpp +++ b/src/game/shared/tf/tf_weapon_invis.cpp @@ -28,8 +28,11 @@ IMPLEMENT_NETWORKCLASS_ALIASED( TFWeaponInvis, DT_TFWeaponInvis ) BEGIN_NETWORK_TABLE( CTFWeaponInvis, DT_TFWeaponInvis ) END_NETWORK_TABLE() +#if defined( CLIENT_DLL ) BEGIN_PREDICTION_DATA( CTFWeaponInvis ) + DEFINE_PRED_FIELD( m_flHideTime, FIELD_FLOAT, 0 ) END_PREDICTION_DATA() +#endif LINK_ENTITY_TO_CLASS( tf_weapon_invis, CTFWeaponInvis ); PRECACHE_WEAPON_REGISTER( tf_weapon_invis ); @@ -69,7 +72,20 @@ void CTFWeaponInvis::OnActiveStateChanged( int iOldState ) //----------------------------------------------------------------------------- void CTFWeaponInvis::HideThink( void ) { - SetWeaponVisible( false ); + // This is now done in ItemPostFrame/ItemBusyFrame + // HideThink uses a context think, which is evaluated with predicted clock on client + // but relative to server (not the player's!) clock on the server + // SetWeaponVisible( false ); +} + +//----------------------------------------------------------------------------- +void CTFWeaponInvis::CheckHideTime( void ) +{ + if ( m_flHideTime && m_flHideTime < gpGlobals->curtime ) + { + SetWeaponVisible( false ); + m_flHideTime = 0; + } } //----------------------------------------------------------------------------- @@ -131,11 +147,15 @@ void CTFWeaponInvis::SetWeaponVisible( bool visible ) //----------------------------------------------------------------------------- bool CTFWeaponInvis::Deploy( void ) { - bool b = BaseClass::Deploy(); + bool bDeploy = BaseClass::Deploy(); - SetWeaponIdleTime( gpGlobals->curtime + 1.5 ); + if ( bDeploy ) + { + SetWeaponIdleTime( gpGlobals->curtime + 1.5 ); + m_flHideTime = 0; + } - return b; + return bDeploy; } //----------------------------------------------------------------------------- @@ -143,8 +163,12 @@ bool CTFWeaponInvis::Holster( CBaseCombatWeapon *pSwitchingTo ) { bool bHolster = BaseClass::Holster( pSwitchingTo ); - // far in the future - SetWeaponIdleTime( gpGlobals->curtime + 10 ); + if ( bHolster ) + { + // far in the future + SetWeaponIdleTime( gpGlobals->curtime + 10 ); + m_flHideTime = gpGlobals->curtime + SequenceDuration(); + } return bHolster; } @@ -161,10 +185,18 @@ void CTFWeaponInvis::SecondaryAttack( void ) // do nothing } +//----------------------------------------------------------------------------- +void CTFWeaponInvis::ItemPostFrame( void ) +{ + CheckHideTime(); + BaseClass::ItemPostFrame(); +} + //----------------------------------------------------------------------------- void CTFWeaponInvis::ItemBusyFrame( void ) { - // do nothing + CheckHideTime(); + // intentionally don't call base } //----------------------------------------------------------------------------- diff --git a/src/game/shared/tf/tf_weapon_invis.h b/src/game/shared/tf/tf_weapon_invis.h index 3791aafb6..23468ebe5 100644 --- a/src/game/shared/tf/tf_weapon_invis.h +++ b/src/game/shared/tf/tf_weapon_invis.h @@ -46,6 +46,7 @@ public: virtual bool Deploy( void ); virtual void HideThink( void ); + void CheckHideTime(); virtual bool Holster( CBaseCombatWeapon *pSwitchingTo ); virtual int GetWeaponID( void ) const { return TF_WEAPON_INVIS; } @@ -59,6 +60,7 @@ public: virtual void SetWeaponVisible( bool visible ); + virtual void ItemPostFrame( void ); virtual void ItemBusyFrame( void ); int GetInvisType( void ) { int iMode = 0; CALL_ATTRIB_HOOK_INT( iMode, set_weapon_mode ); return iMode; }; @@ -81,6 +83,7 @@ public: #endif private: + float m_flHideTime; CTFWeaponInvis( const CTFWeaponInvis & ) {} };