Full Holster Sequence (HL2MP)

From Valve Developer Community
Revision as of 14:14, 15 July 2006 by Ts2do (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Overview

This tutorial provides insight on giving an active weapon time to play its holster animation before showing a newly chosen weapon.

c_basecombatcharacter.h & basecombatcharacter.h

Add the following to the combat character class:

friend class CShowWeapon;

basecombatweapon_shared.cpp

Add the following system to this file to act as the timer for triggering the weapon deploy.

#ifdef CLIENT_DLL
#define CShowWeapon C_ShowWeapon
#endif
class CShowWeapon : public CAutoGameSystem
{
public:
	bool Init()
	{
		ClearShowWeapon();
		return true;
	}
	void FrameUpdatePreEntityThink()
	{
		if(m_pWeapon&&m_flTime<gpGlobals->curtime)
		{
			ShowWeapon();
		}
	}
	void Update(float frametime)
	{
		FrameUpdatePreEntityThink(); // This adds compatibility to this gamesystem on the client
	}
	void SetShowWeapon(CBaseCombatWeapon *pWeapon, int iActivity, float delta)
	{
		m_pWeapon = pWeapon;
		m_iActivity = iActivity;
		if(delta==0)
		{
			ShowWeapon();
		}
		else
		{
			m_flTime = gpGlobals->curtime + delta;
		}
	}
	void ClearShowWeapon()
	{
		m_pWeapon = NULL;
	}
private:
	void ShowWeapon()
	{
		Assert(m_pWeapon);
		m_pWeapon->SetWeaponVisible(true);
		if(m_pWeapon->GetOwner())
		{
			CBaseCombatWeapon *pLastWeapon = m_pWeapon->GetOwner()->GetActiveWeapon();
			m_pWeapon->GetOwner()->m_hActiveWeapon = m_pWeapon;
			CBasePlayer *pOwner = ToBasePlayer( m_pWeapon->GetOwner() );
			if ( pOwner )
			{
				m_pWeapon->SetViewModel();
				m_pWeapon->SendWeaponAnim( m_iActivity );

				pOwner->SetNextAttack( gpGlobals->curtime + m_pWeapon->SequenceDuration() );
				
				if ( pLastWeapon && pOwner->Weapon_ShouldSetLast( pLastWeapon, m_pWeapon ) )
				{
					pOwner->Weapon_SetLast( pLastWeapon->GetLastWeapon() );
				}

				CBaseViewModel *pViewModel = pOwner->GetViewModel();
				Assert( pViewModel );
				if ( pViewModel )
					pViewModel->RemoveEffects( EF_NODRAW );
				pOwner->ResetAutoaim( );
				m_pWeapon->SetupSkin(pViewModel,pOwner);
			}
		}

		// Can't shoot again until we've finished deploying
		m_pWeapon->m_flNextSecondaryAttack = m_pWeapon->m_flNextPrimaryAttack	= gpGlobals->curtime + m_pWeapon->SequenceDuration();

		ClearShowWeapon();
	}
	CBaseCombatWeapon *m_pWeapon;
	int m_iActivity;
	float m_flTime;
};
static CShowWeapon g_ShowWeapon;

Modify DefaultDeploy so it utilizes the new system:

bool CBaseCombatWeapon::DefaultDeploy( char *szViewModel, char *szWeaponModel, int iActivity, char *szAnimExt )
{
	// Msg( "deploy %s at %f\n", GetClassname(), gpGlobals->curtime );

	// Weapons that don't autoswitch away when they run out of ammo 
	// can still be deployed when they have no ammo.
	if ( !HasAnyAmmo() && AllowsAutoSwitchFrom() )
		return false;

	float flSequenceDuration = 0.0f;
	if(GetOwner())
	{
		if ( !GetOwner()->IsAlive() )
			return false;
		CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
		if ( pOwner )
		{
			pOwner->SetAnimationExtension( szAnimExt );
		}
		CBaseCombatWeapon *pActive = GetOwner()->GetActiveWeapon();
		if ( pActive && pActive->GetActivity() == ACT_VM_HOLSTER )
		{
			flSequenceDuration = pActive->SequenceDuration();
		}
	}
	g_ShowWeapon.SetShowWeapon( this, iActivity, flSequenceDuration );

#ifndef CLIENT_DLL
	// Cancel any pending hide events
	g_EventQueue.CancelEventOn( this, "HideWeapon" );
#endif

	return true;
}