fix [tf2]: Prevent wearables from leaking when weapon is dropped

This commit is contained in:
Sean McGeehan
2026-05-23 18:44:28 -04:00
committed by EricS-Valve
parent 50d5de34e2
commit 326c5e2177
2 changed files with 34 additions and 1 deletions
+18 -1
View File
@@ -8524,8 +8524,25 @@ void CTFPlayerShared::DetermineDisguiseWeapon( bool bForcePrimary )
m_hDisguiseWeapon->m_iState = WEAPON_IS_ACTIVE;
m_hDisguiseWeapon->m_bDisguiseWeapon = true;
m_hDisguiseWeapon->SetContextThink( &CTFWeaponBase::DisguiseWeaponThink, gpGlobals->curtime + 0.5, "DisguiseWeaponThink" );
m_hDisguiseWeapon->RemoveExtraWearables();
m_hDisguiseWeapon->UpdateExtraWearables();
// Cap accumulated disguise wearables. Each disguise-weapon swap
// intentionally orphans the prior weapon's world extras (so banners
// etc. stay visible across swaps); skip recreation once we're at
// the cap so they can't grow unbounded under rapid cycling.
// fully cleaned up after disguise removal.
const int kMaxDisguiseWearables = 5;
int nDisguiseWearableCount = 0;
for ( int i = 0; i < m_pOuter->GetNumWearables(); ++i )
{
CTFWearable *pWearable = dynamic_cast< CTFWearable * >( m_pOuter->GetWearable( i ) );
if ( pWearable && pWearable->IsDisguiseWearable() )
nDisguiseWearableCount++;
}
if ( nDisguiseWearableCount < kMaxDisguiseWearables )
{
m_hDisguiseWeapon->UpdateExtraWearables();
}
// Ammo/clip state is displayed to attached medics
m_iDisguiseAmmo = 0;
+16
View File
@@ -1118,6 +1118,22 @@ void CTFWeaponBase::Drop( const Vector &vecVelocity )
}
#endif
#ifndef CLIENT_DLL
// For disguise weapons specifically, the viewmodel-only extra wearable
// (e.g. botkiller medigun head) must be removed before BaseClass::Drop
// clears OwnerEntity — otherwise on disguise-weapon swap it orphans on
// the spy's viewmodel and accumulates one per swap. The world-model
// extra (e.g. soldier banner) is intentionally NOT removed here so
// it remains visible across disguise-weapon swaps within the same
// disguise; We cap Wearables during assingment
// RemoveDisguiseWearables sweeps it up at full disguise removal which prevents the leak.
if ( m_bDisguiseWeapon && m_hExtraWearableViewModel )
{
m_hExtraWearableViewModel->RemoveFrom( GetOwnerEntity() );
m_hExtraWearableViewModel = NULL;
}
#endif
BaseClass::Drop( vecVelocity );
ReapplyProvision();