//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CBaseTFVehicle::SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move )
{
	// animate + update attachment points
#ifdef CLIENT_DLL
	StudioFrameAdvance();
#else
	StudioFrameAdvance();
	// This calls StudioFrameAdvance, then we use the results from that to determine where to move.
	DispatchAnimEvents( this );
#endif
	
	CTFMoveData *pMoveData = (CTFMoveData*)move; 
	Assert( sizeof(VehicleBaseMoveData_t) <= pMoveData->VehicleDataMaxSize() );

	VehicleBaseMoveData_t *pVehicleData = (VehicleBaseMoveData_t*)pMoveData->VehicleData();
	pVehicleData->m_pVehicle = this;
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CObjectBaseMannedGun::SetupMove( CBasePlayer *pPlayer, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move )
{
	BaseClass::SetupMove( pPlayer, ucmd, pHelper, move );

	CTFMoveData *pMoveData = (CTFMoveData*)move; 
	Assert( sizeof(MannedPlasmagunData_t) <= pMoveData->VehicleDataMaxSize() );

	MannedPlasmagunData_t *pVehicleData = (MannedPlasmagunData_t*)pMoveData->VehicleData();
	pVehicleData->m_pVehicle = this;
	pVehicleData->m_flGunYaw = m_flGunYaw;
	pVehicleData->m_flGunPitch = m_flGunPitch;
	pVehicleData->m_flBarrelPitch = m_flBarrelPitch;
	pVehicleData->m_nMoveStyle = m_nMoveStyle;
	pVehicleData->m_flBarrelHeight = m_flBarrelHeight;
	pVehicleData->m_nBarrelPivotAttachment = m_nBarrelPivotAttachment;
	pVehicleData->m_nBarrelAttachment = m_nBarrelAttachment;
	pVehicleData->m_nStandAttachment = m_nStandAttachment;
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CObjectBaseMannedGun::FinishMove( CBasePlayer *player, CUserCmd *ucmd, CMoveData *move )
{
	BaseClass::FinishMove( player, ucmd, move );
	CTFMoveData *pMoveData = (CTFMoveData*)move; 
	Assert( sizeof(MannedPlasmagunData_t) <= pMoveData->VehicleDataMaxSize() );

	MannedPlasmagunData_t *pVehicleData = (MannedPlasmagunData_t*)pMoveData->VehicleData();
	m_flGunYaw = pVehicleData->m_flGunYaw;
	m_flGunPitch = pVehicleData->m_flGunPitch;
	m_flBarrelPitch = pVehicleData->m_flBarrelPitch;

	// Set the bone state..
	SetBoneController( 0, m_flGunYaw );
	SetBoneController( 1, m_flGunPitch );

	if ( m_nMoveStyle == MOVEMENT_STYLE_BARREL_PIVOT )
	{
		SetBoneController( 2, m_flBarrelPitch );
	}

	NetworkStateChanged();
}
//-----------------------------------------------------------------------------
// Implement this if you want to know when the player collides during OnPlayerMove
//-----------------------------------------------------------------------------
void CTFGameMovementRecon::OnTryPlayerMoveCollision( trace_t &tr )
{
	if ( !m_bPerformingAirMove )
		return;
	
	// Only keep track of world collisions
	if ( tr.DidHitWorld() )
	{
		CTFMoveData *pTFMove = TFMove();
		if ( pTFMove )
		{
			if ( ( pTFMove->ReconData().m_flSuppressionJumpTime == TIME_WALL_INVALID ) &&
				 ( pTFMove->ReconData().m_flSuppressionImpactTime == TIME_WALL_INVALID ) )
			{
				// No walljumps off of mostly horizontal surfaces...
				if ( fabs( tr.plane.normal.z ) > 0.9f )
					return;
			
				// No walljumps off of the same plane as the last one...
				if ( (pTFMove->ReconData().m_flImpactDist == tr.plane.dist) && 
					(VectorsAreEqual(pTFMove->ReconData().m_vecImpactNormal, tr.plane.normal, 1e-2) ) )
				{
					return;
				}

				// If you hit a wall, no double jumps for you
				pTFMove->ReconData().m_nJumpCount = 2;
				
				// Play an impact sound
				MoveHelper()->StartSound( pTFMove->m_vecAbsOrigin, "Recon.WallJump" );

				pTFMove->ReconData().m_vecImpactNormal = tr.plane.normal;
				pTFMove->ReconData().m_flImpactDist = tr.plane.dist;

				pTFMove->ReconData().m_flActiveJumpTime = TIME_WALL_ACTIVATE_JUMP;
				pTFMove->ReconData().m_flSuppressionImpactTime = TIME_WALL_SUPPRESSION_IMPACT;
			}
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTFGameMovementRecon::UpdateTimers( void )
{
	BaseClass::UpdateTimers();

	CTFMoveData *pTFMove = TFMove();
	if ( !pTFMove )
		return;

	float frame_msec = 1000.0f * gpGlobals->frametime;

	// Decrement the recon timers.
	if ( pTFMove->ReconData().m_flSuppressionJumpTime != TIME_WALL_INVALID )
	{
		pTFMove->ReconData().m_flSuppressionJumpTime -= frame_msec;
		if ( pTFMove->ReconData().m_flSuppressionJumpTime <= 0.0f )
		{
			pTFMove->ReconData().m_flSuppressionJumpTime = TIME_WALL_INVALID;
		}
	}

	if ( pTFMove->ReconData().m_flSuppressionImpactTime != TIME_WALL_INVALID )
	{
		pTFMove->ReconData().m_flSuppressionImpactTime -= frame_msec;
		if ( pTFMove->ReconData().m_flSuppressionImpactTime <= 0.0f )
		{
			pTFMove->ReconData().m_flSuppressionImpactTime = TIME_WALL_INVALID;
		}
	}

	if ( pTFMove->ReconData().m_flActiveJumpTime != TIME_WALL_INVALID )
	{
		pTFMove->ReconData().m_flActiveJumpTime -= frame_msec;
		if ( pTFMove->ReconData().m_flActiveJumpTime <= 0.0f )
		{
			pTFMove->ReconData().m_flActiveJumpTime = TIME_WALL_INVALID;
		}
	}

	if ( pTFMove->ReconData().m_flStickTime != TIME_WALL_INVALID )
	{
		pTFMove->ReconData().m_flStickTime -= frame_msec;
		if ( pTFMove->ReconData().m_flStickTime <= 0.0f )
		{
			pTFMove->ReconData().m_flStickTime = TIME_WALL_INVALID;

			// Restore velocity at this time
			pTFMove->m_vecVelocity = pTFMove->ReconData().m_vecUnstickVelocity;
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: Check the jump button to make various jumps
//-----------------------------------------------------------------------------
bool CTFGameMovementRecon::CheckJumpButton()
{
	// FIXME: Refactor this so we don't have this complicated duplicate
	// code here + in gamemovement.cpp

	if ( player->pl.deadflag )
	{
		mv->m_nOldButtons |= IN_JUMP ;	// don't jump again until released
		return false;
	}

	// Water jumps!
	if ( CheckWaterJump() )
		return false;

	if ( mv->m_nOldButtons & IN_JUMP )
		return false;		// don't pogo stick

	CTFMoveData *pTFMove = static_cast<CTFMoveData*>( mv );

	// Check for wall jump...
	if ( !CheckWallJump( pTFMove ) )
	{
		// If we already did one air jump, can't do another 
 		if ( (player->GetGroundEntity() == NULL ) && ( pTFMove->ReconData().m_nJumpCount > 1) )
		{
			mv->m_nOldButtons |= IN_JUMP;
			return false;		// in air, so no effect
		}

		pTFMove->ReconData().m_nJumpCount += 1;

		// Am I doing a double-jump?
		bool bWasInAir = (player->GetGroundEntity() == NULL);

		// In the air now.
		SetGroundEntity( NULL );
		
		PlayStepSound( m_pSurfaceData, 1.0, true );

		if (!CheckBackJump(bWasInAir))
		{
			if (CheckStrafeJump(bWasInAir))
			{
				// Can't double jump out of a roll....
				pTFMove->ReconData().m_nJumpCount += 1;
			}
			else
			{
				CheckForwardJump(bWasInAir);
			}
		}
	}

	pTFMove->ReconData().m_flSuppressionJumpTime = TIME_WALL_SUPPRESSION_JUMP;	

	FinishGravity();

	mv->m_outWishVel = mv->m_vecVelocity;
	mv->m_outStepHeight += 0.1f;

	// Flag that we jumped.
	mv->m_nOldButtons |= IN_JUMP;	// don't jump again until released
	return true;
}