
///////////////////////////////////////////////////////////////////////////////
//
// File   : AVP_Predator_HUDHandler.cpp
// Author : Andy Tate
// Date   : 16-Oct-2006
//
// Copyright (C) 2006 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Include files...
////////////////////////////////////////////////////////////////////////////////

#include "Core/Asura.h"

// This file's header...
#include "AVP_Predator_HUDHandler.h"

// asura
#include "Animation/Asura_Animation.h"
#include "Blueprint/Asura_Blueprint_System.h"
#include "Core/Asura_TiledTextureManagement.h"
#include "Core/Asura_Timers.h"
#include "GUIMenu/Asura_GUIMenu_Element_Image.h"
#include "Rendering/Asura_Font_System.h"
#include "Rendering/Asura_Viewport.h"
#include "FSFX/Asura_FSFX_System.h"
#include "Network/Asura_Message.h"

// Game header-files...
#include "Actor/Vertebrates/AVP_Vertebrate_Description.h"
#include "Actor/Vertebrates/AVP_Vertebrate_Focus.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_AnimationHandler.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_CameraHandler.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_Focus.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_InputHandler.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_LockOn.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_Recon.h"
#include "Animation/AVP_AnimFlags.h"
#include "Blueprint/AVP_Blueprint_HashIDs.h"
#include "Entity/PhysicalObject/Actor/AVP_ServerEntity_Actor.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Human/AVP_ServerActor_Human.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Predator/AVP_ClientActor_Predator.h"
#include "Inventory/AVP_AmmoStore.h"
#include "Inventory/AVP_Inventory_Item.h"
#include "Inventory/AVP_Inventory_System.h"
#include "Inventory/AVP_Inventory_HashIDs.h"
#include "Inventory/AVP_InventoryItem_SubType.h"
#include "Inventory/Items/AVP_InventoryItem_VisionMode.h"
#include "Moves/AVP_Movement_System.h"
#include "Rendering/AVP_Overlay_Render.h"

////////////////////////////////////////////////////////////////////////////////
// Global variable declarations...
////////////////////////////////////////////////////////////////////////////////

#define HUD_SHOWVISIONSELECTOR	L"AVP.HUD.ShowVisionSelector"

#define HUD_SHOWENERGY1			L"AVP.HUD.ShowEnergy1"
#define HUD_SHOWENERGY2			L"AVP.HUD.ShowEnergy2"
#define HUD_SHOWENERGY3			L"AVP.HUD.ShowEnergy3"
#define HUD_SHOWENERGY4			L"AVP.HUD.ShowEnergy4"
#define HUD_SHOWENERGY5			L"AVP.HUD.ShowEnergy5"
#define HUD_ENERGY1PARAMETRIC	L"AVP.HUD.Energy1Parametric"
#define HUD_ENERGY2PARAMETRIC	L"AVP.HUD.Energy2Parametric"
#define HUD_ENERGY3PARAMETRIC	L"AVP.HUD.Energy3Parametric"
#define HUD_ENERGY4PARAMETRIC	L"AVP.HUD.Energy4Parametric"
#define HUD_ENERGY5PARAMETRIC	L"AVP.HUD.Energy5Parametric"

#define HUD_SHOWZOOM1			L"AVP.HUD.ShowZoom1"
#define HUD_SHOWZOOM2			L"AVP.HUD.ShowZoom2"
#define HUD_SHOWZOOM3			L"AVP.HUD.ShowZoom3"

#define HUD_RECONACTIVE			L"ReconMode.Active"
#define HUD_RECONPLAYING		L"ReconMode.PlayingLureSound"

#define HUD_HASFOCUSTARGET		L"AVP.HUD.HasFocusModeInfoTarget"

#define HUD_TARGET_SPECIES		L"AVP.HUD.PredTargetInfo.Species"
#define HUD_TARGET_WEAPON		L"AVP.HUD.PredTargetInfo.Weapon"
#define HUD_TARGET_THREATNEAR	L"AVP.HUD.PredTargetInfo.ThreatNear"
#define HUD_TARGET_THREATFAR	L"AVP.HUD.PredTargetInfo.ThreatFar"
#define HUD_TARGET_TRACKER		L"AVP.HUD.PredTargetInfo.MotionTracker"
#define HUD_TARGET_SENCES		L"AVP.HUD.PredTargetInfo.HighSences"

#define HUD_VISIONMODE			L"AVP.HUD.Predator.VisionMode"

#define HUD_AMMO				L"AVP.HUD.Predator.PrimaryAmmo"

// simply here to give meaning to integers used to signify information, allows easily readable code
enum PRED_TARGET_SPECIES
{
	PTS_SPECIES_INVALID = -1,

	PTS_ALIEN,
	PTS_HUMAN,
	PTS_PREDATOR,
	PTS_SYNTHETIC,
	PTS_MECHANICAL,
	PTS_ALIEN_PREDATOR,

	PTS_NUM_SPECIES
};

// simply here to give meaning to integers used to signify information, allows easily readable code
enum PRED_TARGET_WEAPONS
{
	PTW_WEAPON_INVALID = -1,

	PTW_PISTOL,
	PTW_PULSE_RIFLE,
	PTW_SHOTGUN,
	PTW_FLAMETHROWER,
	PTW_SCOPED_RIFLE,
	PTW_SMART_GUN,
	PTW_WRIST_BLADES,
	PTW_MINES,
	PTW_PLASMA_CASTER,
	PTW_DISC,
	PTW_CLAWS,
	PTW_UNARMED,
	PTW_MISSLE_LAUNCHER,
	PTW_ACID_SPIT,

	PTW_NUM_WEAPONS
};

// simply here to give meaning to integers used to signify information, allows easily readable code
enum PRED_TARGET_THREATLEVEL
{
	PTTL_THREAT_INVALID = -1,

	PTTL_NONE,
	PTTL_LOW,
	PTTL_MEDIUM,
	PTTL_HIGH,
	PTTL_EXTREAM,

	PTTL_NUM_THREATS
};

////////////////////////////////////////////////////////////////////////////////
// Static variable declarations...
////////////////////////////////////////////////////////////////////////////////

#define AVP_PRED_HUD_NUM_TICKER_TYPES ( AVP_GUIMenu_System::END_TICKER - AVP_GUIMenu_System::BEGIN_TICKER )
#define AVP_PRED_HUD_NUM_ON_SCREEN_TICKERS 18
#define AVP_PRED_HUD_NUM_OFF_SCREEN_TICKERS ( AVP_PRED_HUD_NUM_TICKER_TYPES - AVP_PRED_HUD_NUM_ON_SCREEN_TICKERS )

