ValveSoftware / halflife

Half-Life 1 engine based games
Other
3.67k stars 621 forks source link

[TFC] Grenades being removed when throwing flag #3273

Open 12souza opened 2 years ago

12souza commented 2 years ago

Grenades are disappearing from a player priming a grenade when they throw the flag when either grenade ammo amounts are at 0

azul1337 commented 2 years ago

There's a block inside RemoveResults(CBaseEntity* Goal, CBasePlayer* pPlayer) that is effectively the following:

if ( ( pPlayer->tfstate & TFSTATE_GRENPRIMED ) && ( pPlayer->no_grenades_1 <= 0 || pPlayer->no_grenades_2 <= 0 ) )
{
   pPlayer->tfstate &= ~TFSTATE_GRENPRIMED;
   pPlayer->tfstate &= ~TFSTATE_GRENTHROWING;
   pPlayer->bRemoveGrenade = 1;
}

Based on the rest of the reversed code: the apparent intention of this was to remove a primed grenade from the player if that grenade's stock had been granted by the goalitem (undoing Apply_Results(...)), as, with the goalitem removed, the player should no longer have such a grenade. This has the unintended side effect of removing a currently primed grenade from the player upon goalitem removal in all instances where at least one of the player's grenade stocks is 0.

For example: A player is carrying the flag on 2fort. The player has 2 primary grenades and 1 secondary grenade and then proceeds to prime a secondary grenade, pPlayer->no_grenades_2 will drop to 0 upon priming. If the player then tosses the flag while the grenade is still primed it will be flagged for removal by RemoveResults and the primed grenade will cease to exist after evaluating the next frame.

Even worse: If the player has 0 primary grenades and 3 secondary grenades in the same situation, primes a secondary grenade and tosses the flag... it will be removed because pPlayer->no_grenades_1 == 0. This process can then be repeated for their remaining two secondary grenades.

A proper solution probably involves checking the appropriate pPlayer->no_grenade_# vs the class of the primed grenade but there exists a brief window in which the grenade has a generic class before it's assigned it's "true" class as briefly mentioned in: #2343, so... I'm uncertain.

At the very least it feels like this problematic block should be elided if Goal->no_grenades_1 == 0 && Goal->no_grenades_2 == 0 as what seems to be the intended purpose of the block doesn't apply to the situation.

Nomad7 commented 10 months ago

Any chance of issues like this being addressed at some point, now that the 25th anniversary update is out?

se7entfc commented 2 weeks ago

I have added a fix to the TFC Bug Fixes plugin for AMXX while this is fixed by Valve:

https://forums.alliedmods.net/showthread.php?t=333746