//---------------------------------------------------------------------------
// File			: AVP_Behaviour_Marine_Attack_Advance.cpp
// Created		: 
// Created By	: Gareth Thomas
// Copyright (C) 2007 Rebellion. All Rights Reserved.
//---------------------------------------------------------------------------

// INCLUDES ///////////////////////////////////////////////////////////

// core
#include "Core/Asura.h"
// header
#include "Behaviour/BehaviourTypes/Human/Marine/AVP_Behaviour_Marine_Attack_Advance.h"
// asura
#include "Entity/Locations/OrientedNode/CoverpointNode/Asura_ServerNode_Coverpoint.h"
#ifndef ASURA_NO_DEBUG_OUTPUT
#include "Rendering/Asura_Font_System.h"
#endif

// axon
// AVP
#include "Entity/GamePlayVolume/AVP_ServerEntity_GamePlayVolume.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Human/AVP_ServerActor_Human.h"
// AVP axon
#include "Behaviour/BehaviourTypes/AVP_Behaviour_Types.h"
#include "Core/BrainTypes/AVP_Brain_Actor_Marine.h"
#include "Tactical/AVP_Tactical_System.h"
#include "Core/AVP_PositionEvaluation.h"
#include "Knowledge/AVP_Knowledge_System_Actor.h"

#include "Behaviour/BehaviourTypes/AVP_Behaviour_Types.h"
#include "Behaviour/BehaviourTypes/Human/Marine/AVP_Behaviour_Marine_InCover.h"

DEBUGVAR float dbg_fLookTimeout = 0.5f;

//---------------------------------------------------------------------------
// AVP_Behaviour_Marine_Attack_Advance :: Constructor
//---------------------------------------------------------------------------
AVP_Behaviour_Marine_Attack_Advance::AVP_Behaviour_Marine_Attack_Advance( AVP_Brain_Actor_Marine* pxBrain )
: PARENT( pxBrain, AVP_BEHAVIOUR_TYPE_MARINE_ATTACK_ADVANCE )
, m_pxMarineBrain( pxBrain )
, m_eUpdateState( ADVANCE_CHOOSE )
, m_fTimer( 0.0f )
, m_uPrimaryThreatGuid( ASURA_GUID_UNREGISTERED )
, m_uWeaponType( AVP_WEAPON_BEHAVIOUR_TYPE_NONE )
, m_uBestCoverPoint( ASURA_GUID_UNREGISTERED )
, m_fAimTimer( dbg_fLookTimeout )
, m_uTestWp( ASURA_INVALID_WAYPOINT_ID )
{

}

//---------------------------------------------------------------------------
// AVP_Behaviour_Marine_Attack_Advance :: Deconstructor
//---------------------------------------------------------------------------
AVP_Behaviour_Marine_Attack_Advance::~AVP_Behaviour_Marine_Attack_Advance( void )
{

}

//---------------------------------------------------------------------------
// AVP_Behaviour_Marine_Attack_Advance :: Activate
//---------------------------------------------------------------------------
bool AVP_Behaviour_Marine_Attack_Advance::Activate( void )
{
	const bool bParentOk = PARENT::Activate();
	// Put Code Below This Comment

	AVP_ServerEntity_Actor* pxThreat = AVP_ServerEntity_Actor::FindEntity( GetKnowledgeSystem()->GetBestThreatKnowledge().GetGuid() );

	if ( pxThreat && pxThreat->IsCloaked( true ) )
	{
		float fDistanceSq = ( pxThreat->GetPosition() - GetMarineBrain()->GetHumanActor()->GetPosition() ).MagnitudeSquared();

		if (fDistanceSq < 100.0f)
		{
			GetMarineBrain()->GetHumanActor()->PlayDialogue( AVP_ServerActor_Human::AVP_DLG_HUMAN_SCARED_REACTION );
		}
	}
	else
	{
		GetMarineBrain()->GetHumanActor()->PlayDialogue( AVP_ServerActor_Human::AVP_DLG_HUMAN_ATTACKING );
	}

	m_uPrimaryThreatGuid = GetMarineBrain()->GetPrimaryThreatGuid();
	m_uWeaponType = GetMarineBrain()->GetCurrentWeaponType();

	// Put Code Above This Comment
	return bParentOk;
}

//---------------------------------------------------------------------------
// AVP_Behaviour_Marine_Attack_Advance :: Deactivate
//---------------------------------------------------------------------------
void AVP_Behaviour_Marine_Attack_Advance::Deactivate( void )
{
	// Put Code Above This Comment
	DestroyAllChildren();
	PARENT::Deactivate();
}

//---------------------------------------------------------------------------
// AVP_Behaviour_Marine_Attack_Advance :: PerFrameUpdate
//---------------------------------------------------------------------------
void AVP_Behaviour_Marine_Attack_Advance::PerFrameUpdate( const float fTimeslice )
{
	switch ( GetUpdateState() )
	{
		//---------------------------------------------------------------------------

		case ADVANCE_CHOOSE:
		{
			if ( m_fTimer <= 0.0f )
			{
				AVP_Navigation::NavData&	xNavData		= GetMarineBrain()->GetNavData();
				Asura_Guid					uCombatZoneGuid	= GetMarineBrain()->GetCombatZoneGuid();

				float fEvaluationRange, fMinEngementRange, fMaxEngagementRange;
				GetPosEvalRanges(&fEvaluationRange, &fMinEngementRange, &fMaxEngagementRange);

				AVP_Navigation::AVP_PosEvalParams	xPosEvalParams( GetMarineBrain()->GetOwnerGuid(), xNavData.m_usCurrentWPID, fEvaluationRange, fMinEngementRange, fMaxEngagementRange, uCombatZoneGuid );
				AVP_Navigation::PosEvalFunctor		pxPosEval( xNavData.m_usCurrentWPID, fEvaluationRange, xPosEvalParams, EvaluationFunction );
				AVP_Navigation::SearchWaypoints( AVP_Navigation::AVP_AI_PATHFINDER_FLAG_HUMANOID, &pxPosEval );

				if ( FindBestWaypoint( &pxPosEval ) )
				{
					SwitchToState( ADVANCE_MOVE );
					m_fTimer = Asura_Random::GetFloat( 3.7f, 5.2f );
				}
				else
				{
					m_fTimer = Asura_Random::GetFloat( 3.7f, 5.2f );
				}
			}

			m_fTimer -= fTimeslice;

		}break;

		//---------------------------------------------------------------------------

		case ADVANCE_MOVE:
		{
			if ( GetTacticalSystem()->HasArrivedAtDestination()  )
			{
				m_fTimer -= fTimeslice;

				if ( m_fTimer <= 0.0f )
				{
					SwitchToState( ADVANCE_CHOOSE );
				}
			}

		}break;

		//---------------------------------------------------------------------------

		case ADVANCE_MOVE_TO_COVER:
		{
			AVP_ServerActor_Human*			pxOurActor		= GetMarineBrain()->GetHumanActor();
			Asura_ServerNode_Coverpoint*	pxCoverPoint	= Asura_ServerNode_Coverpoint::FindEntity( m_uBestCoverPoint );
			Asura_Vector_3					xThreatPos		= Asura_Maths::ZeroVector3;
			GetMarineBrain()->GetThreatPos( xThreatPos );

			if ( !pxCoverPoint || !pxCoverPoint->ProvidesCoverFrom( xThreatPos ) )
			{
				SwitchToState( ADVANCE_CHOOSE );
				return;
			}

			float fDistanceToCoverSq = ( pxCoverPoint->GetPosition() - pxOurActor->GetPosition() ).MagnitudeSquared();

			if ( fDistanceToCoverSq <= 3.0f )
			{
				SwitchToState( ADVANCE_COVER );
			}

			if ( GetTacticalSystem()->DidRouteFindFail() )
			{
				SwitchToState( ADVANCE_CHOOSE );
			}

			// Always Look At The Threat
			GetMarineBrain()->AimAtThreat();
			GetMarineBrain()->LookAtThreat();
			GetTacticalSystem()->SetMovementSpeed( AVP_Navigation::MM_MEDIUM );

		}break;

		//---------------------------------------------------------------------------
		
		case ADVANCE_COVER:
		{
			// If our cover is no longer valid then switch to position evaluation
			if (m_uBestCoverPoint == ASURA_GUID_UNREGISTERED)
			{
				SwitchToState( ADVANCE_CHOOSE );
				return;
			}

			// Check that the cover behaviour hasn't finished
			Axon_Behaviour* pxCoverBehaviour = GetChildWithType( this, AVP_BEHAVIOUR_TYPE_MARINE_INCOVER );
			if ( ( pxCoverBehaviour && pxCoverBehaviour->IsFinished() ) || ( !pxCoverBehaviour ) )
			{
				SwitchToState( ADVANCE_CHOOSE );
				return;
			}

			Asura_ServerNode_Coverpoint* pxCoverPoint = Asura_ServerNode_Coverpoint::FindEntity( m_uBestCoverPoint );
			Asura_Vector_3					xThreatPos		= Asura_Maths::ZeroVector3;
			GetMarineBrain()->GetThreatPos( xThreatPos );

			// If our Cover no longer provides cover then switch to position evaluation
			if ( pxCoverPoint )
			{
				Asura_Vector_3 xDirToThreat = ( xThreatPos - pxCoverPoint->GetPosition() );
				float fDistanceSq = xDirToThreat.MagnitudeSquared();

				if ( fDistanceSq < 64.0f )
				{
					SwitchToState( ADVANCE_CHOOSE );
					return;
				}

				if ( !pxCoverPoint->ProvidesCoverFrom( xThreatPos ) )
				{
					SwitchToState( ADVANCE_CHOOSE );
					return;
				}
			}

		}break;

		default:
		{
		}break;
	}

	//---------------------------------------------------------------------------

	GetMarineBrain()->AimAtThreat();
	GetMarineBrain()->LookAtThreat();
}

//---------------------------------------------------------------------------
// AVP_Behaviour_Marine_Attack_Support :: CheckForCover
//---------------------------------------------------------------------------
void AVP_Behaviour_Marine_Attack_Advance::LookInThreatsArea(const float fTimeslice)
{
	if ( m_fAimTimer >= dbg_fLookTimeout )
	{
		if (GetTacticalSystem() && GetKnowledgeSystem())
		{
			Asura_Vector_3 xThreatPos( Asura_Maths::ZeroVector3 );
			GetMarineBrain()->GetThreatPos( xThreatPos );

			const Asura_Vector_3& xOurPos = GetOurActor()->GetPosition();

			float fDistance = ( xOurPos - xThreatPos ).Magnitude();
			float fAimOffsetXZ = fDistance * 0.1f;
			float fAimOffsety = fDistance * 0.01f;

#if 0
			Asura_Vector_3 xThreatPos( Asura_Maths::ZeroVector3 );

			GetMarineBrain()->GetThreatPos( xThreatPos );
#endif
			xThreatPos.x += Asura_Random::GetFloat( -fAimOffsetXZ, fAimOffsetXZ );
			xThreatPos.y += Asura_Random::GetFloat( -fAimOffsety, fAimOffsety );
			xThreatPos.z += Asura_Random::GetFloat( -fAimOffsetXZ, fAimOffsetXZ );

			GetMarineBrain()->AimAtPosition( xThreatPos );

		}
	}

	m_fAimTimer -= fTimeslice;

	if ( m_fAimTimer <= 0.0f )
	{
		m_fAimTimer = Asura_Random::GetFloat(0.3f, 0.7f);
	}
}

//---------------------------------------------------------------------------
// AVP_Behaviour_Marine_Attack_Advance :: DoesWaypointContainCoverAndItsNotOccupied
//---------------------------------------------------------------------------
bool AVP_Behaviour_Marine_Attack_Advance::DoesWaypointContainCoverAndItsNotOccupied( u_int uWaypointID )
{
	// Ensure we have a threat
	if ( !GetMarineBrain()->DoesHaveThreat() ) { return false; }

	// Ensure Our Waypoint Is Valid
	Asura_AI_NavVertex*					pxWaypoint	= Asura_AI_Navigation_System::GetWaypoint( uWaypointID );
	if ( !pxWaypoint ) { return false; }

	// Ensure Our Volume Is Valid
	AVP_ServerEntity_GamePlayVolume*	pxVolume	= AVP_ServerEntity_GamePlayVolume::GetVolumeThatContainsPosition( pxWaypoint->GetPosition() );
	if ( ( !pxVolume ) || ( pxVolume->GetNumCoverPointGuids() == 0 ) ) { return false; }

	Asura_Vector_3 xThreatPos = Asura_Maths::ZeroVector3;
	GetMarineBrain()->GetThreatPos( xThreatPos );

	// Reset the best cover point
	m_uBestCoverPoint = ASURA_GUID_UNREGISTERED;

	// Iterate around all cover points in the waypoints gameplay volume
	for ( u_int u = 0; u < pxVolume->GetNumCoverPointGuids(); ++u )
	{
		Asura_ServerNode_Coverpoint* pxCoverPoint = Asura_ServerNode_Coverpoint::FindEntity( pxVolume->GetCoverPointGuid( u ) );
		if ( !pxCoverPoint || !pxCoverPoint->IsEntityActive() || pxCoverPoint->IsOccupied() ) { continue; }

		// is the cover point in our waypoint
		if ( Asura_AI_Navigation_System::IsPositionInWaypoint( pxCoverPoint->GetPosition(), uWaypointID ) )
		{
			Asura_Vector_3 xDirToThreat = ( xThreatPos - pxCoverPoint->GetPosition() );
			float fDistanceSq = xDirToThreat.MagnitudeSquared();

			if ( fDistanceSq < 64.0f )
			{
				continue;
			}

			// Does it provide cover from our threat?
			if ( pxCoverPoint->ProvidesCoverFrom( xThreatPos ) )
			{
				// wow we have one!
				m_uBestCoverPoint = pxCoverPoint->GetGuid();
				break;
			}
		}
	}

	if ( m_uBestCoverPoint != ASURA_GUID_UNREGISTERED )
	{
		return true;
	}
	else
	{
		return false;
	}
}

//---------------------------------------------------------------------------
// AVP_Behaviour_Marine_Attack_Advance :: GetPosEvalRanges
//---------------------------------------------------------------------------
void AVP_Behaviour_Marine_Attack_Advance::GetPosEvalRanges( float* fEvaluationRange, float* fMinEngementRange, float* fMaxEngagementRange )
{
	switch ( m_uWeaponType )
	{
		case AVP_WEAPON_BEHAVIOUR_TYPE_FLAMETHROWER:
		case AVP_WEAPON_BEHAVIOUR_TYPE_PISTOL:
		case AVP_WEAPON_BEHAVIOUR_TYPE_SHOTGUN:
		{
			*fEvaluationRange		= 20.0f;
			*fMinEngementRange		= 3.0f;
			*fMaxEngagementRange	= 7.0f;

		}break;
		case AVP_WEAPON_BEHAVIOUR_TYPE_PULSERIFLE:
		{
			*fEvaluationRange		= 20.0f;
			*fMinEngementRange		= 5.0f;
			*fMaxEngagementRange	= 10.0f;

		}break;
		default:
		{
			*fEvaluationRange		= 0.0f;
			*fMinEngementRange		= 0.0f;
			*fMaxEngagementRange	= 0.0f;

		}break;
	}
}

//---------------------------------------------------------------------------
// AVP_Behaviour_Marine_Attack_Advance :: FindBestWaypoint
//---------------------------------------------------------------------------
bool AVP_Behaviour_Marine_Attack_Advance::GetMemberPositionToPosEvalAround( Asura_Vector_3 &xPosition )
{
	AVP_ServerEntity_Squad_Marine* pxSquad = GetMarineBrain()->GetMarineSquad(); // verified by brain every frame

	for ( u_int u = 0; u < pxSquad->GetNumSquadMembers(); ++u )
	{
		AVP_ServerActor_Human* pxHuman = AVP_ServerActor_Human::FindEntity( pxSquad->GetMemberGuid( u ) );

		if ( pxHuman && pxHuman->IsEntityActive() && !pxHuman->IsDead() )
		{
			if (pxHuman->GetFormationRole() == AVP_ServerActor_Human::FORMATION_ROLE_SMARTGUN ||
				pxHuman->GetFormationRole() == AVP_ServerActor_Human::FORMATION_ROLE_SUPPORT )
			{
				xPosition = pxHuman->GetPosition();
				return true;
			}
		}
	}

	return false;
}