bool  AVP_Predator_HUDHandler::s_bShowVisionSelector = false;
bool  AVP_Predator_HUDHandler::s_bShowEnergy[ MAX_HUD_ENERGY_ELEMENTS ];
float AVP_Predator_HUDHandler::s_fEnergyParametric[ MAX_HUD_ENERGY_ELEMENTS ];
bool  AVP_Predator_HUDHandler::s_bLeapPointInRange = false;
bool  AVP_Predator_HUDHandler::s_bReconTargetAvailable = false;
bool  AVP_Predator_HUDHandler::s_bReconTargetSelected = false;
bool  AVP_Predator_HUDHandler::s_bShowZoom[ AVP_CAMERA_NUM_ZOOM_LEVELS - 1 ];
bool  AVP_Predator_HUDHandler::s_bShowRecon = false;
float AVP_Predator_HUDHandler::s_fShowReconSound = 0.0f;
int	  AVP_Predator_HUDHandler::s_iAmmoCounter;
int	  AVP_Predator_HUDHandler::s_iCurrentVisionMode;
float AVP_Predator_HUDHandler::s_fHasFocusInfoTarget = 0.0f;
PredHudTargetInfo AVP_Predator_HUDHandler::s_xTargetInfo = { PTS_SPECIES_INVALID, PTW_WEAPON_INVALID, PTTL_THREAT_INVALID, PTTL_THREAT_INVALID, false, false };


DEBUGVAR float			dbg_fEpsilon		= 0.001f;
DEBUGVAR float			dbg_fTickerTimer	= 1.0f;

static bool				g_bFirstFrame = false;
static bool				g_bSecondFrame = false;
static Asura_Vector_2	g_axTickerPos[ AVP_PRED_HUD_NUM_ON_SCREEN_TICKERS ];
static u_int			g_auOnScreenTickers[ AVP_PRED_HUD_NUM_ON_SCREEN_TICKERS ];
static u_int			g_auOffScreenTickers[ AVP_PRED_HUD_NUM_OFF_SCREEN_TICKERS ];

AVP_Predator_HUDHandler::AVP_Predator_HUDHandler (AVP_ClientEntity_Actor& xClient)
: PARENT(xClient)
, m_xNoEnergyPos( Asura_Maths::ZeroVector2 )
, m_xFullEnergyPos( Asura_Maths::ZeroVector2 )
, m_uMaxNumEnergyBlocks( 5 )
, m_fEnergyPerBlock( 20.0f )
, m_fTickerPhase( 0.0f )
, m_iTargetedJumpSoundHandle(ASURA_INVALID_HANDLE)
, m_iTargetInfoSoundLoopHandle(ASURA_INVALID_HANDLE)
, m_fHudInfoStickTime( 1.0f )
, m_fHudInfoStickCounter( 0.0f )
{
	Asura_Blueprint* pxActorBP = Asura_Blueprint_System::GetBlueprintByHashID( uAVP_BLUEPRINT_TYPE_ACTORS, xClient.GetBlueprintHashID() );
	if ( pxActorBP )
	{
		Asura_Value xValue;
		if ( pxActorBP->GetParameterValueByHashID( uAVP_BLUEPRINT_PARAM_NUMENERGYBLOCKS, xValue ) )
		{
			m_uMaxNumEnergyBlocks = xValue.GetIntValue();
		}
		if ( pxActorBP->GetParameterValueByHashID( uAVP_BLUEPRINT_PARAM_ENERGY, xValue ) )
		{
			m_fEnergyPerBlock = xValue.GetFloatValue() / m_uMaxNumEnergyBlocks;
		}
	}

	Asura_Blueprint* pxPlayerBP = Asura_Blueprint_System::GetBlueprintByHashID( uAVP_BLUEPRINT_TYPE_PLAYERS, xClient.GetBlueprintHashID() );
	if( pxPlayerBP )
	{
		Asura_Value xValue;
		if( pxPlayerBP->GetParameterValueByHashID( uAVP_BLUEPRINT_PARAM_PREDHUD_INFO_STICKTIME, xValue ) )
		{
			m_fHudInfoStickTime = xValue.GetFloatValue();
		}
	}

	for(u_int uZoomItr = 0; uZoomItr < AVP_CAMERA_NUM_ZOOM_LEVELS - 1; uZoomItr++)
	{
		s_bShowZoom[ uZoomItr ] = false;
	}

	// reset static variables incase this is not the first time the HUD handler has been declared on this running. 
	g_bFirstFrame = true;
	g_bSecondFrame = false;
	s_bShowRecon = false;
	s_fShowReconSound = 0.0f;
	s_iAmmoCounter = 0;
	s_iCurrentVisionMode = 0;
	s_fHasFocusInfoTarget = 0.0f;

	SetTargetInfo( PTS_SPECIES_INVALID, PTW_WEAPON_INVALID, PTTL_THREAT_INVALID, PTTL_THREAT_INVALID, false, false );
}

