Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RPG sometimes gets stuck unable to reload #3264

Open
SamVanheer opened this issue Mar 26, 2022 · 0 comments
Open

RPG sometimes gets stuck unable to reload #3264

SamVanheer opened this issue Mar 26, 2022 · 0 comments

Comments

@SamVanheer
Copy link

SamVanheer commented Mar 26, 2022

When firing an RPG with laser dot turned on and the rocket flies into any kind of water (on old maps skies are non-solid and behave like water), if the rocket exits the water and has a speed below 1500 units/sec the rocket will detonate without informing the launcher about it. The launcher won't let you reload if the laser is turned on and any rockets are active, so this stops you from reloading.

This can be easily tested by loading the map c2a5, jumping into the water and swimming to the bottom and then firing a rocket straight up.

This video shows the bug:
https://www.youtube.com/watch?v=-AUqwI1P-Oc

Active rocket check here:

halflife/dlls/rpg.cpp

Lines 310 to 315 in c7240b9

if ( m_cActiveRockets && m_fSpotActive )
{
// no reloading when there are active missiles tracking the designator.
// ward off future autoreload attempts by setting next attack time into the future for a bit.
return;
}

Rocket informs the launcher here, if it detonates on touch:

halflife/dlls/rpg.cpp

Lines 155 to 159 in c7240b9

if ( m_pLauncher )
{
// my launcher is still around, tell it I'm dead.
m_pLauncher->m_cActiveRockets--;
}

Rocket slows down to 300 units/sec here when fully underwater:

halflife/dlls/rpg.cpp

Lines 247 to 255 in c7240b9

if (pev->waterlevel == 3)
{
// go slow underwater
if (pev->velocity.Length() > 300)
{
pev->velocity = pev->velocity.Normalize() * 300;
}
UTIL_BubbleTrail( pev->origin - pev->velocity * 0.1, pev->origin, 4 );
}

Rocket detonates without informing the launcher if going slower than 1500 units/sec while not touching underwater here:

halflife/dlls/rpg.cpp

Lines 272 to 275 in c7240b9

if (pev->waterlevel == 0 && pev->velocity.Length() < 1500)
{
Detonate( );
}

To fix this, when the rocket is detonated it needs to inform the launcher:
Move this code:

halflife/dlls/rpg.cpp

Lines 155 to 159 in c7240b9

if ( m_pLauncher )
{
// my launcher is still around, tell it I'm dead.
m_pLauncher->m_cActiveRockets--;
}

To its own method:

//In class declaration
void UpdateLauncher();

//In rpg.cpp
void CRpgRocket::UpdateLauncher()
{
	if ( m_pLauncher != nullptr )
	{
		// my launcher is still around, tell it I'm dead.
		m_pLauncher->m_cActiveRockets--;
	}
}

//=========================================================
//=========================================================
void CRpgRocket :: RocketTouch ( CBaseEntity *pOther )
{
	UpdateLauncher();

	STOP_SOUND( edict(), CHAN_VOICE, "weapons/rocket1.wav" );
	ExplodeTouch( pOther );
}

Change this:

halflife/dlls/rpg.cpp

Lines 273 to 275 in c7240b9

{
Detonate( );
}

To this:

{
	UpdateLauncher();
	Detonate( );
}

An even better solution would be to update the launcher in the rocket's destructor, but entity destructors aren't called in SDK code so for the purposes of this fix i've limited it to using available solutions.

Note also that doing this in the destructor can cause crashes if the rocket is in flight when a map change or disconnect occurs due to #1719. Changing the launcher pointer to an EHANDLE will still cause edge cases due to #1755, which is why i've changed the code above to compare against nullptr which forces a proper null check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants