//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
//=============================================================================//

#include "cbase.h" 
#include "fx_dod_shared.h"
#include "weapon_dodbipodgun.h"
#include "dod_gamerules.h"
#include "engine/IEngineSound.h"

#ifndef CLIENT_DLL
#include "ndebugoverlay.h"
#endif

IMPLEMENT_NETWORKCLASS_ALIASED( DODBipodWeapon, DT_BipodWeapon )

BEGIN_NETWORK_TABLE( CDODBipodWeapon, DT_BipodWeapon )
#ifdef CLIENT_DLL
	RecvPropBool( RECVINFO( m_bDeployed ) ),
	RecvPropInt( RECVINFO( m_iDeployedReloadModelIndex) ),
#else
	SendPropBool( SENDINFO( m_bDeployed ) ),
	SendPropModelIndex( SENDINFO(m_iDeployedReloadModelIndex) ),
#endif
END_NETWORK_TABLE()

#ifdef CLIENT_DLL
BEGIN_PREDICTION_DATA( CDODBipodWeapon )
	DEFINE_PRED_FIELD( m_bDeployed, FIELD_BOOLEAN, FTYPEDESC_INSENDTABLE )
END_PREDICTION_DATA()
#endif

CDODBipodWeapon::CDODBipodWeapon()
{
}

void CDODBipodWeapon::Spawn()
{
	SetDeployed( false );
	m_flNextDeployCheckTime = 0;

	m_iCurrentWorldModel = 0;

	m_iAltFireHint = HINT_USE_DEPLOY;

	BaseClass::Spawn();
}

void CDODBipodWeapon::SetDeployed( bool bDeployed )
{
	if ( bDeployed == false )
	{
		m_hDeployedOnEnt = NULL;
		m_DeployedEntOrigin = vec3_origin;
		m_flDeployedHeight = 0;

#ifdef GAME_DLL
		CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );
		if ( pPlayer )
		{
			pPlayer->HandleDeployedMGKillCount( 0 );	// reset when we undeploy
		}
#endif
	}

	m_bDeployed = bDeployed;
}

void CDODBipodWeapon::Precache( void )
{
	// precache base first, it loads weapon scripts
	BaseClass::Precache();

	const CDODWeaponInfo &info = GetDODWpnData();

	if( Q_strlen(info.m_szDeployedModel) > 0 )
	{
		Assert( info.m_iAltWpnCriteria & ALTWPN_CRITERIA_DEPLOYED );
		m_iDeployedModelIndex = CBaseEntity::PrecacheModel( info.m_szDeployedModel );
	}

	if( Q_strlen(info.m_szDeployedReloadModel) > 0 )
	{
		Assert( info.m_iAltWpnCriteria & ALTWPN_CRITERIA_DEPLOYED_RELOAD );
		m_iDeployedReloadModelIndex = CBaseEntity::PrecacheModel( info.m_szDeployedReloadModel );
	}

	if( Q_strlen(info.m_szProneDeployedReloadModel) > 0 )
	{
		Assert( info.m_iAltWpnCriteria & ALTWPN_CRITERIA_PRONE_DEPLOYED_RELOAD );
		m_iProneDeployedReloadModelIndex = CBaseEntity::PrecacheModel( info.m_szProneDeployedReloadModel );
	}

	m_iCurrentWorldModel = m_iWorldModelIndex;
	Assert( m_iCurrentWorldModel != 0 );
}

bool CDODBipodWeapon::CanDrop( void )
{
	return ( IsDeployed() == false );
}

bool CDODBipodWeapon::CanHolster( void )
{
	return ( IsDeployed() == false );
}

void CDODBipodWeapon::Drop( const Vector &vecVelocity )
{
	// If a player is killed while deployed, this resets the weapon state
	SetDeployed( false );

	BaseClass::Drop( vecVelocity );
}

void CDODBipodWeapon::SecondaryAttack( void )
{
	// Toggle deployed / undeployed

	if ( IsDeployed() )
		UndeployBipod();
	else 
	{
		if ( CanAttack() )
		{
			bool bSuccess = AttemptToDeploy();

			CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );
			Assert( pPlayer );

			if ( !bSuccess )
			{
				pPlayer->HintMessage( HINT_MG_DEPLOY_USAGE );
			}
			else
			{
#ifndef CLIENT_DLL
				pPlayer->RemoveHintTimer( m_iAltFireHint );
#endif
			}
		}
	}
}