#if defined(ASURA_SUPPORT_COMMAND_CONSOLE)
void AVP_Predator_HUDHandler::CreateConsoleVars()
{
	Asura_CommandConsole::AddVar( HUD_SHOWVISIONSELECTOR, &s_bShowVisionSelector, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_SHOWVISIONSELECTOR );

	Asura_CommandConsole::AddVar( HUD_SHOWENERGY1, &s_bShowEnergy[ 0 ], Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_SHOWENERGY1 );

	Asura_CommandConsole::AddVar( HUD_SHOWENERGY2, &s_bShowEnergy[ 1 ], Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_SHOWENERGY2 );

	Asura_CommandConsole::AddVar( HUD_SHOWENERGY3, &s_bShowEnergy[ 2 ], Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_SHOWENERGY3 );

	Asura_CommandConsole::AddVar( HUD_SHOWENERGY4, &s_bShowEnergy[ 3 ], Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_SHOWENERGY4 );

	Asura_CommandConsole::AddVar( HUD_SHOWENERGY5, &s_bShowEnergy[ 4 ], Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_SHOWENERGY5 );

	Asura_CommandConsole::AddVar( HUD_ENERGY1PARAMETRIC, &s_fEnergyParametric[ 0 ], 0.0f, 1.0f, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_ENERGY1PARAMETRIC );

	Asura_CommandConsole::AddVar( HUD_ENERGY2PARAMETRIC, &s_fEnergyParametric[ 1 ], 0.0f, 1.0f, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_ENERGY2PARAMETRIC );

	Asura_CommandConsole::AddVar( HUD_ENERGY3PARAMETRIC, &s_fEnergyParametric[ 2 ], 0.0f, 1.0f, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_ENERGY3PARAMETRIC );

	Asura_CommandConsole::AddVar( HUD_ENERGY4PARAMETRIC, &s_fEnergyParametric[ 3 ], 0.0f, 1.0f, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_ENERGY4PARAMETRIC );

	Asura_CommandConsole::AddVar( HUD_ENERGY5PARAMETRIC, &s_fEnergyParametric[ 4 ], 0.0f, 1.0f, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_ENERGY5PARAMETRIC );

	Asura_CommandConsole::AddVar( HUD_SHOWZOOM1, &s_bShowZoom[ 0 ], Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_SHOWZOOM1 );

	Asura_CommandConsole::AddVar( HUD_SHOWZOOM2, &s_bShowZoom[ 1 ], Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_SHOWZOOM2 );

	Asura_CommandConsole::AddVar( HUD_SHOWZOOM3, &s_bShowZoom[ 2 ], Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_SHOWZOOM3 );

	Asura_CommandConsole::AddVar( HUD_RECONACTIVE, &s_bShowRecon, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_RECONACTIVE );

	Asura_CommandConsole::AddVar( HUD_RECONPLAYING, &s_fShowReconSound, 0.0f, 1.0f, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_RECONPLAYING );

	Asura_CommandConsole::AddVar( HUD_HASFOCUSTARGET, &s_fHasFocusInfoTarget, 0.0f, 1.0f, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_HASFOCUSTARGET );

	Asura_CommandConsole::AddVar( HUD_TARGET_SPECIES, &s_xTargetInfo.m_iSpecies, 0, 5, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_TARGET_SPECIES );

	Asura_CommandConsole::AddVar( HUD_TARGET_WEAPON, &s_xTargetInfo.m_iWeapon, 0, 13, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_TARGET_WEAPON );

	Asura_CommandConsole::AddVar( HUD_TARGET_THREATNEAR, &s_xTargetInfo.m_iThreatNear, 0, 4, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_TARGET_THREATNEAR );

	Asura_CommandConsole::AddVar( HUD_TARGET_THREATFAR, &s_xTargetInfo.m_iThreatFar, 0, 4, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_TARGET_THREATFAR );

	Asura_CommandConsole::AddVar( HUD_TARGET_TRACKER, &s_xTargetInfo.m_bMotionTracker, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_TARGET_TRACKER );

	Asura_CommandConsole::AddVar( HUD_TARGET_SENCES, &s_xTargetInfo.m_bHieghtenedSences, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_TARGET_SENCES );

	Asura_CommandConsole::AddVar( HUD_VISIONMODE, &s_iCurrentVisionMode, 0, 3, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_VISIONMODE );

	Asura_CommandConsole::AddVar( HUD_AMMO, &s_iAmmoCounter, INT_MIN, INT_MAX, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );

	Asura_CommandConsole::AddVar( L"AVP.HUD.LeapPointInRange", &s_bLeapPointInRange, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( L"AVP.HUD.LeapPointInRange" );

	Asura_CommandConsole::AddVar( L"AVP.PredatorPlayer.ReconTargetAvailable", &s_bReconTargetAvailable, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( L"AVP.PredatorPlayer.ReconTargetAvailable" );

	Asura_CommandConsole::AddVar( L"AVP.PredatorPlayer.ReconTargetSelected", &s_bReconTargetSelected, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( L"AVP.PredatorPlayer.ReconTargetSelected" );	

	AVP_Predator_LockOn::CreateConsoleVars();
}
#endif

AVP_Predator_HUDHandler::~AVP_Predator_HUDHandler () 
{
	StopSoundEvent( m_iTargetedJumpSoundHandle );
	StopSoundEvent( m_iTargetInfoSoundLoopHandle );
}

void AVP_Predator_HUDHandler::Update ( const AVP_ClientEntity_Actor& xClient )
{
	PARENT::Update( xClient );

	//Grab the player values by guid.
	const AVP_ClientActor_Predator& xPredator = static_cast< const AVP_ClientActor_Predator& >( xClient );

	Asura_Guid uGuidOfTargetForInfo = ASURA_GUID_UNREGISTERED;
	
	//UpdateTickers();
	UpdateEnergy( xPredator );
	UpdateAmmo( xPredator );
	UpdateVisionMode( xPredator );

	// CAH needed to make sure FULL updates are carried out on hud elements the first two frames after any change. 
	// This is because the HUDHandler is updated before the GUI Hud itself, 
	// meaning that if the HUD is going to be auto resized the positions of the elements will not be final until the second frame here. 
	// I cant just change the update order because that is Asura code. 
	if( g_bFirstFrame )
	{
		g_bSecondFrame = true;
		g_bFirstFrame = false;
	}
	else if( g_bSecondFrame )
	{
		g_bSecondFrame = false;
	}

	s_bShowRecon = AVP_Predator_Recon::GetRecon().GetReconIsActive();

	// recon sound playing if a folat so the HUD can use the var to run animators. 
	if( AVP_Predator_Recon::GetRecon().GetDistractionSoundPlaying() )
	{
		s_fShowReconSound = 1.0f;
	}
	else
	{
		s_fShowReconSound = 0.0f;
	}

	uGuidOfTargetForInfo = GetPotentialPrey();

	if( xPredator.GetFocusActive() 
		&& uGuidOfTargetForInfo != ASURA_GUID_UNREGISTERED
		&& ! AVP_Predator_Recon::GetRecon().GetReconIsActive() )
	{
		UpdateTargetInfo( uGuidOfTargetForInfo );
		if( s_fHasFocusInfoTarget != 1.0f )
		{
			OnBeginTargetInfo();
		}
		m_fHudInfoStickCounter = m_fHudInfoStickTime;
	}
	else
	{
		if( AVP_Predator_Recon::GetRecon().GetReconIsActive() && s_fHasFocusInfoTarget == 1.0f )
		{
			// if recon mode is active and info is showing end it immediatly. 
			OnEndTargetInfo();
		}
		else if( m_fHudInfoStickCounter >= 0.0f )
		{
			// if the info stick counter is above 0 then take the time of the last frame away from it. 
			m_fHudInfoStickCounter -= Asura_Timers::GetPreviousFrameTime();
		}
		else
		{
			// if the counter has reached 0 then end Target info mode if it is not already off. 
			if( s_fHasFocusInfoTarget != 0.0f )
			{
				OnEndTargetInfo();
			}
		}
	}

	if( xPredator.GetFocusActive() )
	{
		AVP_Actor_HUDHandler::SetHUDEnergyState( AVP_Actor_HUDHandler::HUD_USE_FOCUS );
		AVP_Actor_HUDHandler::SetHUDHealthState( AVP_Actor_HUDHandler::HUD_USE_FOCUS );
	}
}

void AVP_Predator_HUDHandler::UpdateTickers()
{
	// init ticker position - got to do all this in the update as the stupid GUIMenu system messes it all up otherwise
	if ( g_axTickerPos[ 0 ] == Asura_Maths::ZeroVector2 )
	{
		for ( u_int uItr = 0; uItr < AVP_PRED_HUD_NUM_ON_SCREEN_TICKERS; ++uItr )
		{
			g_auOnScreenTickers[ uItr ] = uItr;
			Asura_GUIMenu_Element_Image* pxImageItem = static_cast< Asura_GUIMenu_Element_Image* >( AVP_GUIMenu_System::GetHUDElement( static_cast < AVP_GUIMenu_System::STORED_WIDGETS >( AVP_GUIMenu_System::BEGIN_TICKER + uItr ) ) );
			if ( pxImageItem )
			{
				g_axTickerPos[ uItr ] = pxImageItem->GetScaledWorldPos();
			}
		}
		for ( u_int uItr = 0; uItr < AVP_PRED_HUD_NUM_OFF_SCREEN_TICKERS; ++uItr )
		{
			g_auOffScreenTickers[ uItr ] = AVP_PRED_HUD_NUM_ON_SCREEN_TICKERS + uItr;
		}
	}
	else if ( g_bFirstFrame ) // this is the case upon restarts
	{
		// if we have valid positions ( after a restart when the icons have been jigged about )
		for ( u_int uItr = 0; uItr < AVP_PRED_HUD_NUM_ON_SCREEN_TICKERS; ++uItr )
		{
			// make on screen tickers visible and move to right location
			Asura_GUIMenu_Element_Image* pxImageItem = static_cast< Asura_GUIMenu_Element_Image* >( AVP_GUIMenu_System::GetHUDElement( static_cast < AVP_GUIMenu_System::STORED_WIDGETS >( AVP_GUIMenu_System::BEGIN_TICKER + g_auOnScreenTickers [ uItr ] ) ) );
			if ( pxImageItem )
			{
				Asura_Bounding_Rectangle xBounds(pxImageItem->GetScaledWorldBounds());
				xBounds.Displace(g_axTickerPos[ uItr ] - xBounds.GetTopLeft());
				pxImageItem->SetScaledWorldBounds( xBounds );
				Asura_RGBA xColour = pxImageItem->GetColour();
				xColour.m_fA = 1.0f;
				pxImageItem->SetColour( xColour );
			}
		}

		for ( u_int uItr = 0; uItr < AVP_PRED_HUD_NUM_OFF_SCREEN_TICKERS; ++uItr )
		{
			// make off screen tickers invisible
			Asura_GUIMenu_Element_Image* pxImageItem = static_cast< Asura_GUIMenu_Element_Image* >( AVP_GUIMenu_System::GetHUDElement( static_cast < AVP_GUIMenu_System::STORED_WIDGETS >( AVP_GUIMenu_System::BEGIN_TICKER + g_auOffScreenTickers[ uItr ] ) ) );
			if ( pxImageItem )
			{
				Asura_RGBA xColour = pxImageItem->GetColour();
				xColour.m_fA = 0.0f;
				pxImageItem->SetColour( xColour );
			}
		}
	}
	else if ( g_bSecondFrame )
	{
		// if this is the second frame double check the element positions, if the page was resized they will be different. 
		for ( u_int uItr = 0; uItr < AVP_PRED_HUD_NUM_ON_SCREEN_TICKERS; ++uItr )
		{
			g_auOnScreenTickers[ uItr ] = uItr;
			Asura_GUIMenu_Element_Image* pxImageItem = static_cast< Asura_GUIMenu_Element_Image* >( AVP_GUIMenu_System::GetHUDElement( static_cast < AVP_GUIMenu_System::STORED_WIDGETS >( AVP_GUIMenu_System::BEGIN_TICKER + uItr ) ) );
			if ( pxImageItem )
			{
				g_axTickerPos[ uItr ] = pxImageItem->GetScaledWorldPos();
			}
		}
		for ( u_int uItr = 0; uItr < AVP_PRED_HUD_NUM_OFF_SCREEN_TICKERS; ++uItr )
		{
			g_auOffScreenTickers[ uItr ] = AVP_PRED_HUD_NUM_ON_SCREEN_TICKERS + uItr;
		}
	}

	if ( m_fTickerPhase > dbg_fTickerTimer )
	{
		// pick a ticker which is on screen
		u_int uOnScreenTickerIndex = Asura_Random::GetIntU( 0, AVP_PRED_HUD_NUM_ON_SCREEN_TICKERS - 1 );
		u_int uOnScreenTicker = g_auOnScreenTickers[ uOnScreenTickerIndex ];
		// and one which isn't
		u_int uOffScreenTickerIndex = Asura_Random::GetIntU( 0, AVP_PRED_HUD_NUM_OFF_SCREEN_TICKERS - 1 );
		u_int uOffScreenTicker = g_auOffScreenTickers[ uOffScreenTickerIndex ];

		// and swap them over
		g_auOnScreenTickers[ uOnScreenTickerIndex ] = uOffScreenTicker;
		g_auOffScreenTickers[ uOffScreenTickerIndex ] = uOnScreenTicker;

		// make old off screen ticker visible and move to right location
		Asura_GUIMenu_Element_Image* pxImageItem = static_cast< Asura_GUIMenu_Element_Image* >( AVP_GUIMenu_System::GetHUDElement( static_cast < AVP_GUIMenu_System::STORED_WIDGETS >( AVP_GUIMenu_System::BEGIN_TICKER + uOffScreenTicker ) ) );
		if ( pxImageItem )
		{
			Asura_Bounding_Rectangle xBounds(pxImageItem->GetScaledWorldBounds());
			xBounds.Displace(g_axTickerPos[ uOnScreenTickerIndex ] - xBounds.GetTopLeft());
			pxImageItem->SetScaledWorldBounds( xBounds );
			Asura_RGBA xColour = pxImageItem->GetColour();
			xColour.m_fA = 1.0f;
			pxImageItem->SetColour( xColour );
		}

		// make old on screen ticker invisible
		pxImageItem = static_cast< Asura_GUIMenu_Element_Image* >( AVP_GUIMenu_System::GetHUDElement( static_cast < AVP_GUIMenu_System::STORED_WIDGETS >( AVP_GUIMenu_System::BEGIN_TICKER + uOnScreenTicker ) ) );
		if ( pxImageItem )
		{
			Asura_RGBA xColour = pxImageItem->GetColour();
			xColour.m_fA = 0.0f;
			pxImageItem->SetColour( xColour );
		}

		m_fTickerPhase = 0.0f;
	}
	m_fTickerPhase += Asura_Timers::GetGameTimeSlice();
}

void AVP_Predator_HUDHandler::UpdateEnergy( const AVP_ClientActor_Predator& xPredator )
{
	//Update energy bar
	float fEnergy = xPredator.GetDynamicEnergy()->GetCurrentValue();

	// Check for changes in energy and update hud state if it has.
	if( m_fPreviousEnergy != fEnergy )
	{
		if( m_fPreviousEnergy > fEnergy )
		{
			SetHUDEnergyState( HUD_STAT_LOSS );
		}
		else
		{
			SetHUDEnergyState( HUD_STAT_GAIN );
		}
		m_fPreviousEnergy = fEnergy;
	}

	Asura_Assertf( m_uMaxNumEnergyBlocks <= MAX_HUD_ENERGY_ELEMENTS, ( "MAX_HUD_ENERGY_ELEMENTS not big enough for entity %d who wants %d blocks", MAX_HUD_ENERGY_ELEMENTS, xPredator.GetGuid(), m_uMaxNumEnergyBlocks ) );
	float fEnergyParametric = fEnergy / m_fEnergyPerBlock;
	Asura_Assertf( fEnergyParametric - dbg_fEpsilon <= m_uMaxNumEnergyBlocks, ( "Player doesn't have enough energy blocks to have %.0f energy", fEnergy ) );
	u_int uFullBlocks = Asura_Maths::FloatToInt_Chop( fEnergyParametric );
	fEnergyParametric -= uFullBlocks;
	for ( u_int uItr = 0; uItr < MAX_HUD_ENERGY_ELEMENTS; ++uItr )
	{
		s_bShowEnergy[ uItr ] = uItr < m_uMaxNumEnergyBlocks;
		if ( uItr < uFullBlocks )
		{
			s_fEnergyParametric[ uItr ] = 1.0f;
		}
		else if ( uItr == uFullBlocks )
		{
			s_fEnergyParametric[ uItr ] = fEnergyParametric;
		}
		else
		{
			s_fEnergyParametric[ uItr ] = 0.0f;
		}
	}

	// Get start and end position of energy pointer
// 	if ( m_xNoEnergyPos == Asura_Maths::ZeroVector2 || g_bSecondFrame )
// 	{
// 		Asura_GUIMenu_Element_Image* pxImageItem = static_cast<Asura_GUIMenu_Element_Image*>(AVP_GUIMenu_System::GetHUDElement( AVP_GUIMenu_System::ENERGY_POINTER_EMPTY ) );
// 		if ( pxImageItem )
// 		{
// 			m_xNoEnergyPos = pxImageItem->GetScaledWorldPos();
// 		}
// 		pxImageItem = static_cast<Asura_GUIMenu_Element_Image*>(AVP_GUIMenu_System::GetHUDElement( AVP_GUIMenu_System::ENERGY_POINTER_FULL ) );
// 		if ( pxImageItem )
// 		{
// 			m_xFullEnergyPos = pxImageItem->GetScaledWorldPos();
// 		}
// 	}
// 
// 	// update energy pointer
// 	Asura_GUIMenu_Element_Image* pxImageItem = static_cast<Asura_GUIMenu_Element_Image*>(AVP_GUIMenu_System::GetHUDElement( AVP_GUIMenu_System::ENERGY_POINTER ) );
// 	if( pxImageItem )
// 	{
// 		Asura_Vector_2 xEnergyPos;
// 
// 		xEnergyPos = m_xFullEnergyPos * (fEnergy / xPredator.GetMaxEnergy());
// 		xEnergyPos += m_xNoEnergyPos * (1.0f - fEnergy / xPredator.GetMaxEnergy());
// 		Asura_Bounding_Rectangle xBounds(pxImageItem->GetScaledWorldBounds());
// 		xBounds.Displace(xEnergyPos - xBounds.GetTopLeft());
// 		pxImageItem->SetScaledWorldBounds( xBounds );
// 	}
}

void AVP_Predator_HUDHandler::UpdateAmmo( const AVP_ClientActor_Predator& xPredator )
{
	const AVP_Inventory_System* pxSystem = xPredator.GetInventorySystem();
	if(pxSystem)
	{
		const AVP_Inventory_Item* pxItem = pxSystem->GetCurrentItem(uAVP_INVENTORY_GROUPHASH_WEAPON);
		if(pxItem)
		{
			if(pxItem->GetNumSubTypes() > 0) // if we have a subtype...
			{
				if(pxItem->GetSubType(0)) // get the first one
				{
					float fAmmoInGun = pxItem->GetSubType(0)->GetCurrentQuantity();
					float fAmmoStored = pxSystem->GetAmmoStore()->GetAmmoQuantity(pxItem->GetSubType(0)->GetAmmoType());

					s_iAmmoCounter = Asura_Maths::FloatToInt(fAmmoStored + fAmmoInGun);
					return;
				}
			}
		}
	}
	s_iAmmoCounter = 0; // If we don't have the spear gun assume its 0
}

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Predator_HUDHandler::UpdateVisionMode
// Scope		: Private 
// Author       : Callum Hope
// Date         : 21-Jan-2009
//
// Desc			: Per frame update to record the current vision mode used by the predator
//				  Sets member variable s_iCurrentVisionMode which is used for display conditions on the HUD
//				  0 - Normal, 1 - Heat, 2 - Alien, 3 - Tech
//				  Because each mode is and inventory item (and none are named in code) the highest multiplier is used to indicate the current mode. 
////////////////////////////////////////////////////////////////////////////////

void AVP_Predator_HUDHandler::UpdateVisionMode( const AVP_ClientActor_Predator& xPredator )
{
	// first get the Inventory system for the predator being updated
	const AVP_Inventory_System* pxInventory = xPredator.GetInventorySystem();

	// now get the current visionmode being used.
	const AVP_InventoryItem_VisionMode* pxVision = pxInventory != NULL ? static_cast<const AVP_InventoryItem_VisionMode*>( pxInventory->GetCurrentItem( uAVP_INVENTORY_GROUPHASH_VISIONMODE ) ) : NULL;
	
	if( pxVision )
	{
		// now get all of the multipliers for this vision mode, the largest one will tell us the mode. 
		float fHeatVision = pxVision->GetVisionModeMultiplier( static_cast<AVP_ENTITY_CLASSIFICATION>( AVP_ENTITYCLASS_MARINE ) );
		float fAlienVision = pxVision->GetVisionModeMultiplier( static_cast<AVP_ENTITY_CLASSIFICATION>( AVP_ENTITYCLASS_ALIEN ) );
		float fTechVision = pxVision->GetVisionModeMultiplier( static_cast<AVP_ENTITY_CLASSIFICATION>( AVP_ENTITYCLASS_ANDROID ) );

		if( ( fHeatVision > fAlienVision ) && ( fHeatVision > fTechVision ) )
		{
			// if heat vision is bigger than both others this is active, assign and return. 
			s_iCurrentVisionMode = 1;
		}
		else if( ( fAlienVision > fHeatVision ) && ( fAlienVision > fTechVision ) )
		{
			s_iCurrentVisionMode = 2;
		}
		else if( ( fTechVision > fHeatVision ) && ( fTechVision > fAlienVision ) )
		{
			s_iCurrentVisionMode = 3;
		}
		else
		{
			s_iCurrentVisionMode = 0;
		}
	}
	else
	{
		// if we didnt get a vision mode then set the current mode to Normal by default. 
		s_iCurrentVisionMode = 0;
	}
}

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Predator_HUDHandler::UpdateTargetInfo
// Scope		: Private 
// Author       : Callum Hope
// Date         : 22-April-2009
//
// Desc			: Logic to update information about current melee targets. 
//				  Only called from the per frame update funciton if we are in focus mode and have a target highlighted. 
////////////////////////////////////////////////////////////////////////////////

void AVP_Predator_HUDHandler::UpdateTargetInfo( Asura_Guid uGuidOfTarget )
{
	//Asura_Guid uTargetGuid = xPredator.GetFocus()->GetMeleeTarget();
	Asura_Guid uTargetGuid = uGuidOfTarget;

	if( uTargetGuid != ASURA_GUID_UNREGISTERED )
	{
		AVP_ServerEntity_Actor* pxTargetEntity = AVP_ServerEntity_Actor::FindEntity( uTargetGuid );

		if( pxTargetEntity )
		{
			int iSpecies = PTS_SPECIES_INVALID;
			bool bTracker = false;
			bool bSences = false;

			// CW - Aliens / Civilians may not have a weapon, adding NULL checks
			AVP_Inventory_System* pxSystem = pxTargetEntity->GetInventorySystem();
			AVP_Inventory_Item* pxWeaponItem = ( pxSystem )?pxSystem->GetCurrentItem( uAVP_INVENTORY_GROUPHASH_WEAPON ):NULL;
			u_int uDispCondIndex = ( pxWeaponItem ) ? pxWeaponItem->GetSelectorDisplayConditionIndex() : UINT_MAX;

			switch( pxTargetEntity->GetClassification() )
			{
				////////////////////
				case AVP_ENTITYCLASS_ALIEN:
				////////////////////
				{
					SetTargetInfo( PTS_ALIEN, PTW_CLAWS, PTTL_MEDIUM, PTTL_NONE, false, true );
					return;
				}
				////////////////////
				case AVP_ENTITYCLASS_ALIENFACEHUGGER:		
				case AVP_ENTITYCLASS_ALIEN_HYBRID:
				////////////////////
				{
					SetTargetInfo( PTS_ALIEN, PTW_CLAWS, PTTL_HIGH, PTTL_NONE, false, false );
					return;
				}
				////////////////////
				case AVP_ENTITYCLASS_ALIENQUEEN:
				////////////////////
				{
					SetTargetInfo( PTS_ALIEN, PTW_CLAWS, PTTL_EXTREAM, PTTL_LOW, false, false );
					return;
				}
				////////////////////
				case AVP_ENTITYCLASS_SENTRYGUN:		
				////////////////////
				{
					SetTargetInfo( PTS_MECHANICAL, PTW_SMART_GUN, PTTL_EXTREAM, PTTL_MEDIUM, false, false );
					return;
				}
				////////////////////
				case AVP_ENTITYCLASS_PREDALIEN:	
				////////////////////
				{
					SetTargetInfo( PTS_ALIEN_PREDATOR, PTW_CLAWS, PTTL_HIGH, PTTL_LOW, false, true );
					return;
				}
				////////////////////
				case AVP_ENTITYCLASS_DROPSHIP:	
				////////////////////
				{
					SetTargetInfo( PTS_MECHANICAL, PTW_MISSLE_LAUNCHER, PTTL_HIGH, PTTL_EXTREAM, false, true );
					return;
				}
				////////////////////
				case AVP_ENTITYCLASS_HUMAN:			
				case AVP_ENTITYCLASS_CIVILIAN:		
				////////////////////
				{
					iSpecies = PTS_HUMAN;
					break;
				}
				////////////////////
				case AVP_ENTITYCLASS_MARINE:	
				////////////////////
				{
					iSpecies = PTS_HUMAN;
					break;
				}
				////////////////////
				case AVP_ENTITYCLASS_PREDATOR:			
				////////////////////
				{
					iSpecies = PTS_PREDATOR;
					break;
				}
				////////////////////
				case AVP_ENTITYCLASS_ANDROID:		
				////////////////////
				{
					iSpecies = PTS_SYNTHETIC;
					bSences = true;
					break;
				}
				////////////////////
				default:
				////////////////////
				{
					Asura_Assertf( false, ( "AVP_Predator_HUDHandler::UpdateTargetInfo\n Current Target entity classification is not recognised\n make sure there is code to implement info retrieval for it or not allow it to be focused on. Classification %d", pxTargetEntity->GetClassification() ) );
					break;
				}
			}

			//anything that is a human or below needs to be checked for motion tracker. 
			if(		( pxTargetEntity->GetSpeciesByClassification() == AVP_Settings::AVP_SPECIES_HUMAN )
				&&	( pxTargetEntity->GetClassification() != AVP_ENTITYCLASS_SENTRYGUN ) )
			{
				AVP_ServerActor_Human* pxHumanTargetEntity = static_cast<AVP_ServerActor_Human*>( pxTargetEntity );
				if( pxHumanTargetEntity )
				{
					bTracker = pxHumanTargetEntity->GetHasMotionTracker();
				}
			}

			// the only way to tell the difference between some weapons is with thier HUD display condition index as they share the same ItemType. 
			if( pxWeaponItem )
			{
				switch( uDispCondIndex )
				{
					////////////////////
					case 2000:			//Pistol
					////////////////////
					{
						SetTargetInfo( iSpecies, PTW_PISTOL, PTTL_LOW, PTTL_LOW, bTracker, bSences );
						break;
					}
					////////////////////
					case 2001:			//Pulse Rifle
					////////////////////
					{
						SetTargetInfo( iSpecies, PTW_PULSE_RIFLE, PTTL_MEDIUM, PTTL_MEDIUM, bTracker, bSences );
						break;
					}
					////////////////////
					default:
					////////////////////
					{
 						switch( pxWeaponItem->GetItemType() )
 						{
							////////////////////
							case AVP_INVENTORYITEMTYPE_WEAPON_RANGED:
							////////////////////
							{
								Asura_Assert( false, "AVP_Predator_HUDHandler::UpdateTargetInfo\n There is a ranged weapon that does not have its HUD display condition index in the correct switch case" );
								break;
							}
							////////////////////
							case AVP_INVENTORYITEMTYPE_PREDATORDISC:
							////////////////////
							{
								SetTargetInfo( iSpecies, PTW_DISC, PTTL_HIGH, PTTL_EXTREAM, bTracker, bSences );
								break;
							}
							////////////////////
							case AVP_INVENTORYITEMTYPE_SMARTGUN:
							////////////////////
							{
								SetTargetInfo( iSpecies, PTW_SMART_GUN, PTTL_EXTREAM, PTTL_HIGH, bTracker, bSences );
								break;
							}
							////////////////////
							case AVP_INVENTORYITEMTYPE_WEAPON_FLAMETHROWER:
							////////////////////
							{
								SetTargetInfo( iSpecies, PTW_FLAMETHROWER, PTTL_HIGH, PTTL_NONE, bTracker, bSences );
								break;
							}
							////////////////////
							case AVP_INVENTORYITEMTYPE_UNARMED:
							////////////////////
							{
								SetTargetInfo( iSpecies, PTW_UNARMED, PTTL_NONE, PTTL_NONE, bTracker, bSences );
								break;
							}
							////////////////////
							case AVP_INVENTORYITEMTYPE_SCOPEDRIFLE:
							////////////////////
							{
								SetTargetInfo( iSpecies, PTW_SCOPED_RIFLE, PTTL_MEDIUM, PTTL_HIGH, bTracker, bSences );
								break;
							}
							////////////////////
							case AVP_INVENTORYITEMTYPE_PLASMACASTER:
							////////////////////
							{
								SetTargetInfo( iSpecies, PTW_PLASMA_CASTER, PTTL_EXTREAM, PTTL_HIGH, bTracker, bSences );
								break;
							}
							////////////////////
							case AVP_INVENTORYITEMTYPE_SHOTGUN:
							////////////////////
							{
								SetTargetInfo( iSpecies, PTW_SHOTGUN, PTTL_HIGH, PTTL_LOW, bTracker, bSences );
								break;
							}
							////////////////////
							case AVP_INVENTORYITEMTYPE_PREDATORMINE:
							////////////////////
							{
								SetTargetInfo( iSpecies, PTW_MINES, PTTL_EXTREAM, PTTL_NONE, bTracker, bSences );
								break;
							}
							////////////////////
							default:
							////////////////////
							{
								Asura_Assertf( false, ( "AVP_Predator_HUDHandler::UpdateTargetInfo\n Weapon type of Predator's target is not recognised and seems to have no type\n Weapon Display Condition Index %d", pxTargetEntity->GetInventorySystem()->GetCurrentItem( uAVP_INVENTORY_GROUPHASH_WEAPON )->GetSelectorDisplayConditionIndex() ) );
								break;
							}
 						}
						break;
					}
				}
			}
			else
			{
				SetTargetInfo( iSpecies, PTW_UNARMED, PTTL_NONE, PTTL_NONE, bTracker, bSences );
			}
		}
	}
}

void AVP_Predator_HUDHandler::SetTargetInfo( int iSpecies, int iWeapon, int iThreatNear, int iThreatFar, bool bMotionTracker, bool bHieghtendSences )
{
	s_xTargetInfo.m_iSpecies = iSpecies;
	s_xTargetInfo.m_iWeapon = iWeapon;
	s_xTargetInfo.m_bHieghtenedSences = bHieghtendSences;
	s_xTargetInfo.m_bMotionTracker = bMotionTracker;
	s_xTargetInfo.m_iThreatNear = iThreatNear;
	s_xTargetInfo.m_iThreatFar = iThreatFar;
}

void AVP_Predator_HUDHandler::Reset( void )
{
	for(u_int uZoomItr = 0; uZoomItr < AVP_CAMERA_NUM_ZOOM_LEVELS - 1; uZoomItr++)
	{
		s_bShowZoom[ uZoomItr ] = false;
	}

	g_bFirstFrame = true;

	PARENT::Reset();
}

void AVP_Predator_HUDHandler::OnBeginTargetedJump(void)
{
	SetFSFXValue(FSFX_TARGETEDJUMP, uAVP_BLUEPRINT_PARAM_TARGETEDJUMP_FSFX, 0.5f, 0.5f);
	PlaySoundEvent(uAVP_BLUEPRINT_PARAM_TARGETEDJUMP_SOUND_LOOP, &m_iTargetedJumpSoundHandle);
}

void AVP_Predator_HUDHandler::OnEndTargetedJump(void)
{
	SetFSFXValue(FSFX_TARGETEDJUMP, uAVP_BLUEPRINT_PARAM_TARGETEDJUMP_FSFX, 0.0f, 0.5f);
	StopSoundEvent(m_iTargetedJumpSoundHandle);
}

void AVP_Predator_HUDHandler::OnBeginZoomingIn( const u_int uZoomLevel )
{
	PARENT::OnBeginZoomingIn( uZoomLevel );

	for(u_int uZoomItr = 0; uZoomItr < AVP_CAMERA_NUM_ZOOM_LEVELS - 1; uZoomItr++)
	{
		s_bShowZoom[ uZoomItr ] = ( uZoomItr + 1 == uZoomLevel );
	}
}

void AVP_Predator_HUDHandler::OnBeginZoomingOut( const u_int uZoomLevel )
{
	PARENT::OnBeginZoomingOut( uZoomLevel );

	for(u_int uZoomItr = 0; uZoomItr < AVP_CAMERA_NUM_ZOOM_LEVELS - 1; uZoomItr++)
	{
		s_bShowZoom[ uZoomItr ] = ( uZoomItr + 1 == uZoomLevel );
	}
}

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Predator_HUDHandler::OnBeginRecon
// Author       : Callum Hope
// Date         : 24-Nov-2008
////////////////////////////////////////////////////////////////////////////////

void AVP_Predator_HUDHandler::OnBeginRecon(void)
{
	// any HUD effects at the start of recon can go here
}

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Predator_HUDHandler::OnOnEndReconEndFocus
// Author       : Callum Hope
// Date         : 24-Nov-2008
////////////////////////////////////////////////////////////////////////////////

void AVP_Predator_HUDHandler::OnEndRecon(void)
{
	// any HID effects that were started on recon mode can be shut down here. 
}

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Predator_HUDHandler::OnSelectReconTarget
// Author       : Callum Hope
// Date         : 1-Dec-2008
////////////////////////////////////////////////////////////////////////////////

void AVP_Predator_HUDHandler::OnSelectReconTarget(void)
{
	// any hud effects when target is selected can go here. 
}

bool* AVP_Predator_HUDHandler::GetShowVisionSelectorConsoleVarPtr()
{
	return &s_bShowVisionSelector;
}

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Predator_HUDHandler::OnBeginTargetInfo
// Author       : Callum Hope
// Date         : 7/5/09
////////////////////////////////////////////////////////////////////////////////

void AVP_Predator_HUDHandler::OnBeginTargetInfo( void )
{
	PlaySoundEvent( uAVP_BLUEPRINT_PARAM_TARGETINFO_SOUND_BEGIN, NULL );
	PlaySoundEvent( uAVP_BLUEPRINT_PARAM_TARGETINFO_SOUND_LOOP, &m_iTargetInfoSoundLoopHandle );

	s_fHasFocusInfoTarget = 1.0f;
}

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Predator_HUDHandler::OnEndTargetInfo
// Author       : Callum Hope
// Date         : 7/5/09
////////////////////////////////////////////////////////////////////////////////

void AVP_Predator_HUDHandler::OnEndTargetInfo( void )
{
	PlaySoundEvent( uAVP_BLUEPRINT_PARAM_TARGETINFO_SOUND_END, NULL );
	StopSoundEvent( m_iTargetInfoSoundLoopHandle );

	s_fHasFocusInfoTarget = 0.0f;
}

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Predator_HUDHandler::GetPotentialPrey
// Scope		: Private
// Author       : Callum Hope
// Date         : 12-5-2009
//
// Desc			: Goes through entities and finds the one - if any - that are closest to the center of the screen. 
//				  Returns the Guid of the target so we know to display info about it. 
//				  Funcitonality is very similar to pred recon function "UpdattPotentialPrey"
////////////////////////////////////////////////////////////////////////////////

Asura_Guid AVP_Predator_HUDHandler::GetPotentialPrey()
{
	Asura_Vector_3		xCameraPosition;
	Asura_Matrix_3x3	xCameraOrientation;

	Asura_Guid uPotPreyGuid = ASURA_GUID_UNREGISTERED;

	AVP_ClientActor_Predator* xOwner = AVP_ClientActor_Predator::FindEntity( m_xOwner.GetGuid() );
	if( xOwner )
	{
		// fist see if they have a melee target, if so then return the guid of this entity. 
		if( xOwner->GetFocus()->GetMeleeTarget() != ASURA_GUID_UNREGISTERED )
		{
			return xOwner->GetFocus()->GetMeleeTarget();
		}

		// Get the Hash ID of the camera attached to the player model's eye position, its what we will use for the LOS test. 
		Asura_Hash_ID uCameraHashID = AVP_Vertebrate_Description::GetMarkerPointHashID( AVP_Vertebrate_Description::MPID_EYES ); 

		if( xOwner->GetWorldSpaceMarkerPoint( uCameraHashID, &xCameraPosition, &xCameraOrientation) ) 
		{
			// if we got the camera position etc then get the vector direction to be used for the LOS test. 
			const Asura_Vector_3 xCameraDirection( xCameraOrientation.e13, xCameraOrientation.e23, xCameraOrientation.e33 );
			const AVP_ClientEntity_Actor* pxEntity = NULL;

			// set the best screen position found to as far away from the centre as possible. 
			Asura_Vector_2 xBestScreenPos(1.0f, 1.0f); 

			for( Asura_Hashed_List_ConstIt<AVP_ClientEntity_Actor> xIt( AVP_ClientEntity_Actor::GetList() ); !xIt.Done(); xIt.Next() )
			{
				pxEntity = xIt.GetCurrent();

				if(		( pxEntity )																		// if we have an entiry
					&&	( ! pxEntity->IsDead() )															// and it is not dead
					&&	( ! pxEntity->IsDestroyed() )														// and it has not been destroyed
					&&	( pxEntity->GetGuid() != xOwner->GetGuid() )	)									// and it is not the local player
				{
					if( m_xOwner.GetFocus()->GetActive()										
						&& pxEntity->GetSpeciesByClassification() != AVP_Settings::AVP_SPECIES_UNKNOWN )	 
					{
						if( TestEntityAgainstLOS( *pxEntity, xCameraPosition, xCameraDirection, xBestScreenPos ) )
						{
							// record needed data for render and raise 'potential found' flag AS LONG AS we are NOT looking at an already active prey
							uPotPreyGuid = pxEntity->GetGuid();
						}
					}
				}
			}
		}
	}
	return uPotPreyGuid;
}

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Predator_HUDHandler::TestEntityAgainstLOS
// Scope		: Private
// Author       : Callum Hope
// Date         : 12-5-2009
//
// Desc			: Performes the Line Of Sight tests for this class. But incorporates a whole area of the screen, not just the cross hair
//				  Checks that the entity under question is infront of the camera and within the max Recon Range. 
//				  Returns true if we have hit the entity under question. 
////////////////////////////////////////////////////////////////////////////////

static const Asura_Vector_3 xSCREEN_CENTRE(0.5f, 0.5f, 0.0f);

bool AVP_Predator_HUDHandler::TestEntityAgainstLOS(const AVP_ClientEntity_Actor& xEntity, const Asura_Vector_3& xCameraPosition, Asura_Vector_3 xCameraDirection, Asura_Vector_2& xBestScreenPos ) const
{
	// make the screen area for selecetion 10% (5 in both directions)
	float fScreenSpaceFromCentreLimit = 0.05f;

	// get the chest position of the entity, as a point generally in the center of the model 
	Asura_Vector_3 xChestWorldPos;
	xEntity.GetChestPosition( xChestWorldPos );

	// find the distance from the camera to the entity in question (used to limit the LOS search to a max length.)
	Asura_Vector_3 xDirToEntity = xChestWorldPos - xCameraPosition;
	float fDistToPrey = xDirToEntity.Magnitude() + 1.0f;
	xDirToEntity.Normalise();

	// set the input to the LOS test: from position, direction, ignor the player, check distance. 
	Asura_LOS_InputData xInput( xCameraPosition, xDirToEntity, m_xOwner.GetGuid(), fDistToPrey );

	// carry out the Asura Internal LOS test.
	const Asura_LOS_OutputData* pxOutput = Asura_LOS::TestAgainstEverything( &xInput );

	if( pxOutput->m_bHitEnvironment || ( pxOutput->m_uHitEntity && pxOutput->m_uHitEntity != xEntity.GetGuid() ) )
	{
		// if there is environment or another entity betwen us and them (that is not them) then return false. 
		return false;
	}

	// using this position in world space find the camera space for it. (used for the valid range test)
	Asura_Vector_3 xChestCameraSpacePos = xChestWorldPos;
	Asura_Camera::ProjectWorldCoordsToScreenSpace( xChestCameraSpacePos );

	if( xChestCameraSpacePos.z <= 0.0f ) 
	{ 
		// return if the entity is behind the camera. 
		return false; 
	} 
	else if( xChestCameraSpacePos.z > AVP_Predator_Recon::GetRecon().GetMaxEngageDistance() )
	{ 
		// return false if the entity is too far away
		return false; 
	} 

	xChestCameraSpacePos -= xSCREEN_CENTRE;
	xChestCameraSpacePos.z = 0.0f;

	// make a new vector 2 and fill with the x and y from the camera space position so we can compare it agains any other potential preys on the screen. 
	Asura_Vector_2 xNewScreenSpace( xChestCameraSpacePos.GetX(), xChestCameraSpacePos.GetY() );

	if ( xNewScreenSpace.MagnitudeSquared() >= xBestScreenPos.MagnitudeSquared() )
	{
		// Already have a more central target so return false
		return false;
	}
	else
	{
		xBestScreenPos = xNewScreenSpace;
	}

	if( ( xChestCameraSpacePos.x > -fScreenSpaceFromCentreLimit )	&&
		( xChestCameraSpacePos.x < fScreenSpaceFromCentreLimit )	&&
		( xChestCameraSpacePos.y > -fScreenSpaceFromCentreLimit )	&&
		( xChestCameraSpacePos.y < fScreenSpaceFromCentreLimit )	)
	{
		return true;
	}

	// set the input to the LOS test: from position, direction, ignor the player, check distance. 
	xInput = Asura_LOS_InputData( xCameraPosition, xCameraDirection, m_xOwner.GetGuid(), fDistToPrey );

	// carry out the Asura Internal LOS test.
	pxOutput = Asura_LOS::TestAgainstEverything( &xInput );

	return( pxOutput->m_uHitEntity == xEntity.GetGuid() );

}
