//-----------------------------------------------------------------------------
// Here's where we deal with weapons, ladders, etc.
//-----------------------------------------------------------------------------
void CVehicleTeleportStation::OnItemPostFrame( CBaseTFPlayer *pDriver )
{
	// I can't do anything if I'm not active
	if ( !ShouldBeActive() )
		return;

	if ( GetPassengerRole( pDriver ) != VEHICLE_DRIVER )
		return;

	if ( !IsDeployed() && ( pDriver->m_afButtonPressed & IN_ATTACK ) )
	{
		if ( ValidDeployPosition() )
		{
			Deploy();
		}
	}
	else if ( IsDeployed() && ( pDriver->m_afButtonPressed & IN_ATTACK ) )
	{
		UnDeploy();

		SetControlPanelsActive( false );
		SetBodygroup( 1, true );
		RemoveCornerSprites();
		SetContextThink( NULL, 0, TELEPORT_STATION_THINK_CONTEXT );
	}
}
void
ModConfig::EnableMod(const char* name)
{
	if (!name || !*name)
	return;

	Text* mod_name;

	ListIter<Text> iter = disabled;
	while (++iter) {
		Text* t = iter.value();

		if (*t == name) {
			mod_name = t;
			iter.removeItem();
			break;
		}
	}

	if (mod_name) {
		enabled.append(mod_name);

		if (!IsDeployed(*mod_name)) {
			ModInfo* mod_info = new(__FILE__,__LINE__) ModInfo;
			
			if (mod_info->Load(*mod_name) && mod_info->Enable()) {
				mods.append(mod_info);
			}
		}
	}
}
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 CDODBaseRocketWeapon::Reload( void )
{
	CDODPlayer *pPlayer = GetDODPlayerOwner();

	if (pPlayer->GetAmmoCount( GetPrimaryAmmoType() ) <= 0)
	{
		CDODPlayer *pDODPlayer = ToDODPlayer( pPlayer );
		pDODPlayer->HintMessage( HINT_AMMO_EXHAUSTED );
		return false;
	}

	Activity actReload;

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

	int iResult = DefaultReload( GetMaxClip1(), GetMaxClip2(), actReload );
	if ( !iResult )
		return false;

	pPlayer->SetAnimation( PLAYER_RELOAD );

	// if we don't want the auto-rezoom, undeploy here
	if ( !pPlayer->ShouldAutoRezoom() )
	{
		m_bDeployed = false;
		pPlayer->SetBazookaDeployed( m_bDeployed );
	}

	return true;
}
bool CDODBaseRocketWeapon::CanHolster( void )
{
	// can't holster if we are delpoyed and not reloading
	if ( IsDeployed() && !m_bInReload )
		return false;

	return true;
}
//-----------------------------------------------------------------------------
// Here's where we deal with weapons, ladders, etc.
//-----------------------------------------------------------------------------
void CVehicleSiegeTower::OnItemPostFrame( CBaseTFPlayer *pDriver )
{
	// I can't do anything if I'm not active
	if ( !ShouldBeActive() )
		return;

	if ( GetPassengerRole( pDriver ) != VEHICLE_DRIVER )
		return;

	if ( !IsDeployed() && ( pDriver->m_afButtonPressed & IN_ATTACK ) )
	{
		InternalDeploy();
	}
	else if ( IsDeployed() && ( pDriver->m_afButtonPressed & IN_ATTACK ) )
	{
		InternalUnDeploy();
	}
}
bool CDODBaseRocketWeapon::ShouldPlayerBeSlow( void )
{
	if( IsDeployed() && !m_bInReload )
	{
		return true;
	}
	else
		return false;
}
float CDODBipodWeapon::GetWeaponAccuracy( float flPlayerSpeed )
{
	float flSpread = BaseClass::GetWeaponAccuracy( flPlayerSpeed );
	
	if( IsDeployed() )
	{
		flSpread = m_pWeaponInfo->m_flSecondaryAccuracy;
	}

	return flSpread;
}
Activity CDODBipodWeapon::GetReloadActivity( void )
{
	Activity actReload;

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

	return actReload;
}
Activity CDODBipodWeapon::GetPrimaryAttackActivity( void )
{
	Activity actPrim;

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

	return actPrim;
}
Activity CDODBaseRocketWeapon::GetIdleActivity( void )
{
	Activity actIdle;

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

	return actIdle;
}
	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
		}
	}