bool CDODBipodWeapon::Reload( void )
{
	bool bSuccess = BaseClass::Reload();

	if ( bSuccess )
	{
		m_flNextSecondaryAttack = gpGlobals->curtime;
	}

	return bSuccess;
}

#include "in_buttons.h"
// check in busy frame too, to catch cancelling reloads
void CDODBipodWeapon::ItemBusyFrame( void )
{
	BipodThink();

	CBasePlayer *pPlayer = GetPlayerOwner();

	if ( !pPlayer )
		return;

	if ((pPlayer->m_nButtons & IN_ATTACK2) && (m_flNextSecondaryAttack <= gpGlobals->curtime))
	{
		SecondaryAttack();

		pPlayer->m_nButtons &= ~IN_ATTACK2;
	}

	BaseClass::ItemBusyFrame();
}

void CDODBipodWeapon::ItemPostFrame( void )
{
	BipodThink();
	BaseClass::ItemPostFrame();
}

// see if we're still deployed on the same entity at the same height
// in future can be expanded to check when deploying on other ents that may move / die / break
void CDODBipodWeapon::BipodThink( void )
{
	if ( m_flNextDeployCheckTime < gpGlobals->curtime )
	{
		if ( IsDeployed() )
		{
			if ( CheckDeployEnt() == false )
			{
				UndeployBipod();

				// cancel any reload in progress
				m_bInReload = false;
				m_flNextPrimaryAttack = gpGlobals->curtime + 0.1;
				m_flNextSecondaryAttack = gpGlobals->curtime + 0.1;
			}
		}

		m_flNextDeployCheckTime = gpGlobals->curtime + 0.2;
	}	
}

void CDODBipodWeapon::DoFireEffects()
{
	BaseClass::DoFireEffects();

	CBaseEntity *pDeployedOn = m_hDeployedOnEnt.Get();

	// in future can be expanded to check when deploying on other ents that may move / die / break
	if ( pDeployedOn && pDeployedOn->IsPlayer() && IsDeployed() )
	{
#ifndef CLIENT_DLL
		CSingleUserRecipientFilter user( (CBasePlayer *)pDeployedOn );
		enginesound->SetPlayerDSP( user, 32, false );
#endif
	}
}

// Do the work of deploying the gun at the current location and angles
void CDODBipodWeapon::DeployBipod( float flHeight, CBaseEntity *pDeployedOn, float flYawLimitLeft, float flYawLimitRight )
{
	m_flDeployedHeight = flHeight;
	m_hDeployedOnEnt = pDeployedOn;

	if ( pDeployedOn )
        m_DeployedEntOrigin = pDeployedOn->GetAbsOrigin();
	else
		m_DeployedEntOrigin = vec3_origin;	// world ent 

	SendWeaponAnim( GetDeployActivity() );
	SetDeployed( true );

	CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );
	pPlayer->m_Shared.SetDeployed( true, flHeight );
	pPlayer->m_Shared.SetDeployedYawLimits( flYawLimitLeft, flYawLimitRight );

	// Save this off so we do duck checks later, even though we won't be flagged as ducking
	m_bDuckedWhenDeployed = pPlayer->m_Shared.IsDucking();	

	// More TODO:
	// recalc our yaw limits if the item we're deployed on has moved or rotated
	// if our new limits are outside our current eye angles, undeploy us

	m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
	m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
	m_flTimeWeaponIdle = gpGlobals->curtime + SequenceDuration();
}

// Do the work of undeploying the gun
void CDODBipodWeapon::UndeployBipod( void )
{
	SendWeaponAnim( GetUndeployActivity() );
	SetDeployed( false );

	CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );
	pPlayer->m_Shared.SetDeployed( false );

	// if we cancelled our reload by undeploying, don't let the reload complete
	if ( m_bInReload )
		m_bInReload = false;

	m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
	m_flNextSecondaryAttack = gpGlobals->curtime + SequenceDuration();
	pPlayer->m_flNextAttack = m_flNextPrimaryAttack;
	m_flTimeWeaponIdle = gpGlobals->curtime + SequenceDuration();
}

#ifndef CLIENT_DLL
ConVar dod_debugmgdeploy( "dod_debugmgdeploy", "0", FCVAR_CHEAT|FCVAR_GAMEDLL );
#endif

bool CDODBipodWeapon::AttemptToDeploy( void )
{
	CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );

	if ( pPlayer->GetGroundEntity() == NULL )
		return false;

	if ( pPlayer->m_Shared.IsGettingUpFromProne() || pPlayer->m_Shared.IsGoingProne() )
		return false;

	CBaseEntity *pDeployedOn = NULL;
	float flDeployedHeight = 0.0f;
	float flYawLimitLeft = 0;
	float flYawLimitRight = 0;

	if ( TestDeploy( &flDeployedHeight, &pDeployedOn, &flYawLimitLeft, &flYawLimitRight ) )
	{
		if ( pPlayer->m_Shared.IsProne() && !pPlayer->m_Shared.IsGettingUpFromProne() )
		{
			DeployBipod( flDeployedHeight, NULL, flYawLimitLeft, flYawLimitRight );
			return true;
		}
		else
		{
			float flMinDeployHeight = 24.0;
			if( flDeployedHeight >= flMinDeployHeight )
			{
				DeployBipod( flDeployedHeight, pDeployedOn, flYawLimitLeft, flYawLimitRight );
				return true;
			}
		}		
	}

	return false;
}

bool CDODBipodWeapon::CheckDeployEnt( void )
{
	CBaseEntity *pDeployedOn = NULL;
	float flDeployedHeight = 0.0f;

	if ( TestDeploy( &flDeployedHeight, &pDeployedOn ) == false )
		return false;

	// If the entity we were deployed on has changed, or has moved, the origin
	// of it will be different. If so, recalc our yaw limits.
	if ( pDeployedOn )
	{
		if ( m_DeployedEntOrigin != pDeployedOn->GetAbsOrigin() )
		{
			float flYawLimitLeft = 0, flYawLimitRight = 0;
			TestDeploy( &flDeployedHeight, &pDeployedOn, &flYawLimitLeft, &flYawLimitRight );

			CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );
			
			if ( pPlayer )
				pPlayer->m_Shared.SetDeployedYawLimits( flYawLimitLeft, flYawLimitRight );

			m_DeployedEntOrigin = pDeployedOn->GetAbsOrigin();
		}
	}
	
	// 20 unit tolerance in height
	if ( abs( m_flDeployedHeight - flDeployedHeight ) > 20 )
		return false;

	return true;
}

bool CDODBipodWeapon::TestDeploy( float *flDeployedHeight, CBaseEntity **pDeployedOn, float *flYawLimitLeft /* = NULL */, float *flYawLimitRight /* = NULL */ )
{
	CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );

	QAngle angles = pPlayer->EyeAngles();

	float flPitch = angles[PITCH];
	if( flPitch > 180 )
	{
		flPitch -= 360;
	}

	if( flPitch > MIN_DEPLOY_PITCH || flPitch < MAX_DEPLOY_PITCH )
	{
		return false;
	}

	bool bSuccess = false;

	// if we're not finding the range, test at the current angles
	if ( flYawLimitLeft == NULL && flYawLimitRight == NULL )
	{
		// test our current angle only
		bSuccess = TestDeployAngle( pPlayer, flDeployedHeight, pDeployedOn, angles );
	}
	else
	{
		float flSaveYaw = angles[YAW];

		const float flAngleDelta = 5;
		const float flMaxYaw = 45;

		float flLeft = 0;
		float flRight = 0;

		float flTestDeployHeight = 0;
		CBaseEntity *pTestDeployedOn = NULL;

		// Sweep Left
		while ( flLeft <= flMaxYaw )
		{
			angles[YAW] = flSaveYaw + flLeft;

			if ( TestDeployAngle( pPlayer, &flTestDeployHeight, &pTestDeployedOn, angles ) == true )
			{
				if ( flLeft == 0 )	// first sweep is authoritative on deploy height and entity
				{
					*flDeployedHeight = flTestDeployHeight;
					*pDeployedOn = pTestDeployedOn;
				}
				else if ( abs( *flDeployedHeight - flTestDeployHeight ) > 20 )
				{
					// don't allow yaw to a position that is too different in height
					break;
				}

				*flYawLimitLeft = flLeft;
			}
			else
			{
				break;
			}
			flLeft += flAngleDelta;
		}

		// can't deploy here, drop out early
		if ( flLeft <= 0 )
			return false;

		// we already tested directly ahead and it was clear. skip one test
		flRight += flAngleDelta;

		// Sweep Right
		while ( flRight <= flMaxYaw )
		{
			angles[YAW] = flSaveYaw - flRight;

			if ( TestDeployAngle( pPlayer, &flTestDeployHeight, &pTestDeployedOn, angles ) == true )
			{
				if ( abs( *flDeployedHeight - flTestDeployHeight ) > 20 )
				{
					// don't allow yaw to a position that is too different in height
					break;
				}

				*flYawLimitRight = flRight;
			}
			else
			{
				break;
			}
			flRight += flAngleDelta;
		}

		bSuccess = true;
	}

	return bSuccess;
}

//ConVar dod_deploy_box_size( "dod_deploy_box_size", "8", FCVAR_REPLICATED );

#include "util_shared.h"

// trace filter that ignores all players except the passed one
class CTraceFilterIgnorePlayersExceptFor : public CTraceFilterSimple
{
public:
	// It does have a base, but we'll never network anything below here..
	DECLARE_CLASS( CTraceFilterIgnorePlayersExceptFor, CTraceFilterSimple );

	CTraceFilterIgnorePlayersExceptFor( const IHandleEntity *passentity, int collisionGroup )
		: CTraceFilterSimple( passentity, collisionGroup )
	{
	}

	virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask )
	{
		CBaseEntity *pEntity = EntityFromEntityHandle( pServerEntity );

		if ( pEntity->IsPlayer() )
		{
			if ( pEntity != GetPassEntity() )
			{
				return false;
			}
			else
				return true;
		}

		return true;
	}
};

#define DEPLOY_DOWNTRACE_FORWARD_DIST	16
#define DEPLOY_DOWNTRACE_OFFSET	16	// yay for magic numbers

bool CDODBipodWeapon::TestDeployAngle( CDODPlayer *pPlayer, float *flDeployedHeight, CBaseEntity **pDeployedOn, QAngle angles )
{
	// make sure we are deployed on the same entity at the same height
	trace_t tr;	

	angles[PITCH] = 0;

	Vector forward, right, up;
	AngleVectors( angles, &forward, &right, &up );

	// start at top of player bbox
	Vector vecStart = pPlayer->GetAbsOrigin();

	float flForwardTraceDist = 32;

	// check us as ducking if we are ducked, or if were ducked when we were deployed
	bool bDucking = pPlayer->m_Shared.IsDucking() || ( IsDeployed() && m_bDuckedWhenDeployed );

	if ( pPlayer->m_Shared.IsProne() )
	{
		vecStart.z += VEC_PRONE_HULL_MAX[2];
		flForwardTraceDist = 16;
	}		
	else if ( bDucking )
	{
		vecStart.z += VEC_DUCK_HULL_MAX[2];
	}
	else
	{
		vecStart.z += 60;
	}

	int dim = 1;	//	dod_deploy_box_size.GetInt();
	Vector vecDeployTraceBoxSize( dim, dim, dim );

	vecStart.z -= vecDeployTraceBoxSize[2];
	vecStart.z -= 4;

	// sandbags are around 50 units high. Shouldn't be able to deploy on anything a lot higher than that

	// optimal standing height ( for animation's sake ) is around 42 units
	// optimal ducking height is around 20 units ( 20 unit high object, plus 8 units of gun )

	// Start one half box width away from the edge of the player hull
	Vector vecForwardStart = vecStart + forward * ( VEC_HULL_MAX_SCALED( pPlayer )[0] + vecDeployTraceBoxSize[0] );

	int traceMask = MASK_SOLID;

	CBaseEntity *pDeployedOnPlayer = NULL;

	if ( m_hDeployedOnEnt && m_hDeployedOnEnt->IsPlayer() )
	{
		pDeployedOnPlayer = m_hDeployedOnEnt.Get();
	}

	CTraceFilterIgnorePlayersExceptFor deployedFilter( pDeployedOnPlayer, COLLISION_GROUP_NONE );
	CTraceFilterSimple undeployedFilter( pPlayer, COLLISION_GROUP_NONE );

	// if we're deployed, skip all players except for the deployed on player
	// if we're not, only skip ourselves
	ITraceFilter *filter;
	if ( IsDeployed() )
		filter = &deployedFilter;
	else
		filter = &undeployedFilter;

	UTIL_TraceHull( vecForwardStart,
		vecForwardStart + forward * ( flForwardTraceDist - 2 * vecDeployTraceBoxSize[0] ),
		-vecDeployTraceBoxSize,
		vecDeployTraceBoxSize,
		traceMask,	
		filter,
		&tr );

#ifndef CLIENT_DLL
	if ( dod_debugmgdeploy.GetBool() )
	{
		NDebugOverlay::Line( vecForwardStart, vecForwardStart + forward * ( flForwardTraceDist - 2 * vecDeployTraceBoxSize[0] ), 0, 0, 255, true, 0.1 );
		NDebugOverlay::Box( vecForwardStart, -vecDeployTraceBoxSize, vecDeployTraceBoxSize, 255, 0, 0, 128, 0.1 );
		NDebugOverlay::Box( tr.endpos, -vecDeployTraceBoxSize, vecDeployTraceBoxSize, 0, 0, 255, 128, 0.1 );
	}
#endif

	// Test forward, are we trying to deploy into a solid object?
	if ( tr.fraction < 1.0 )
	{
		return false;
	}

	// If we're prone, we can always deploy, don't do the ground test
	if ( pPlayer->m_Shared.IsProne() && !pPlayer->m_Shared.IsGettingUpFromProne() )
	{
		// MATTTODO: do trace from *front* of player, not from the edge of crouch hull
		// this is sufficient
		*flDeployedHeight = PRONE_DEPLOY_HEIGHT;
		return true;
	}

	// fix prediction hitch when coming up from prone. client thinks we aren't
	// prone, but hull is still prone hull
	// assumes prone hull is shorter than duck hull!
	if ( pPlayer->WorldAlignMaxs().z <= VEC_PRONE_HULL_MAX.z )
		return false;

	// Else trace down
	Vector vecDownTraceStart = vecStart + forward * ( VEC_HULL_MAX_SCALED( pPlayer )[0] + DEPLOY_DOWNTRACE_FORWARD_DIST );
	int iTraceHeight = -( pPlayer->WorldAlignMaxs().z );


	// search down from the forward trace
	// use the farthest point first. If that fails, move towards the player a few times
	// to see if they are trying to deploy on a thin railing

	bool bFound = false;

	int maxAttempts = 4;
	float flHighestTraceEnd = vecDownTraceStart.z + iTraceHeight;
	CBaseEntity *pBestDeployEnt = NULL;

	while( maxAttempts > 0 )
	{
		UTIL_TraceHull( vecDownTraceStart,
			vecDownTraceStart + Vector(0,0,iTraceHeight),	// trace forward one box width
			-vecDeployTraceBoxSize,
			vecDeployTraceBoxSize,
			traceMask,	
			filter,
			&tr );

#ifndef CLIENT_DLL
		if ( dod_debugmgdeploy.GetBool() )
		{
			NDebugOverlay::Line( vecDownTraceStart, tr.endpos, 255, 0, 0, true, 0.1 );
			NDebugOverlay::Box( vecDownTraceStart, -vecDeployTraceBoxSize, vecDeployTraceBoxSize, 255, 0, 0, 128, 0.1 );
			NDebugOverlay::Box( tr.endpos, -vecDeployTraceBoxSize, vecDeployTraceBoxSize, 0, 0, 255, 128, 0.1 );
		}
#endif

		bool bSuccess = ( tr.fraction < 1.0 ) && !tr.startsolid && !tr.allsolid;

		// if this is the first one found, set found flag
		if ( bSuccess && !bFound )
		{
			bFound = true;
		}
		else if ( bFound == true && bSuccess == false )
		{
			// it failed and we have some data. break here
			break;
		}

		// if this trace is better ( higher ) use this one
		if ( tr.endpos.z > flHighestTraceEnd )
		{
			flHighestTraceEnd = tr.endpos.z;
			pBestDeployEnt = tr.m_pEnt;
		}

		--maxAttempts;

		// move towards the player, looking for a better height to deploy on
		vecDownTraceStart += forward * -4;
	}

	if ( bFound == false || pBestDeployEnt == NULL )
		return false;

	*pDeployedOn = pBestDeployEnt;
	*flDeployedHeight = flHighestTraceEnd - vecDeployTraceBoxSize[0] + DEPLOY_DOWNTRACE_OFFSET - pPlayer->GetAbsOrigin().z;
	return true;
}

