//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
float CWeaponCombatShield::GetLoweringTime( void )
{
	if ((GetShieldState() != SS_DOWN ) && (GetShieldState() != SS_LOWERING))
		return 0.0f;

	return gpGlobals->curtime - m_flShieldDownStartTime;
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponCombatShield::GetViewmodelBoneControllers( C_BaseViewModel *pViewModel, float controllers[MAXSTUDIOBONECTRLS])
{
	// Dial shows the shield power level
	float flPowerLevel = 1.0;
	if ( GetShieldState() == SS_UP )
	{
		flPowerLevel = GetShieldHealth();
	}
	else if ( GetShieldState() == SS_RAISING )
	{
		// Bring the power up with the animation
		float flTotal = m_flShieldRaisedTime - m_flShieldUpStartTime;
		float flCurrent = (gpGlobals->curtime - m_flShieldUpStartTime);
		flPowerLevel = flCurrent / flTotal;
	}
	else if ( GetShieldState() == SS_LOWERING )
	{
		// Bring the power down with the animation
		float flTotal = (m_flShieldLoweredTime - m_flShieldDownStartTime);
		float flCurrent = (gpGlobals->curtime - m_flShieldDownStartTime);
		flPowerLevel = 1.0 - (flCurrent / flTotal);
	}

	// Make the middle point be full power (right of the middle being powered up)
	// Adjust a little for the perspective.
	flPowerLevel *= 0.55;

	// Add some shake
	flPowerLevel += RandomFloat( -0.02, 0.02 );
	controllers[0] = flPowerLevel;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
float CWeaponCombatShield::GetRaisingTime( void )
{
	if ((GetShieldState() != SS_UP ) && (GetShieldState() != SS_RAISING))
		return 0.0f;

	return gpGlobals->curtime - m_flShieldUpStartTime;
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponCombatBaseGrenade::ItemPostFrame( void )
{
	CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
	if (!pOwner)
		return;

	AllowShieldPostFrame( !m_flStartedThrowAt );

	// Look for button downs
	if ( (pOwner->m_nButtons & IN_ATTACK) && GetShieldState() == SS_DOWN && !m_flStartedThrowAt && (m_flNextPrimaryAttack <= gpGlobals->curtime) )
	{
		m_flStartedThrowAt = gpGlobals->curtime;

		SendWeaponAnim( ACT_VM_DRAW );
	}

	// Look for button ups
	if ( (pOwner->m_afButtonReleased & IN_ATTACK) && (m_flNextPrimaryAttack <= gpGlobals->curtime) && m_flStartedThrowAt )
	{
		m_flNextPrimaryAttack = gpGlobals->curtime;
		PrimaryAttack();
		m_flStartedThrowAt = 0;
	}

	//  No buttons down?
	if ( !((pOwner->m_nButtons & IN_ATTACK) || (pOwner->m_nButtons & IN_ATTACK2) || (pOwner->m_nButtons & IN_RELOAD)) )
	{
		WeaponIdle( );
	}
}
//-----------------------------------------------------------------------------
// Purpose: Handle deploying, undeploying, firing, etc.
// TODO: Add a deploy to the firing!  Currently no reloading!
//-----------------------------------------------------------------------------
void CWeaponRocketLauncher::ItemPostFrame( void )
{
	// Get the player.
	CBaseTFPlayer *pPlayer = ToBaseTFPlayer( GetOwner() );
	if ( !pPlayer )
		return;

	if ( UsesClipsForAmmo1() )
	{
		CheckReload();
	}

#if !defined( CLIENT_DLL )
	if ( !HasPrimaryAmmo() && ( m_flNextPrimaryAttack <= gpGlobals->curtime ) )
	{
		pPlayer->SwitchToNextBestWeapon( NULL );
	}
#endif

	// Handle Firing
	if ( GetShieldState() == SS_DOWN && !m_bInReload )
	{
		// Attempting to fire.
		if ( ( pPlayer->m_nButtons & IN_ATTACK ) && ( m_flNextPrimaryAttack <= gpGlobals->curtime ) )
		{
			if ( m_iClip1 > 0 )
			{
				PrimaryAttack();
			}
			else
			{
				Reload();
			}
		}

		// Reload button (or fire button when we're out of ammo)
		if ( m_flNextPrimaryAttack <= gpGlobals->curtime ) 
		{
			if ( pPlayer->m_nButtons & IN_RELOAD ) 
			{
				Reload();
			}
			else if ( !((pPlayer->m_nButtons & IN_ATTACK) || (pPlayer->m_nButtons & IN_ATTACK2) || (pPlayer->m_nButtons & IN_RELOAD)) )
			{
				if ( !m_iClip1 && HasPrimaryAmmo() )
				{
					Reload();
				}
			}
		}
	}

	// Prevent shield post frame if we're not ready to attack, or we're charging
	AllowShieldPostFrame( m_flNextPrimaryAttack <= gpGlobals->curtime || m_bInReload );
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponCombatLaserRifle::ItemPostFrame( void )
{
	CBaseTFPlayer *pOwner = ToBaseTFPlayer( GetOwner() );
	if (!pOwner)
		return;

	if ( UsesClipsForAmmo1() )
	{
		CheckReload();
	}

	RecalculateAccuracy();

	// Handle firing
	if ( GetShieldState() == SS_DOWN && !m_bInReload )
	{
		if ( (pOwner->m_nButtons & IN_ATTACK ) && (m_flNextPrimaryAttack <= gpGlobals->curtime) )
		{
			if ( m_iClip1 > 0 )
			{
				// Fire the plasma shot
				PrimaryAttack();
			}
			else
			{
				Reload();
			}
		}

		// Reload button (or fire button when we're out of ammo)
		if ( m_flNextPrimaryAttack <= gpGlobals->curtime ) 
		{
			if ( pOwner->m_nButtons & IN_RELOAD ) 
			{
				Reload();
			}
			else if ( !((pOwner->m_nButtons & IN_ATTACK) || (pOwner->m_nButtons & IN_ATTACK2) || (pOwner->m_nButtons & IN_RELOAD)) )
			{
				if ( !m_iClip1 && HasPrimaryAmmo() )
				{
					Reload();
				}
			}
		}
	}

	// Prevent shield post frame if we're not ready to attack, or we're charging
	AllowShieldPostFrame( m_flNextPrimaryAttack <= gpGlobals->curtime || m_bInReload );
}
//-----------------------------------------------------------------------------
// Purpose: I've been bashed by another player's shield
//-----------------------------------------------------------------------------
bool CWeaponCombatShield::TakeShieldBash( CBaseTFPlayer *pBasher )
{
	CBaseTFPlayer *pOwner = ToBaseTFPlayer( GetOwner() );
	if ( !pOwner )
		return false;

	// If I'm blocking, drop my block and prevent me from doing anything
	if ( GetShieldState() == SS_UP ||
		 GetShieldState() == SS_RAISING ||
		 GetShieldState() == SS_LOWERING )
	{
		// Make the shield unavailable
		SetShieldState( SS_UNAVAILABLE );
		SendWeaponAnim( ACT_VM_HITCENTER );

		m_flShieldUnavailableEndTime = gpGlobals->curtime + 2.0;

		// Play a sound	
		EmitSound( "WeaponCombatShield.TakeBash" );		
		return true;
	}

	return false;
}
//-----------------------------------------------------------------------------
// Purpose: Get the activity the other weapon in our twohanded container should 
//			play instead of the one it's attempting to play.
//-----------------------------------------------------------------------------
int	CWeaponCombatShield::ReplaceOtherWeaponsActivity( int iActivity )
{
	switch ( iActivity )
	{
	case ACT_VM_IDLE:
		// If I'm active, don't let it idle
		if ( GetShieldState() != SS_DOWN )
			return -1;

	default:
		break;
	};

	return BaseClass::ReplaceOtherWeaponsActivity(iActivity);
}
//-----------------------------------------------------------------------------
// Purpose: Attempt to block the incoming attack, and return the damage it 
//			should do after the block, if any.
//-----------------------------------------------------------------------------
float CWeaponCombatShield::AttemptToBlock( float flDamage )
{
	CBaseTFPlayer *pPlayer = ToBaseTFPlayer( GetOwner() );
	if ( !pPlayer || !weapon_combat_shield_factor.GetFloat() )
		return 0;

	// Block as much of the damage as we can
	float flPowerNeeded = flDamage * weapon_combat_shield_factor.GetFloat();
	flPowerNeeded = RemapVal( flPowerNeeded, 0, weapon_combat_shield_health.GetFloat(), 0, 1 );
	float flPowerUsed = min( flPowerNeeded, GetShieldHealth() );

#ifndef CLIENT_DLL
	RemoveShieldHealth( flPowerUsed );

	// Start recharging shortly after taking damage
	SetThink( ShieldRechargeThink );
	SetNextThink( gpGlobals->curtime + weapon_combat_shield_rechargetime.GetFloat() );
#endif

	// Failed to block it all?
	if ( flPowerUsed < flPowerNeeded )
	{
#ifndef CLIENT_DLL
		// Force the shield to drop if it's up
		if ( GetShieldState() == SS_UP )
		{
			// Play sound & anim
			SendWeaponAnim( ACT_VM_HAULBACK );
			WeaponSound( SPECIAL2 );
			SetShieldState( SS_LOWERING );
		}
#endif

		return ( flDamage - (flPowerUsed * (1.0 / weapon_combat_shield_factor.GetFloat())) );
	}

	return 0;
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponCombat_ChargeablePlasma::ItemPostFrame( void )
{
	CBaseTFPlayer *pOwner = ToBaseTFPlayer( GetOwner() );
	if (!pOwner)
		return;

	if ( UsesClipsForAmmo1() )
	{
		CheckReload();
	}

	// If burst shots are firing, ignore input
	if ( m_iBurstShotsRemaining > 0 )
	{
		if ( gpGlobals->curtime < m_flNextBurstShotTime )
			return;

		if ( m_iClip1 > 0 )
		{
			PrimaryAttack();
		}

		m_iBurstShotsRemaining--;
		m_flNextBurstShotTime = gpGlobals->curtime + BURST_FIRE_RATE;
		m_flNextPrimaryAttack = gpGlobals->curtime + GetFireRate();
		return;
	}

	// Handle charge firing
	if ( m_iClip1 > 0 && GetShieldState() == SS_DOWN && !m_bInReload )
	{
		if ( (pOwner->m_nButtons & IN_ATTACK ) )
		{
			if (m_bHasCharge)
			{
				if ( !m_bCharging && (m_flNextPrimaryAttack <= gpGlobals->curtime) )
				{
					m_bCharging = true;
					m_flChargeStartTime = gpGlobals->curtime;

					// Get a lock target right now
					m_hLockTarget = GetLockTarget();
				}
			}
			else
			{
				// Fire the plasma shot
				if (m_flNextPrimaryAttack <= gpGlobals->curtime)
					PrimaryAttack();
			}
		}
		else if ( m_bCharging )
		{
			m_bCharging = false;

			// Fire the plasma shot
			PrimaryAttack();

			// We might be firing a burst shot
			if (m_bHasBurstShot)
			{
				if ( m_flPower >= (MAX_CHARGED_TIME * 0.5) )
				{
					if ( m_flPower >= MAX_CHARGED_TIME )
					{
						m_iBurstShotsRemaining = 2;
					}
					else
					{
						m_iBurstShotsRemaining = 1;
					}

					m_flNextBurstShotTime = gpGlobals->curtime + BURST_FIRE_RATE;
				}
			}
		}
	}

	// Reload button
	if ( m_iBurstShotsRemaining == 0 && !m_bCharging )
	{
		if ( pOwner->m_nButtons & IN_RELOAD && UsesClipsForAmmo1() && !m_bInReload )
		{
			Reload();
		}
	}

	// Prevent shield post frame if we're not ready to attack, or we're charging
	AllowShieldPostFrame( !m_bCharging && ((m_flNextPrimaryAttack <= gpGlobals->curtime) || m_bInReload) );
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool CWeaponCombatShield::IsUp( void )
{
	return ( GetShieldState() == SS_UP );
}
//-----------------------------------------------------------------------------
// Purpose: Handle the shield input
//-----------------------------------------------------------------------------
void CWeaponCombatShield::ShieldPostFrame( void )
{
	CBaseTFPlayer *pOwner = ToBaseTFPlayer( GetOwner() );
	if (!pOwner)
		return;

	UpdateShieldState();
	CheckReload();

	// Store off EMP state
	bool isEMPed = IsOwnerEMPed();

	// If the shield's unavailable, just abort
	if ( GetShieldState() == SS_UNAVAILABLE )
		return;

	if ( m_flNextPrimaryAttack > gpGlobals->curtime )
		return;

	bool shieldRaised = ( GetShieldState() == SS_UP );
	bool shieldRaising = ( GetShieldState() == SS_RAISING );

	//	GetShieldState() == SS_LOWERING );

	// If my shield's out of power, I can't do anything with it
	if ( !GetShieldHealth() )
		return;

	// Was the shield button just pressed?
	if ( GetShieldState() == SS_DOWN && !isEMPed && pOwner->m_nButtons & IN_ATTACK2 )
	{
		// Play sound & anim
		WeaponSound( SPECIAL1 );
		SendWeaponAnim( ACT_VM_SECONDARYATTACK );

		SetShieldState( SS_RAISING );
		
		// Abort any reloads in progess
		pOwner->AbortReload();
	}
	else if ( ( shieldRaised || shieldRaising ) && !FBitSet( pOwner->m_nButtons, IN_ATTACK2 ) )
	{
		// Shield button was just released, check to see if we were parrying
		bool shouldParry = (gpGlobals->curtime < (m_flShieldUpStartTime + PARRY_DETECTION_TIME ));

		if ( m_bHasShieldParry && shouldParry )
		{
			// Parry!
			// Play sound & anim
			WeaponSound( SPECIAL2 );
			SendWeaponAnim( ACT_VM_SWINGHIT );

			SetShieldState( SS_PARRYING );

			// Bash enemies in front of me
			ShieldBash();
		}
		else
		{
			// Player's just lowered his shield
			// Play sound & anim
			WeaponSound( SPECIAL2 );
			SendWeaponAnim( ACT_VM_HAULBACK );

			SetShieldState( SS_LOWERING );
			m_flNextPrimaryAttack = gpGlobals->curtime + SequenceDuration();
		}
	}
	else if ( GetShieldState() == SS_UP && ( pOwner->m_nButtons & IN_ATTACK2 ) && ( isEMPed ) )
	{
		// We've got our shield up, and we were just EMPed, so drop it
		// Play sound & anim
		SendWeaponAnim( ACT_VM_HAULBACK );
		WeaponSound( SPECIAL2 );

		SetShieldState( SS_LOWERING );
	}
}