void CDODBaseRocketWeapon::SecondaryAttack()
{
	CBasePlayer *pPlayer = GetPlayerOwner();

	//if we're underwater, lower it
	if( pPlayer->GetWaterLevel() > 2 )
	{
		if( IsDeployed() )
			Lower();
		return;
	}

	if( IsDeployed() )
	{	
		Lower();
	}
	else
	{
		if ( CanAttack() )
            Raise();
	}	
}
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
	}
}
// 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
ModConfig::Deploy()
{
	Save();

	if (enabled.size() < 1)
	return;

	Print("\nDEPLOYING MODS\n--------------\n");

	int i = 1;
	ListIter<Text> iter = enabled;
	while (++iter) {
		Text* name = iter.value();

		if (IsDeployed(name->data())) {
			Print("  %d. %s is already deployed (skipping)\n", i++, name->data());
			continue;
		}

		Print("  %d. %s\n", i++, name->data());

		ModInfo* mod_info = new(__FILE__,__LINE__) ModInfo;
		
		if (mod_info->Load(name->data()) && mod_info->Enable()) {
			mods.append(mod_info);
		}
		else {
			Print("     Could not deploy '%s' - disabling\n", name->data());

			delete mod_info;
			iter.removeItem();
			disabled.append(name);
		}
	}

	Print("\n");
	Game::UseLocale(0);
}
bool CDODBipodWeapon::CanHolster( void )
{
	return ( IsDeployed() == false );
}
void CDODBaseRocketWeapon::PrimaryAttack()
{
	Assert( m_pWeaponInfo );

	CDODPlayer *pPlayer = ToDODPlayer( GetPlayerOwner() );
	
	// Out of ammo?
	if ( m_iClip1 <= 0 )
	{
		if (m_bFireOnEmpty)
		{
			PlayEmptySound();
			m_flNextPrimaryAttack = gpGlobals->curtime + 0.2;
		}

		return;
	}

	if( pPlayer->GetWaterLevel() > 2 )
	{
		PlayEmptySound();
		m_flNextPrimaryAttack = gpGlobals->curtime + 1.0;
		return;
	}

	if( IsDeployed() )
	{
		// player "shoot" animation
		pPlayer->SetAnimation( PLAYER_ATTACK1 );

		SendWeaponAnim( ACT_VM_PRIMARYATTACK );
		
		FireRocket();

		DoFireEffects();

		m_iClip1--; 

#ifdef CLIENT_DLL
		if ( prediction->IsFirstTimePredicted() )
			pPlayer->DoRecoil( GetWeaponID(), m_pWeaponInfo->m_flRecoil );
#endif

		if ( m_iClip1 <= 0 && pPlayer->GetAmmoCount( GetPrimaryAmmoType() ) <= 0 )
		{
			Lower();
		}

		m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration() + 0.5;
		m_flTimeWeaponIdle = gpGlobals->curtime + SequenceDuration() + 0.5;	//length of the fire anim!

#ifndef CLIENT_DLL
		IGameEvent * event = gameeventmanager->CreateEvent( "dod_stats_weapon_attack" );
		if ( event )
		{
			event->SetInt( "attacker", pPlayer->GetUserID() );
			event->SetInt( "weapon", GetStatsWeaponID() );

			gameeventmanager->FireEvent( event );
		}
#endif	//CLIENT_DLL
	}
	else
	{
#ifdef CLIENT_DLL
		pPlayer->HintMessage( HINT_SHOULDER_WEAPON, true );
#endif

		m_flNextPrimaryAttack = gpGlobals->curtime + 2.0f;
	}
}
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[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[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;
}
bool CDODBipodWeapon::CanDrop( void )
{
	return ( IsDeployed() == false );
}