Activity CDODBipodWeapon::GetUndeployActivity( void )
{
	return ACT_VM_UNDEPLOY;
}

Activity CDODBipodWeapon::GetDeployActivity( void )
{
	return ACT_VM_DEPLOY;
}


Activity CDODBipodWeapon::GetPrimaryAttackActivity( void )
{
	Activity actPrim;

	if( IsDeployed() )
		actPrim = ACT_VM_PRIMARYATTACK_DEPLOYED;	
	else
		actPrim = ACT_VM_PRIMARYATTACK;

	return actPrim;
}

Activity CDODBipodWeapon::GetReloadActivity( void )
{
	Activity actReload;

	if( IsDeployed() )
		actReload = ACT_VM_RELOAD_DEPLOYED;	
	else
		actReload = ACT_VM_RELOAD;

	return actReload;
}

Activity CDODBipodWeapon::GetIdleActivity( void )
{
	Activity actIdle;

	if( IsDeployed() )
		actIdle = ACT_VM_IDLE_DEPLOYED;	
	else
		actIdle = ACT_VM_IDLE;

	return actIdle;
}


float CDODBipodWeapon::GetWeaponAccuracy( float flPlayerSpeed )
{
	float flSpread = BaseClass::GetWeaponAccuracy( flPlayerSpeed );
	
	if( IsDeployed() )
	{
		flSpread = m_pWeaponInfo->m_flSecondaryAccuracy;
	}

	return flSpread;
}