//---------------------------------------------------------------------------
// AVP_Behaviour_Marine_Attack_Advance :: FindBestWaypoint
//---------------------------------------------------------------------------
bool AVP_Behaviour_Marine_Attack_Advance::FindBestWaypoint( AVP_Navigation::PosEvalFunctor* pxPosEval )
{
// 	AVP_Navigation::NavData& xNavData = GetMarineBrain()->GetNavData();
// 
// 	Asura_AI_NavVertex*	pxStartWaypoint	= Asura_AI_Navigation_System::GetWaypoint( xNavData.m_usCurrentWPID );
// 
// 	//float fBestPercentage = 0.0f;
// 	float fBestRouteDistanceSq = Asura_Maths::LargeFloat;
	u_int uBestWaypointID = pxPosEval->GetBestWaypointID();

// 	Asura_Vector_3 xThreatPos( Asura_Maths::ZeroVector3 );
// 	GetMarineBrain()->GetThreatPos( xThreatPos );
// 
// 	for ( u_int u = 0; u < AVP_Navigation::PosEvalFunctor::MAX_STORED_BEST_WAYPOINTS; ++u )
// 	{
// 		u_int uTestWPID = pxPosEval->GetBestWaypointID( u );
// 		Asura_AI_NavVertex*	pxTestWaypoint	= Asura_AI_Navigation_System::GetWaypoint( uTestWPID );
// 
// 		if ( pxTestWaypoint )
// 		{
// 			AVP_Navigation::NavData xTempNavData;
// 
// 			// Set the human path finding flags
// 			xTempNavData.m_uPathfinderFlags		= AVP_Navigation::AVP_AI_PATHFINDER_FLAG_HUMANOID;
// 			xTempNavData.m_eMovementMode		= AVP_Navigation::MM_SLOW;
// 			xTempNavData.m_usCurrentWPID		= xNavData.m_usCurrentWPID;
// 			xTempNavData.m_xStartPosition		= pxStartWaypoint->GetPosition();
// 			xTempNavData.m_usDestinationWPID	= (u_short)uTestWPID;
// 			xTempNavData.m_xDestinationPosition = pxTestWaypoint->GetPosition();
// 			xTempNavData.m_usCurrentZone		= pxStartWaypoint->m_usZone;
// 			xTempNavData.m_fCharacterHeight		= 2.0f;
// 			xTempNavData.m_fCharacterWidth		= 1.0f;
// 
// 			AVP_Navigation::HumanoidThreatProximityAStarFunctor xFunctor( xThreatPos );
// 			AVP_Navigation::FindRoute( xTempNavData, &xFunctor );
// 
// 			float fRouteDistanceSq = AVP_Navigation::CalculateRouteDistance( xTempNavData, pxStartWaypoint->GetPosition(), 0 );
// 			fRouteDistanceSq = fRouteDistanceSq * fRouteDistanceSq;
// 
// 			if ( fRouteDistanceSq < fBestRouteDistanceSq )
// 			{
// 				fBestRouteDistanceSq = fRouteDistanceSq;
// 				uBestWaypointID = uTestWPID;
// 			}
// 		}
// 	}

	m_uTestWp = uBestWaypointID;

	if ( uBestWaypointID != ASURA_INVALID_WAYPOINT_ID )
	{
		Asura_AI_NavVertex*	pxWaypoint	= Asura_AI_Navigation_System::GetWaypoint( uBestWaypointID );
		AVP_Tactical_System* pxTactical	= GetMarineBrain()->GetTacticalSystem();

		if ( pxWaypoint )
		{
			if ( DoesWaypointContainCoverAndItsNotOccupied( uBestWaypointID ) )
			{
				if ( m_uBestCoverPoint != ASURA_GUID_UNREGISTERED )
				{
					Asura_ServerNode_Coverpoint* pxCoverPoint = Asura_ServerNode_Coverpoint::FindEntity( m_uBestCoverPoint );
					if ( pxCoverPoint )
					{
						pxTactical->SetDestination( pxCoverPoint->GetPosition() );
						pxTactical->SetAtDestinationRange( ONE_METER );
						pxTactical->SetMovementSpeed( AVP_Navigation::MM_MEDIUM );
						pxTactical->LetRouteSetLookAt( false );
						pxTactical->OverrideSlowDownForThisDestination();
						SwitchToState( ADVANCE_MOVE_TO_COVER );
						return false;
					}
				}
			}

			float fDistanceSq = ( GetOurActor()->GetPosition() - pxWaypoint->m_xPosition ).MagnitudeSquared();

			if ( fDistanceSq > 9.0f )
			{
				pxTactical->SetDestination( pxWaypoint->m_xPosition );
				pxTactical->SetAtDestinationRange( ONE_METER );
				pxTactical->SetMovementSpeed( AVP_Navigation::MM_SLOW );
				pxTactical->LetRouteSetLookAt( false );
				pxTactical->OverrideStartMovementDelay();
				return true;
			}
		}
	}

	return false;
}

