Weapon Respawn Fix

From Valve Developer Community
Jump to: navigation, search
English (en)Deutsch (de)русский (ru)
... Icon-Important.png

Introduction

When weapons are not placed correctly by level designers (i.e. when their bounding boxes intersect other entities or world geometry), they will respawn at an incorrect place on the map after being picked up by players. In most cases, the weapon will instead respawn at 0 0 0 on the map, and will continue on in a perpetual loop of falling, waiting, respawning and falling again. Fortunately, the fix for this extremely common bug is very simple.

Note.pngNote:This bug only affects multiplayer mods based on the HL2DM SDK code, singleplayer mods can safely ignore this.

Requirements

  • Using the latest multiplayer OB SDK code

Solution

Open game/shared/hl2mp/weapon_hl2mpbase.h and change this block:

#ifdef GAME_DLL
	DECLARE_DATADESC();
	void Materialize( void );
	virtual	int	ObjectCaps( void );
#endif

such that it becomes:

#ifdef GAME_DLL
	DECLARE_DATADESC();
	void Materialize( void );
	virtual	int	ObjectCaps( void );
	virtual void	FallThink( void );						// make the weapon fall to the ground after spawning
#endif

Now, edit game/shared/hl2mp/weapon_hl2mpbase.cpp and in CWeaponHL2MPBase::FallInit( void ), change:

	SetThink(&CBaseCombatWeapon::FallThink);

to:

	SetThink(&CWeaponHL2MPBase::FallThink);

Add the following block below CWeaponHL2MPBase::FallInit( void ):

#ifdef GAME_DLL
void CWeaponHL2MPBase::FallThink(void)
{
	// Prevent the common HL2DM weapon respawn bug from happening
	// When a weapon is spawned, the following chain of events occurs:
	// - Spawn() is called (duh), which then calls FallInit()
	// - FallInit() is called, and prepares the weapon's 'Think' function (CBaseCombatWeapon::FallThink())
	// - FallThink() is called, and performs several checks before deciding whether the weapon should Materialize()
	// - Materialize() is called (the HL2DM version above), which sets the weapon's respawn location.
	// The problem occurs when a weapon isn't placed properly by a level designer.
	// If the weapon is unable to move from its location (e.g. if its bounding box is halfway inside a wall), Materialize() never gets called.
	// Since Materialize() never gets called, the weapon's respawn location is never set, so if a person picks it up, it respawns forever at
	// 0 0 0 on the map (infinite loop of fall, wait, respawn, not nice at all for performance and bandwidth!)
	if ( HasSpawnFlags( SF_NORESPAWN ) == false )
	{
		if ( GetOriginalSpawnOrigin() == vec3_origin )
		{
			m_vOriginalSpawnOrigin = GetAbsOrigin();
			m_vOriginalSpawnAngles = GetAbsAngles();
		}
	}
	return BaseClass::FallThink();
}
#endif // GAME_DLL

And that's really all there is to it - incorrectly placed weapons should now respawn at their correct locations, instead of some awkward location on the map.