#ifdef CLIENT_DLL

	int CDODBipodWeapon::GetWorldModelIndex( void )
	{
		if( GetOwner() == NULL )
			return m_iWorldModelIndex;
		else if( m_bUseAltWeaponModel )
			return m_iWorldModelIndex;	//override for hand signals etc
		else
            return m_iCurrentWorldModel;
	}

	void CDODBipodWeapon::CheckForAltWeapon( int iCurrentState )
	{
		int iCriteria = GetDODWpnData().m_iAltWpnCriteria;

		bool bReloading = ( iCurrentState & ALTWPN_CRITERIA_RELOADING );

		if( bReloading )
		{
			if( IsDeployed() && iCurrentState & ALTWPN_CRITERIA_PRONE && 
				iCriteria & ALTWPN_CRITERIA_PRONE_DEPLOYED_RELOAD )
			{
				m_iCurrentWorldModel = m_iProneDeployedReloadModelIndex;		// prone deployed reload	
			}
			else if( IsDeployed() && iCriteria & ALTWPN_CRITERIA_DEPLOYED_RELOAD )
			{
				m_iCurrentWorldModel = m_iDeployedReloadModelIndex;		// deployed reload			
			}
			else if( iCriteria & ALTWPN_CRITERIA_RELOADING )
			{
				m_iCurrentWorldModel = m_iReloadModelIndex;				// left handed reload			
			}
			else 
			{
				m_iCurrentWorldModel = m_iWorldModelIndex;				// normal weapon reload
			}
		}
		else if( IsDeployed() && iCriteria & ALTWPN_CRITERIA_DEPLOYED )
		{
			m_iCurrentWorldModel = m_iDeployedModelIndex;				// bipod down
		}
		else if( (iCurrentState & iCriteria) & ALTWPN_CRITERIA_FIRING )
		{
			// don't think we have any weapons that do this
			m_iCurrentWorldModel = m_iReloadModelIndex;					// left handed shooting?	
		}
		else
		{
			m_iCurrentWorldModel = m_iWorldModelIndex;					// normal weapon
		}
	}

	ConVar deployed_mg_sensitivity( "deployed_mg_sensitivity", "0.9", FCVAR_CHEAT, "Mouse sensitivity while deploying a machine gun" );

	void CDODBipodWeapon::OverrideMouseInput( float *x, float *y )
	{
		if( IsDeployed() )
		{
			float flSensitivity = deployed_mg_sensitivity.GetFloat();

			*x *= flSensitivity;
			*y *= flSensitivity;		
		}
	}

#endif