//---------------------------------------------------------------------------
// AVP_Behaviour_Marine_Attack_Advance :: GetAttackingScoreForWaypoint
//---------------------------------------------------------------------------
u_int AVP_Behaviour_Marine_Attack_Advance::EvaluationFunction( AVP_Navigation::AVP_PosEvalParams xPosEvalParams )
{
	AVP_ServerActor_Human* pxHuman = AVP_ServerActor_Human::FindEntity( xPosEvalParams.m_uActorGuid );

	u_int uScore = 0;

	// this should always be valid as he has just requested a position evaluation
	if ( !pxHuman ) { return uScore; }

	// Waypoint Proximity
	uScore += AVP_PositionEvaluation::GetProximityToThreatScore( pxHuman, xPosEvalParams.m_uTestWPID, 10.0f );
	
	AVP_Brain_Actor_Marine* pxBrain = (AVP_Brain_Actor_Marine*)pxHuman->GetActorBrain();

	if ( pxBrain )
	{
		if ( !pxBrain->GetKnowledgeSystem()->ShootAtScriptedTarget() || ( pxBrain->GetKnowledgeSystem()->ShootAtScriptedTarget() && !pxBrain->GetKnowledgeSystem()->ScriptedTargetIsShootAtPoint() ) )
		{
			// Line Of Fire To The Primary Threat
			uScore += AVP_PositionEvaluation::GetWaypointLOFtoPrimaryThreatScore( pxHuman, xPosEvalParams.m_uTestWPID, 20 );
		}
		else
		{
			uScore += AVP_PositionEvaluation::GetWaypointLOFToScriptedTarget( pxHuman, xPosEvalParams.m_uTestWPID, 20 );
		}
	}

	// Preferred Fighting Range
	uScore += AVP_PositionEvaluation::GetPreferredFightingRangeScore( pxHuman, xPosEvalParams.m_uTestWPID, xPosEvalParams.m_fMinFightingRange, xPosEvalParams.m_fMaxFightingRange, 40 );

	// Waypoint Occupied by ally
	uScore += AVP_PositionEvaluation::GetHumanoidPositionOccupiedByAllyScore( pxHuman, xPosEvalParams.m_uTestWPID, 20 );

	// Waypoint Gives no LOF from Secondary Threats
	uScore += AVP_PositionEvaluation::GetHumanoidPositionGivesCoverFromSecondaryThreatsScore( pxHuman, xPosEvalParams.m_uTestWPID, 20 );

	// Waypoint Has a cover point that provides cover from primary threat
	uScore += AVP_PositionEvaluation::GetPositionProvidesCoverFromPrimaryThreat( pxHuman, xPosEvalParams.m_uTestWPID, 20 );

	return uScore;
}

//---------------------------------------------------------------------------
// AVP_Behaviour_Marine_Attack_Advance :: SwitchToState
//---------------------------------------------------------------------------
void AVP_Behaviour_Marine_Attack_Advance::SwitchToState( UpdateState eState )
{
	switch (GetUpdateState())
	{
		//---------------------------------------------------------------------------
		case ADVANCE_MOVE_TO_COVER:
		{
			if (eState != ADVANCE_COVER)
			{
				Asura_ServerNode_Coverpoint* pxCoverPoint = Asura_ServerNode_Coverpoint::FindEntity( m_uBestCoverPoint );
				if ( pxCoverPoint )
				{
					pxCoverPoint->SetIsOccupied( false );
				}
			}
		}break;
		//---------------------------------------------------------------------------
		case ADVANCE_COVER:
		{
			DestroyChildWithType(AVP_BEHAVIOUR_TYPE_MARINE_INCOVER);
			
			m_uBestCoverPoint = ASURA_GUID_UNREGISTERED;

			Asura_ServerNode_Coverpoint* pxCoverPoint = Asura_ServerNode_Coverpoint::FindEntity( m_uBestCoverPoint );
			if ( pxCoverPoint )
			{
				pxCoverPoint->SetIsOccupied( false );
			}

		}break;
		//---------------------------------------------------------------------------
		case UNSET:
		default:
		{

		}
	}

	SetUpdateState( eState );

	switch (GetUpdateState())
	{
		//---------------------------------------------------------------------------
		case ADVANCE_MOVE_TO_COVER:
		{
			// Create the cover behaviour and set the cover point
			Asura_ServerNode_Coverpoint* pxCoverPoint = Asura_ServerNode_Coverpoint::FindEntity( m_uBestCoverPoint );
			if ( pxCoverPoint )
			{
				pxCoverPoint->SetIsOccupied( true );
			}

		}break;
		//---------------------------------------------------------------------------
		case ADVANCE_COVER:
		{
			// Create the cover behaviour and set the cover point
			AVP_Behaviour_Marine_InCover* pxCoverBehaviour = ( AVP_Behaviour_Marine_InCover* )CreateChildWithType( AVP_BEHAVIOUR_TYPE_MARINE_INCOVER );

			if ( pxCoverBehaviour )
			{
				pxCoverBehaviour->SetCoverPoint( m_uBestCoverPoint );
			}

		}break;
		case ADVANCE_CHOOSE:
		{
			m_fTimer = 0.0f;

		}break;

		case ADVANCE_MOVE:
		{
			m_fTimer = Asura_Random::GetFloat( 3.7f, 5.2f );

		}break;

		case UNSET:
		default:
		{

		}
	}
}

//---------------------------------------------------------------------------
// AVP_Behaviour_Marine_Attack_Advance :: RenderDebugInfo
//---------------------------------------------------------------------------
#ifndef ASURA_NO_DEBUG_OUTPUT
static const char* s_aszStateStrings[ AVP_Behaviour_Marine_Attack_Advance::MAX_STATES ] =
{
	"ATTACK_ADVANCE - UNSET",
	"ATTACK_ADVANCE - CHOOSE",
	"ATTACK_ADVANCE - MOVE",
	"ATTACK_ADVANCE - MOVE TO COVER",
	"ATTACK_ADVANCE - COVER",
};

#include "Core/AVP_Navigation_Types.h"
#include "Debugging/Asura_DebugLineRender.h"

void AVP_Behaviour_Marine_Attack_Advance::RenderDebugInfo( void )
{
	PARENT::RenderDebugInfo();

	Asura_Font_System::Print
	(
		GetProjectBrain()->GetDebugOutputPos().x,
		GetProjectBrain()->GetDebugOutputPos().y,
		0.5f, 
		0XFFFFFFFF,
		ASURA_TEXTFORMAT_CENTREJUSTIFIED, 
		s_aszStateStrings[GetUpdateState()]
	);

	if ( m_uTestWp != ASURA_INVALID_WAYPOINT_ID )
	{
		Asura_AI_NavVertex* pxWP = Asura_AI_Navigation_System::GetWaypoint( m_uTestWp );
		
		Asura_DebugLineRender::AddSphere(pxWP->GetPosition(), 0.5f, 0xffffffff, 8, 4);
	}

#if defined(_DEBUG) && !defined(ASURA_NO_DEBUG_OUTPUT)
	//AVP_Navigation::PosEvalFunctor::RenerWpInfo();
#endif

	// Offset the debug output position for other behaviours to render there own text
	GetProjectBrain()->GetDebugOutputPos().y += 10.0f;
}
#endif

/// End Of File 'AVP_behaviour_Marine_Attack_Advance.cpp'
