
///////////////////////////////////////////////////////////////////////////////
//
// File   : AVP_Actor_HUDHandler.cpp
// Author : Chris Wallace
// Date   : 2-Nov-2006
//
// Copyright (C) 2006 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

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

#include "Core/Asura.h"

// This file's header...
#include "Actor/AVP_Actor_HUDHandler.h"

// Asura independent header-files...
#include "Animation/Asura_AnimationAttachment.h"
#include "Blueprint/Asura_Blueprint_System.h"
#include "Camera/Asura_Camera.h"
#include "Core/Asura_HashedLocalisedText.h"
#include "Core/Asura_MaterialResponse_System.h"
#include "Core/Asura_TextureManagement.h"
#if !defined(ASURA_NO_DEBUG_OUTPUT)
#include "Debugging/Asura_DebugLineRender.h"
#endif // if !defined(ASURA_NO_DEBUG_OUTPUT)
#include "FSFX/Asura_FSFX_System.h"
#include "GUIMenu/Asura_GUIMenu_Widget_Group.h"
#include "GUIMenu/Asura_GUIMenu_Element_Image.h"
#include "Interface/Asura_CommandConsole.h"
#include "Light/Asura_Photon.h"
#include "Network/Online/Asura_Lobby.h"
#include "Network/Asura_Message.h"
#include "Rendering/Asura_Font_System.h"
#include "Rendering/Asura_Render.h"
#include "Rendering/Asura_Viewport.h"
#include "Sound/Asura_Audio_System.h"
#include "Sound/Asura_Sound_Event_Storage.h"
#include "Sound/Asura_Sound_Event_System.h"
#include "SpecialFX/pfx/Asura_PFX_Enums.h"
#include "SpecialFX/pfx/Asura_PFX_Entity_Effect.h"
#include "SpecialFX/pfx/Asura_PFX_System.h"
#include "Sound/Asura_Sound_Mixer.h"

// Game header-files...
#include "Actor/AVP_Actor_AnimationHandler.h"
#include "Actor/AVP_Actor_CameraHandler.h"
#include "Actor/AVP_Actor_InputHandler.h"
#include "Animation/AVP_Hierarchy_System.h"
#include "Core/AVP_Core.h"
#include "Core/AVP_Game_Core.h"
#include "Core/AVP_GameStatus.h"
#include "Core/AVP_Settings.h"
#include "Entity/AVP_Entity_Classification.h"
#include "Entity/Damage/AVP_EntityDamage_Apply.h"
#include "Entity/ObjectiveSystem/PlayerObjective/AVP_ServerEntity_PlayerObjective.h"
#include "Entity/PhysicalObject/AVP_ServerEntity_PhysicalObject.h"
#include "Entity/PhysicalObject/Actor/AVP_ClientEntity_Actor.h"
#include "Entity/PlayerInfo/AVP_ClientEntity_PlayerInfo.h"
#include "GUIMenu/AVP_GUIMenu_System.h"
#include "Inventory/AVP_Inventory_HashIDs.h"
#include "Inventory/AVP_Inventory_System.h"
#include "Inventory/Items/AVP_InventoryItem_Weapon.h"
#include "Multiplayer/AVP_Multiplayer_GameRules.h"
#include "Multiplayer/AVP_Multiplayer_HashIDs.h"

// Tools header-files...
#if defined(ASURA_TOOLS)
	#include "Tools_System.h"
	#include "FSFX/Tools_FSFX_System.h"
#endif

////////////////////////////////////////////////////////////////////////////////
// Constant declarations...
////////////////////////////////////////////////////////////////////////////////

#define HUD_SHOWDAMAGEEFFECT	L"AVP.HUD.ShowDamageEffect"
#define HUD_SHOWHEALTHEFFECT	L"AVP.HUD.ShowHealthEffect"
#define HUD_SHOWWEAPONSELECTOR	L"AVP.HUD.ShowWeaponSelector"

#define HUD_SHOWHEALTH1			L"AVP.HUD.ShowHealth1"
#define HUD_SHOWHEALTH2			L"AVP.HUD.ShowHealth2"
#define HUD_SHOWHEALTH3			L"AVP.HUD.ShowHealth3"
#define HUD_SHOWHEALTH4			L"AVP.HUD.ShowHealth4"
#define HUD_SHOWHEALTH5			L"AVP.HUD.ShowHealth5"
#define HUD_HEALTH1PARAMETRIC	L"AVP.HUD.Health1Parametric"
#define HUD_HEALTH2PARAMETRIC	L"AVP.HUD.Health2Parametric"
#define HUD_HEALTH3PARAMETRIC	L"AVP.HUD.Health3Parametric"
#define HUD_HEALTH4PARAMETRIC	L"AVP.HUD.Health4Parametric"
#define HUD_HEALTH5PARAMETRIC	L"AVP.HUD.Health5Parametric"
#define HUD_CAUTION				L"AVP.HUD.Caution"

#define HUD_SHOWOBJECTIVEADDED    	L"AVP.HUD.ShowObjectiveAdded"
#define HUD_SHOWOBJECTIVECOMPLETED 	L"AVP.HUD.ShowObjectiveCompleted"
#define HUD_SHOWOBJECTIVE    	    L"AVP.HUD.ShowObjective"
#define HUD_SHOWOBJECTIVEARROW 	    L"AVP.HUD.ShowObjectiveArrow"

#define HUD_SHOWCHECKPOINTREACHED   L"AVP.HUD.CheckpointReached"
#define HUD_SHOWAUDIODIARYPICKED    L"AVP.HUD.ShowAudioDiaryPicked"
#define HUD_SHOWHITBYPLASMA			L"AVP.HUD.ShowHitByPlasma"
#define HUD_SHOWHITBYACID			L"AVP.HUD.ShowHitByAcid"
#define HUD_SHOWWEAPONACCURACY      L"AVP.HUD.ShowWeaponAccuracy"

#define HUD_CLAMPEDANGLE	L"AVP.HUD.ClampedAngleToObjective"
#define HUD_WEAPONACCURACY	L"AVP.HUD.WeaponAccuracy"

#define HUD_HEALTHSTATE		L"AVP.HUD.HealthState"
#define HUD_AMMOSTATE		L"AVP.HUD.AmmoState"
#define HUD_ENERGYSTATE		L"AVP.HUD.EnergyState"

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

DEBUGVAR float dbg_fEpsilon	= 0.001f;
DEBUGVAR float dbg_fTimeToShowNewObjective		= 5.00f; // 5 seconds
DEBUGVAR float dbg_fTimeToShowCheckpointReached = 4.00f; // 3 seconds
DEBUGVAR float dbg_fTimeToShowAudioDiaryPicked  = 4.00f;

bool  AVP_Actor_HUDHandler::s_bShowDamageEffect			= false;
bool  AVP_Actor_HUDHandler::s_bShowHealthEffect			= false;
bool  AVP_Actor_HUDHandler::s_bShowWeaponSelector		= false;
bool  AVP_Actor_HUDHandler::s_bShowHealth[ MAX_HUD_HEALTH_ELEMENTS ];
float AVP_Actor_HUDHandler::s_fHealthParametric[ MAX_HUD_HEALTH_ELEMENTS ];
bool  AVP_Actor_HUDHandler::s_bCaution					= false;
bool  AVP_Actor_HUDHandler::s_bShowObjective			= false;
bool  AVP_Actor_HUDHandler::s_bShowObjectiveAdded		= false;
bool  AVP_Actor_HUDHandler::s_bShowObjectiveCompleted	= false;
bool  AVP_Actor_HUDHandler::s_bShowObjectiveArrow    	= false;
bool  AVP_Actor_HUDHandler::s_bCheckpointReached        = false;
bool  AVP_Actor_HUDHandler::s_bShowAudioDiaryPicked     = false;
bool  AVP_Actor_HUDHandler::s_bShowHitByPlasma			= false;
bool  AVP_Actor_HUDHandler::s_bShowHitByAcid			= false;
bool  AVP_Actor_HUDHandler::s_bShowWeaponAccuracy       = false;

Asura_Guid AVP_Actor_HUDHandler::s_uObjectiveToShow     = ASURA_GUID_UNREGISTERED;
float AVP_Actor_HUDHandler::s_fWeaponAccuracy			= 0.0f;
float AVP_Actor_HUDHandler::s_fClampedAngleToObjective	= 0.0f;

int AVP_Actor_HUDHandler::s_iMissionTimeHours = 0;
int AVP_Actor_HUDHandler::s_iMissionTimeMinutes = 0;
int AVP_Actor_HUDHandler::s_iMissionTimeSeconds = 0;


u_int AVP_Actor_HUDHandler::s_uHUDHealthState	= 1; //
u_int AVP_Actor_HUDHandler::s_uHUDAmmoState		= 1; // Should be visible from the beginning
u_int AVP_Actor_HUDHandler::s_uHUDEnergyState	= 1; //

float AVP_Actor_HUDHandler::s_fHealthStateTimer = 0.0f;
float AVP_Actor_HUDHandler::s_fAmmoStateTimer	= 0.0f;
float AVP_Actor_HUDHandler::s_fEnergyStateTimer = 0.0f;

#if !defined(AVP_SUBMISSION)
	DVSVAR bool dvs_bDisableVisionModes = false;

#if defined(ASURA_TOOLS)
	DVSVAR bool dvs_bForceFixedExposure = false;
#endif
#endif

DVSVAR bool dvs_bUseHUDPhotons = true;
DVSVAR bool dvs_bOverrideHUDPhotonSettings = false;
DVSVAR float dvs_fHUDPhotonOverrideX = -0.3f;
DVSVAR float dvs_fHUDPhotonOverrideY = 0.0f;
DVSVAR float dvs_fHUDPhotonOverrideZ = 0.3f;
DVSVAR float dvs_fHUDPhotonOverrideRed = 2.0f;
DVSVAR float dvs_fHUDPhotonOverrideGreen = 2.0f;
DVSVAR float dvs_fHUDPhotonOverrideBlue = 2.0f;
DVSVAR float dvs_fHUDPhotonOverridePower = 1.0f;
DVSVAR float dvs_fHUDPhotonOverrideRange = 1.0f;

bool	AVP_Actor_HUDHandler::s_bHUDEnabled	= false;

Asura_CameraData::HDRSettings AVP_Actor_HUDHandler::s_xTorchHDRSettings;

bool AVP_Actor_HUDHandler::s_bTorchOverride      = false;
bool AVP_Actor_HUDHandler::s_bAllowTorchOverride = false;

bool	AVP_Actor_HUDHandler::s_bHUDSubLevelLoaded			= false;
u_int	AVP_Actor_HUDHandler::s_uCurrentHUDSubLevelPage		= 0;

static int g_iFrameCounter = 0;

////////////////////////////////////////////////////////////////////////////////
// Public functions...
////////////////////////////////////////////////////////////////////////////////

AVP_Actor_HUDHandler::AVP_Actor_HUDHandler(AVP_ClientEntity_Actor& xClient)
: m_xNoHealthPos( Asura_Maths::ZeroVector2 )
, m_xFullHealthPos( Asura_Maths::ZeroVector2 )
, m_fLeft(Asura_Viewport::GetWidth() * Asura_Camera::GetViewingArea()->m_fXOffset)
, m_fTop(Asura_Viewport::GetHeight() * Asura_Camera::GetViewingArea()->m_fYOffset)
, m_fRight(m_fLeft + m_fWidth)
, m_fBottom(m_fTop + m_fHeight)
, m_fWidth(Asura_Viewport::GetWidth() * Asura_Camera::GetViewingArea()->m_fWidth)
, m_fHeight(Asura_Viewport::GetHeight() * Asura_Camera::GetViewingArea()->m_fHeight)
, m_uVisionModeBlueprintHash(ASURA_HASH_ID_UNSET)
, m_iVisionModeChangeSoundHandle(ASURA_INVALID_HANDLE)
, m_iVisionModeLoopSoundHandle(ASURA_INVALID_HANDLE)
, m_iAdrenalineLoopHandle(ASURA_INVALID_HANDLE)
, m_iBreathingLoopHandle(ASURA_INVALID_HANDLE)
, m_uMaxNumHealthBlocks( 5 )
, m_fHealthPerBlock( 20.0f )
, m_fDamageFadeTime( 0.0f )
, m_fHealthFadeTime( 0.0f )
, m_fHitByPlasmaFadeTime( 10.0f )
, m_fHitByPlasmaTimer( 0.0f )
, m_fHitByAcidFadeTime( 3.0f )
, m_fHitByAcidTimer( 0.f )
, m_fObjectiveTimer( 0.0f )
, m_fAudioDiaryTimer( 0.0f )
, m_fHUDStateFadeTime( 4.0f )
, m_fSprintFOVDecrease( Asura_Maths::DegToRad( 10.0f ) )
, m_fSprintFovFadeInTime( 1.0f )
, m_fSprintFovFadeOutTime( 1.0f )
, m_fTargetSprintFOV( 0.0f )
, m_fCurrentSprintFOV( 0.0f )
, m_xOwner(xClient)
, m_bInCutscene(false)
{
	for ( u_int uItr = 0; uItr < NUM_FSFX_TYPES; ++uItr )
	{
		m_fDesiredFSFXValue[ uItr ] = 0.0f;
		m_uCurrentFSFXParameterHash[ uItr ] = ASURA_HASH_ID_UNSET;
	}

	m_uOwnerGuid			= xClient.GetGuid();

	const Asura_Blueprint*	pxBP	= GetActorBlueprint();
	if(pxBP != NULL)
	{
		Asura_Value xValue;
		if ( pxBP->GetParameterValueByHashID( uAVP_BLUEPRINT_PARAM_NUMHEALTHBLOCKS, xValue ) )
		{
			m_uMaxNumHealthBlocks = xValue.GetIntValue();
		}
		if ( pxBP->GetParameterValueByHashID( 0xb735025c, xValue ) )	// Health
		{
			m_fHealthPerBlock = xValue.GetFloatValue() / m_uMaxNumHealthBlocks;
		}
	}

	pxBP = GetPlayerBlueprint();
	if ( pxBP )
	{
		Asura_Value xValue;
		if ( pxBP->GetParameterValueByHashID( uAVP_BLUEPRINT_PARAM_SPRINTFOVDECREASE, xValue ) )
		{
			m_fSprintFOVDecrease = Asura_Maths::DegToRad( xValue.GetFloatValue() );
		}
		if ( pxBP->GetParameterValueByHashID( uAVP_BLUEPRINT_PARAM_SPRINTFOVFADEIN, xValue ) )
		{
			m_fSprintFovFadeInTime = xValue.GetFloatValue();
		}
		if ( pxBP->GetParameterValueByHashID( uAVP_BLUEPRINT_PARAM_SPRINTFOVFADEOUT, xValue ) )
		{
			m_fSprintFovFadeOutTime = xValue.GetFloatValue();
		}

		if( pxBP->GetParameterValueByHashID( uAVP_BLUEPRINT_PARAM_HITBYPLASMA_FADETIME, xValue ) )
		{
			m_fHitByPlasmaFadeTime = xValue.GetFloatValue();
		} 
		else
		{
			Asura_Assert(false, "Actor Hud failed to find blueprint value Damage.HitByPlasmaDuration in player blueprint");
		}

		if( pxBP->GetParameterValueByHashID( uAVP_BLUEPRINT_PARAM_HITBYACID_FADETIME, xValue ) )
		{
			m_fHitByAcidFadeTime = xValue.GetFloatValue();
		}
		else
		{
			Asura_Assert(false, "Actor Hud failed to find blueprint value Damage.HitByAcidDuration in player blueprint");
		}
		if( pxBP->GetParameterValueByHashID( uAVP_BLUEPRINT_PARAM_HUDSTATE_FADETIME, xValue ) )
		{
			m_fHUDStateFadeTime = xValue.GetFloatValue();
		}
		else
		{
			Asura_Assert( false, "Actor Hud failed to find blueprint value HUD.StateFadeTime in player blueprint");
		}

	}

	//Set up font
	m_fIncrement			= Asura_Font_System::GetFontHeight();
	m_uTextColour			= 0xFFFF3333;
	m_uTextFormat			= ASURA_TEXTFORMAT_DEFAULT;
	m_fTextScale			= 1.0f;

	// Reset objective
	s_bShowObjective          = false;
	s_bShowObjectiveAdded     = false;
	s_bShowObjectiveCompleted = false;
	s_bShowObjectiveArrow     = false;
	
	s_bCheckpointReached    = false;
	s_bShowAudioDiaryPicked = false;
	s_bShowHitByPlasma		= false;
	s_bShowHitByAcid		= false;

	if (AVP_Settings::IsMultiPlayer())
	{
		// Clear all FSFX
		Asura_FSFX_System::ClearAllHandlerTemplates();
	}

	for (int i=0; i<MAX_HUD_PHOTONS; ++i)
	{
		m_axHUDPhotons[i].m_pxPhoton = NULL;
		m_axHUDPhotons[i].m_xCameraOffset = Asura_Maths::ZeroVector3;
		m_axHUDPhotons[i].m_fRed = 0.0f;
		m_axHUDPhotons[i].m_fGreen = 0.0f;
		m_axHUDPhotons[i].m_fBlue = 0.0f;
		m_axHUDPhotons[i].m_fFadeInRate = 1.0f;
		m_axHUDPhotons[i].m_fFadeOutRate = 1.0f;
		m_axHUDPhotons[i].m_fRange = 0.0f;
		m_axHUDPhotons[i].m_fPower = 0.0f;
		m_axHUDPhotons[i].m_fCurrentFade = 0.0f;
		m_axHUDPhotons[i].m_bRunning = false;
	}
}
//s_bHUDEnabled
#if defined(ASURA_SUPPORT_COMMAND_CONSOLE)
void AVP_Actor_HUDHandler::CreateConsoleVars()
{
#if !defined(AVP_SUBMISSION)
	Asura_CommandConsole::AddVar( L"AVP.DisableVisionModes", &dvs_bDisableVisionModes, Asura_CommandConsole::REMOVE_AT_SHUTDOWN);
#if defined(ASURA_TOOLS)
	Asura_CommandConsole::AddVar( L"AVP.ForceFixedExposure", &dvs_bForceFixedExposure, Asura_CommandConsole::REMOVE_AT_SHUTDOWN);
#endif
#endif
	Asura_CommandConsole::AddVar( HUD_SHOWDAMAGEEFFECT, &s_bShowDamageEffect, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_SHOWDAMAGEEFFECT );

	Asura_CommandConsole::AddVar( HUD_SHOWHEALTHEFFECT, &s_bShowHealthEffect, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_SHOWHEALTHEFFECT );

	Asura_CommandConsole::AddVar( HUD_SHOWWEAPONSELECTOR, &s_bShowWeaponSelector, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_SHOWWEAPONSELECTOR );

	Asura_CommandConsole::AddVar( HUD_SHOWHEALTH1, &s_bShowHealth[ 0 ], Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_SHOWHEALTH1 );

	Asura_CommandConsole::AddVar( HUD_SHOWHEALTH2, &s_bShowHealth[ 1 ], Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_SHOWHEALTH2 );

	Asura_CommandConsole::AddVar( HUD_SHOWHEALTH3, &s_bShowHealth[ 2 ], Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_SHOWHEALTH3 );

	Asura_CommandConsole::AddVar( HUD_SHOWHEALTH4, &s_bShowHealth[ 3 ], Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_SHOWHEALTH4 );

	Asura_CommandConsole::AddVar( HUD_SHOWHEALTH5, &s_bShowHealth[ 4 ], Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_SHOWHEALTH5 );

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

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

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

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

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

	Asura_CommandConsole::AddVar( HUD_CAUTION, &s_bCaution, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::MakeVarReadOnly( HUD_CAUTION );

	Asura_CommandConsole::AddVar( HUD_SHOWOBJECTIVEADDED    , &s_bShowObjectiveAdded    , Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( HUD_SHOWOBJECTIVECOMPLETED, &s_bShowObjectiveCompleted, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( HUD_SHOWOBJECTIVE         , &s_bShowObjective         , Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( HUD_SHOWOBJECTIVEARROW    , &s_bShowObjectiveArrow    , Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	
	Asura_CommandConsole::AddVar( HUD_SHOWCHECKPOINTREACHED, &s_bCheckpointReached,    Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( HUD_SHOWAUDIODIARYPICKED,  &s_bShowAudioDiaryPicked, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( HUD_SHOWHITBYPLASMA,		 &s_bShowHitByPlasma,	   Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( HUD_SHOWHITBYACID,		 &s_bShowHitByAcid,		   Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( HUD_SHOWWEAPONACCURACY,	 &s_bShowWeaponAccuracy,   Asura_CommandConsole::REMOVE_AT_SHUTDOWN );

	Asura_CommandConsole::AddVar( HUD_CLAMPEDANGLE, &s_fClampedAngleToObjective, 0.0f, 1.0f, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( HUD_WEAPONACCURACY, &s_fWeaponAccuracy, 0.0f, 1.0f, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );

	Asura_CommandConsole::AddVar( HUD_HEALTHSTATE , &s_uHUDHealthState, 0, INT_MAX , Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( HUD_AMMOSTATE	  , &s_uHUDAmmoState  , 0, INT_MAX , Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( HUD_ENERGYSTATE , &s_uHUDEnergyState, 0, INT_MAX , Asura_CommandConsole::REMOVE_AT_SHUTDOWN );

#ifdef ASURA_DEBUG_VARIABLE_SYSTEM
	Asura_CommandConsole::AddVar( L"AVP.HUD.CameraPhotons.Active", &dvs_bUseHUDPhotons, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( L"AVP.HUD.CameraPhotons.OverrideAllSettings", &dvs_bOverrideHUDPhotonSettings, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( L"AVP.HUD.CameraPhotons.Offset.Right", &dvs_fHUDPhotonOverrideX, -10.0f, 10.0f, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( L"AVP.HUD.CameraPhotons.Offset.Down", &dvs_fHUDPhotonOverrideY, -10.0f, 10.0f, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( L"AVP.HUD.CameraPhotons.Offset.Forward", &dvs_fHUDPhotonOverrideZ, -10.0f, 10.0f, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( L"AVP.HUD.CameraPhotons.Colour.Red", &dvs_fHUDPhotonOverrideRed, 0.0f, 255.0f, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( L"AVP.HUD.CameraPhotons.Colour.Green", &dvs_fHUDPhotonOverrideGreen, 0.0f, 255.0f, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( L"AVP.HUD.CameraPhotons.Colour.Blue", &dvs_fHUDPhotonOverrideBlue, 0.0f, 255.0f, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( L"AVP.HUD.CameraPhotons.Power", &dvs_fHUDPhotonOverridePower, 0.1f, 10.0f, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddVar( L"AVP.HUD.CameraPhotons.Range", &dvs_fHUDPhotonOverrideRange, 0.0f, 20.0f, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
#endif //#ifdef ASURA_DEBUG_VARIABLE_SYSTEM
}

void AVP_Actor_HUDHandler::CreateConsoleCommands()
{
	Asura_CommandConsole::AddCmd( L"AVP.CMD.ObjectiveList", AVP_Actor_HUDHandler::ConsoleCmd_ObjectiveList, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddCmd( L"AVP.HUD.GetPlayerName",  ConsoleCmd_GetPlayerName,	Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddCmd( L"AVP.HUD.MissionTimeHours", AVP_Actor_HUDHandler::ConsoleCmd_MissionTimeHours, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddCmd( L"AVP.HUD.MissionTimeMinutes", AVP_Actor_HUDHandler::ConsoleCmd_MissionTimeMinutes, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
	Asura_CommandConsole::AddCmd( L"AVP.HUD.MissionTimeSeconds", AVP_Actor_HUDHandler::ConsoleCmd_MissionTimeSeconds, Asura_CommandConsole::REMOVE_AT_SHUTDOWN );
}
#endif

bool AVP_Actor_HUDHandler::ConsoleCmd_ObjectiveList( u_int uElementIndex, bool bInterrogate, bool bHelp )
{
	if( bInterrogate || bHelp )
	{
		return true;
	}

	AVP_ServerEntity_PlayerObjective* const pxObjective = AVP_ServerEntity_PlayerObjective::FindEntity(s_uObjectiveToShow);
	if(pxObjective)
	{
		if ( pxObjective)
		{
			Asura_CommandConsole::Printf( L"%s", Asura_HashedLocalisedText::GetString(pxObjective->GetObjectiveText().GetTextPageHash(), pxObjective->GetObjectiveText().GetTextID()) );
		}
		return true;
	}
	return false;
}

bool AVP_Actor_HUDHandler::ConsoleCmd_MissionTimeHours( u_int uElementIndex, bool bInterrogate, bool bHelp )
{
	if( bInterrogate || bHelp )
	{
		Asura_CommandConsole::Printf( L"Retrieves the hours part of mission time." ); 
		return true;
	}
	else
	{

		Asura_CommandConsole::Printf( L"%.2i", s_iMissionTimeHours );

		return true;
	}
}

bool AVP_Actor_HUDHandler::ConsoleCmd_MissionTimeMinutes( u_int uElementIndex, bool bInterrogate, bool bHelp )
{
	if( bInterrogate || bHelp )
	{
		Asura_CommandConsole::Printf( L"Retrieves the minutes part of mission time." ); 
		return true;
	}
	else
	{
		Asura_CommandConsole::Printf( L"%.2i", s_iMissionTimeMinutes );

		return true;
	}
}

bool AVP_Actor_HUDHandler::ConsoleCmd_MissionTimeSeconds( u_int uElementIndex, bool bInterrogate, bool bHelp )
{
	if( bInterrogate || bHelp )
	{
		Asura_CommandConsole::Printf( L"Retrieves the seconds part of mission time." ); 
		return true;
	}
	else
	{
		Asura_CommandConsole::Printf( L"%.2i", s_iMissionTimeSeconds );

		return true;
	}
}

AVP_Actor_HUDHandler::~AVP_Actor_HUDHandler()
{
	Asura_Sound_Event_System::Stop(m_iVisionModeChangeSoundHandle);
	Asura_Sound_Event_System::Stop(m_iVisionModeLoopSoundHandle);
	Asura_Sound_Event_System::Stop(m_iAdrenalineLoopHandle);
	Asura_Sound_Event_System::Stop(m_iBreathingLoopHandle);

	// if the HUD is still open close it 
	Asura_Hash_ID uHUDHash =  AVP_GUIMenu_System::GetMenuHash( AVP_GUIMenu_System::GUIMENU_ID_HUD );
	if(Asura_GUIMenu_System::IsMenuPageHashActive(uHUDHash))
	{
		Asura_GUIMenu_System::CloseMenuPage(uHUDHash);
	}
	
	Asura_Hash_ID uWeaponHash =  AVP_GUIMenu_System::GetMenuHash( AVP_GUIMenu_System::GUIMENU_ID_WEAPONSELECTOR );
	if(Asura_GUIMenu_System::IsMenuPageHashActive(uWeaponHash))
	{
		Asura_GUIMenu_System::CloseMenuPage(uWeaponHash);
	}

	// now the same check for sub level pages (eg tutorial text) if any have been used. 
	if( s_bHUDSubLevelLoaded && s_uCurrentHUDSubLevelPage )
	{
		if( Asura_GUIMenu_System::IsMenuPageHashActive( s_uCurrentHUDSubLevelPage ) )
		{
			Asura_GUIMenu_System::CloseMenuPage( s_uCurrentHUDSubLevelPage );
		}
	}

	for (int i=0; i<MAX_HUD_PHOTONS; ++i)
	{
		Asura_Photon_System::DestroyPhoton(m_axHUDPhotons[i].m_pxPhoton); // Should always have been NULLed when invalidated.
	}
}

void AVP_Actor_HUDHandler::Update( const AVP_ClientEntity_Actor& xClient )
{
	if ( Asura_Render::GetCutsceneHasCameraControl() != m_bInCutscene )
	{
		if ( m_bInCutscene )
		{
			OnEndCutscene();
		}
		else
		{
			OnBeginCutscene();
		}
	}

	UpdateFOVModifiers(xClient);

	Asura_Hash_ID uHUDHash =  AVP_GUIMenu_System::GetMenuHash( AVP_GUIMenu_System::GUIMENU_ID_HUD );
	
	// If it's not open (and were not dead!!!!), open the HUD menu page. Its visibility is bound to the Render.Enable.HUD
	// console variable in the GUI menu art package
	if( !Asura_GUIMenu_System::IsMenuPageHashActive( uHUDHash ) && !xClient.IsDead() && !Asura_Render::GetCutsceneHasCameraControl() && !AVP_GameStatus::GetLevelComplete() )
	{
		AVP_GUIMenu_System::Activate( AVP_GUIMenu_System::GUIMENU_ID_HUD );
	}

	// If it's not open and a sub level file has been loaded(and were not dead!!!!), open the sub level GUI page (eg for tutorials). 
	// Its visibility is bound to the Render.Enable.HUD console variable in the GUI menu art package
	if( s_bHUDSubLevelLoaded && s_uCurrentHUDSubLevelPage )
	{
		if( !Asura_GUIMenu_System::IsMenuPageHashActive( s_uCurrentHUDSubLevelPage ) && !xClient.IsDead() && !Asura_Render::GetCutsceneHasCameraControl() && !AVP_GameStatus::GetLevelComplete() )
		{
			AVP_GUIMenu_System::Activate( s_uCurrentHUDSubLevelPage, false, false );
		}
	}

	if ( m_fDamageFadeTime > 0.0f )
	{
		m_fDamageFadeTime -= Asura_Timers::GetGameTimeSlice();
	}
	s_bShowDamageEffect = m_fDamageFadeTime > 0.0f;

	if ( m_fHealthFadeTime > 0.0f )
	{
		m_fHealthFadeTime -= Asura_Timers::GetGameTimeSlice();
	}
	s_bShowHealthEffect = m_fHealthFadeTime > 0.0f;

	if ( s_bShowHitByPlasma )
	{
		m_fHitByPlasmaTimer -= Asura_Timers::GetGameTimeSlice();
		if( m_fHitByPlasmaTimer <= 0.0f )
		{
			s_bShowHitByPlasma = false;
			m_fHitByPlasmaTimer = 0.0f;
		}
	}

	if ( s_bShowHitByAcid )
	{
		m_fHitByAcidTimer -= Asura_Timers::GetGameTimeSlice();
		if( m_fHitByAcidTimer <= 0.0f )
		{
			s_bShowHitByAcid  = false;
			m_fHitByAcidTimer = 0.0f;
		}
	}

	if( s_uHUDHealthState > 0 )
	{
		s_fHealthStateTimer += Asura_Timers::GetGameTimeSlice();
		if( s_fHealthStateTimer >= m_fHUDStateFadeTime )
		{
			s_fHealthStateTimer = 0.0f;
			s_uHUDHealthState = HUD_NOT_VISIBLE;
		}
	}

	if( s_uHUDAmmoState > 0 )
	{
		s_fAmmoStateTimer += Asura_Timers::GetGameTimeSlice();
		if( s_fAmmoStateTimer >= m_fHUDStateFadeTime )
		{
			s_fAmmoStateTimer = 0.0f;
			s_uHUDAmmoState = HUD_NOT_VISIBLE;
		}
	}

	if( s_uHUDEnergyState > 0 )
	{
		s_fEnergyStateTimer += Asura_Timers::GetGameTimeSlice();
		if( s_fEnergyStateTimer >= m_fHUDStateFadeTime )
		{
			s_fEnergyStateTimer = 0.0f;
			s_uHUDEnergyState = HUD_NOT_VISIBLE;
		}
	}

	UpdateHealth( xClient );

	if ((m_iVisionModeChangeSoundHandle != ASURA_INVALID_HANDLE) && !Asura_Sound_Event_System::IsPlaying(m_iVisionModeChangeSoundHandle))
	{
		Asura_Sound_Event_System::Stop(m_iVisionModeChangeSoundHandle);
	}

	// Objectives
	if(s_bShowObjectiveAdded || s_bShowObjectiveCompleted)
	{
		m_fObjectiveTimer += Asura_Timers::GetGameTimeSlice();
		if(m_fObjectiveTimer >= dbg_fTimeToShowNewObjective)
		{
			s_bShowObjectiveAdded     = false;
			s_bShowObjectiveCompleted = false;
			s_bShowObjective          = false;
			m_fObjectiveTimer         = 0.0f;
		}
	}
	else
	{
		m_fObjectiveTimer = 0.0f;
	}

	// Audio diary
	if( s_bShowAudioDiaryPicked )
	{
		m_fAudioDiaryTimer += Asura_Timers::GetGameTimeSlice();
		if( m_fAudioDiaryTimer >= dbg_fTimeToShowAudioDiaryPicked )
		{
			s_bShowAudioDiaryPicked = false;
			m_fAudioDiaryTimer     = 0.0f;
		}
	}
	else
	{
		m_fAudioDiaryTimer = 0.0f;
	}

	if( g_iFrameCounter < 2 )
	{
		g_iFrameCounter ++;
	}

	if( s_bCheckpointReached )
	{
		m_fCheckpointTimer += Asura_Timers::GetGameTimeSlice();
		if( m_fCheckpointTimer >= dbg_fTimeToShowCheckpointReached )
		{
			s_bCheckpointReached = false;
			m_fCheckpointTimer = 0.0f;
		}
	}
	else
	{
		m_fCheckpointTimer = 0.0f;
	}

	// Calculate the weapon accuracy
	if( m_xOwner.IsPlayer() )
	{
		const AVP_Inventory_System* pxInventorySystem = m_xOwner.GetInventorySystem();
		if( pxInventorySystem )
		{
			const AVP_InventoryItem_Weapon*	pxCurrentWeapon = static_cast< const AVP_InventoryItem_Weapon* >( pxInventorySystem->GetCurrentItem(uAVP_INVENTORY_GROUPHASH_WEAPON) );
			if( pxCurrentWeapon && !pxCurrentWeapon->IsEncumberment())
			{
				float fCurrentSpread = 1.0f - pxCurrentWeapon->GetSpreadParametric();
				float fMinSpread = pxCurrentWeapon->GetPrimaryMinSpread();
				float fMaxSpread = pxCurrentWeapon->GetPrimaryMaxSpread();

				if( pxCurrentWeapon->IsUsing( true ) )
				{
					SetHUDAmmoState( HUD_STAT_LOSS );
				}

				s_fWeaponAccuracy = (Asura_Maths::Lerp( fMaxSpread, fMinSpread, fCurrentSpread ) - fMinSpread )/(fMaxSpread - fMinSpread);
				s_bShowWeaponAccuracy = true;
			}
			else
			{
				s_bShowWeaponAccuracy = false;
				s_fWeaponAccuracy = 0.0f; // If we are not holding a weapon we put it at the most accurate state
			}
		}
	}

	const AVP_ClientEntity_PlayerInfo* pxPlayerInfo = AVP_ClientEntity_PlayerInfo::FindEntity( m_xOwner.GetPlayerInfoGuid() );
	if( pxPlayerInfo )
	{
		s_iMissionTimeHours = pxPlayerInfo->GetMissionTimeHours();
		s_iMissionTimeMinutes = pxPlayerInfo->GetMissionTimeMinutes();
		s_iMissionTimeSeconds = pxPlayerInfo->GetMissionTimeSeconds();
	}

#ifdef ASURA_DEBUG_VARIABLE_SYSTEM
	float fTimeStep = Asura_Timers::GetFrameTime();
#else
	float fTimeStep = Asura_Timers::GetGameTimeSlice();
#endif
	const Asura_Vector_3& xCamPos = *Asura_Camera::GetPosition();
	const Asura_Matrix_3x3& xCamOri = *Asura_Camera::GetOrientation();
	for (int i=0; i<MAX_HUD_PHOTONS; ++i)
	{
		if (m_axHUDPhotons[i].m_bRunning && dvs_bUseHUDPhotons)
		{
			if (m_axHUDPhotons[i].m_fFadeInRate > 0.0f)
			{
				m_axHUDPhotons[i].m_fCurrentFade += fTimeStep * m_axHUDPhotons[i].m_fFadeInRate;
				m_axHUDPhotons[i].m_fCurrentFade = Asura_Maths::Min(m_axHUDPhotons[i].m_fCurrentFade, 1.0f);
			}
			else
			{
				m_axHUDPhotons[i].m_fCurrentFade = 1.0f;
			}
			if (!m_axHUDPhotons[i].m_pxPhoton)
			{
				m_axHUDPhotons[i].m_pxPhoton = Asura_Photon_System::CreatePhoton();
			}
		}
		else
		{
			if (m_axHUDPhotons[i].m_fFadeOutRate > 0.0f)
			{
				m_axHUDPhotons[i].m_fCurrentFade -= fTimeStep * m_axHUDPhotons[i].m_fFadeOutRate;
				m_axHUDPhotons[i].m_fCurrentFade = Asura_Maths::Max(m_axHUDPhotons[i].m_fCurrentFade, 0.0f);
			}
			else
			{
				m_axHUDPhotons[i].m_fCurrentFade = 0.0f;
			}
			if (m_axHUDPhotons[i].m_fCurrentFade <= 0.0f)
			{
				if (m_axHUDPhotons[i].m_pxPhoton)
				{
					Asura_Photon_System::DestroyPhoton(m_axHUDPhotons[i].m_pxPhoton);
					m_axHUDPhotons[i].m_pxPhoton = NULL;
				}
			}
		}

		if (m_axHUDPhotons[i].m_pxPhoton)
		{
			if (dvs_bOverrideHUDPhotonSettings)
			{
				m_axHUDPhotons[i].m_pxPhoton->SetColours(dvs_fHUDPhotonOverrideRed * m_axHUDPhotons[i].m_fCurrentFade, dvs_fHUDPhotonOverrideGreen * m_axHUDPhotons[i].m_fCurrentFade, dvs_fHUDPhotonOverrideBlue * m_axHUDPhotons[i].m_fCurrentFade);
				m_axHUDPhotons[i].m_pxPhoton->SetPosition(xCamPos + (Asura_Vector_3(dvs_fHUDPhotonOverrideX, dvs_fHUDPhotonOverrideY, dvs_fHUDPhotonOverrideZ) * xCamOri));
				m_axHUDPhotons[i].m_pxPhoton->SetFalloffPower(dvs_fHUDPhotonOverridePower);
				m_axHUDPhotons[i].m_pxPhoton->SetRange(dvs_fHUDPhotonOverrideRange);
			}
			else
			{
				m_axHUDPhotons[i].m_pxPhoton->SetColours(m_axHUDPhotons[i].m_fRed * m_axHUDPhotons[i].m_fCurrentFade, m_axHUDPhotons[i].m_fGreen * m_axHUDPhotons[i].m_fCurrentFade, m_axHUDPhotons[i].m_fBlue * m_axHUDPhotons[i].m_fCurrentFade);
				m_axHUDPhotons[i].m_pxPhoton->SetPosition(xCamPos + (m_axHUDPhotons[i].m_xCameraOffset * xCamOri));
				m_axHUDPhotons[i].m_pxPhoton->SetFalloffPower(m_axHUDPhotons[i].m_fPower);
				m_axHUDPhotons[i].m_pxPhoton->SetRange(m_axHUDPhotons[i].m_fRange);
			}
		}
	}
}

void AVP_Actor_HUDHandler::UpdateHealth( const AVP_ClientEntity_Actor& xClient )
{
	//Update health bar
	const float fHealth = xClient.GetHealth();
	Asura_Assertf( m_uMaxNumHealthBlocks <= MAX_HUD_HEALTH_ELEMENTS, ( "MAX_HUD_HEALTH_ELEMENTS not big enough for entity %d who wants %d blocks", MAX_HUD_HEALTH_ELEMENTS, xClient.GetGuid(), m_uMaxNumHealthBlocks ) );
	float fHealthParametric = fHealth / m_fHealthPerBlock;
	s_bCaution = fHealthParametric < 1.0f;
	Asura_Assertf( fHealthParametric - dbg_fEpsilon <= m_uMaxNumHealthBlocks, ( "Player doesn't have enough health blocks to have %.0f health", fHealth ) );
	u_int uFullBlocks = Asura_Maths::FloatToInt_Chop( fHealthParametric );
	fHealthParametric -= uFullBlocks;
	for ( u_int uItr = 0; uItr < MAX_HUD_HEALTH_ELEMENTS; ++uItr )
	{
		s_bShowHealth[ uItr ] = uItr < m_uMaxNumHealthBlocks;
		if ( uItr < uFullBlocks )
		{
			s_fHealthParametric[ uItr ] = 1.0f;
		}
		else if ( uItr == uFullBlocks )
		{
			s_fHealthParametric[ uItr ] = fHealthParametric;
		}
		else
		{
			s_fHealthParametric[ uItr ] = 0.0f;
		}
	}

	// Get start and end position of health pointer
	// This must be done for the first couple frames to make sure if the HUD is going to auto resize the new positions are recorded instead of the inital ones. 
// 	if ( m_xNoHealthPos == Asura_Maths::ZeroVector2 || g_iFrameCounter < 2 )
// 	{
// 		Asura_GUIMenu_Element_Image* pxImageItem = static_cast<Asura_GUIMenu_Element_Image*>(AVP_GUIMenu_System::GetHUDElement( AVP_GUIMenu_System::HEALTH_POINTER_EMPTY ) );
// 		if ( pxImageItem )
// 		{
// 			m_xNoHealthPos = pxImageItem->GetScaledWorldPos();
// 		}
// 		pxImageItem = static_cast<Asura_GUIMenu_Element_Image*>(AVP_GUIMenu_System::GetHUDElement( AVP_GUIMenu_System::HEALTH_POINTER_FULL ) );
// 		if ( pxImageItem )
// 		{
// 			m_xFullHealthPos = pxImageItem->GetScaledWorldPos();
// 		}
// 	}
// 
// 	// update health pointer
// 	Asura_GUIMenu_Element_Image* pxImageItem = static_cast<Asura_GUIMenu_Element_Image*>(AVP_GUIMenu_System::GetHUDElement( AVP_GUIMenu_System::HEALTH_POINTER ) );
// 	if( pxImageItem )
// 	{
// 		Asura_Vector_2 xHealthPos;
// 
// 		xHealthPos = m_xFullHealthPos * (fHealth / xClient.GetInitialHealth());
// 		xHealthPos += m_xNoHealthPos * (1.0f - fHealth / xClient.GetInitialHealth());
// 		Asura_Bounding_Rectangle xBounds(pxImageItem->GetScaledWorldBounds());
// 		xBounds.Displace(xHealthPos - xBounds.GetTopLeft());
// 		pxImageItem->SetScaledWorldBounds( xBounds );
// 	}
}

void AVP_Actor_HUDHandler::UpdateFOVModifiers( const AVP_ClientEntity_Actor& xClient )
{
	if ( m_fCurrentSprintFOV != m_fTargetSprintFOV )
	{
		if ( ( m_fTargetSprintFOV - m_fCurrentSprintFOV ) * m_fSprintFOVDecrease > 0.0f )
		{
			m_fCurrentSprintFOV += m_fSprintFOVDecrease * Asura_Timers::GetGameTimeSlice() / m_fSprintFovFadeInTime;
			if ( ( m_fTargetSprintFOV - m_fCurrentSprintFOV ) * m_fSprintFOVDecrease < 0.0f )
			{
				m_fCurrentSprintFOV = m_fTargetSprintFOV;
			}
		}
		else
		{
			m_fCurrentSprintFOV -= m_fSprintFOVDecrease * Asura_Timers::GetGameTimeSlice() / m_fSprintFovFadeOutTime;
			if ( ( m_fTargetSprintFOV - m_fCurrentSprintFOV ) * m_fSprintFOVDecrease > 0.0f )
			{
				m_fCurrentSprintFOV = m_fTargetSprintFOV;
			}
		}
	}

	AVP_Actor_CameraHandler* pxCameraHandler = m_xOwner.GetCameraHandler();
	if ( pxCameraHandler != NULL )
	{
		pxCameraHandler->SetFOVModifier( m_fCurrentSprintFOV, AVP_Actor_CameraHandler::FOVMOD_SPRINT );
	}
}

void AVP_Actor_HUDHandler::Reset()
{
	g_iFrameCounter = 0;
}

void AVP_Actor_HUDHandler::Render( const AVP_ClientEntity_Actor& xClient )
{
	Asura_Font_System::SetTranslucencyMode(ASURA_TRANSLUCENCY_NORMAL);

	//Update screen-sizes
	//This should really be in Update, but the values are not correct until BeginRender is called

	m_fWidth	= (Asura_Viewport::GetWidth()  * Asura_Camera::GetViewingArea()->m_fWidth);
	m_fHeight	= (Asura_Viewport::GetHeight() * Asura_Camera::GetViewingArea()->m_fHeight);
	m_fLeft		= (Asura_Viewport::GetWidth()  * Asura_Camera::GetViewingArea()->m_fXOffset);
	m_fTop		= (Asura_Viewport::GetHeight() * Asura_Camera::GetViewingArea()->m_fYOffset);
	m_fRight	= (m_fLeft + m_fWidth);
	m_fBottom	= (m_fTop + m_fHeight);

	// Render the HUD for multiplayer games if necessary
	if (AVP_Settings::IsMultiPlayer())
	{
		RenderMultiplayerHUD( xClient ); 
	}
}

void AVP_Actor_HUDHandler::SetVisionMode(const AVP_ClientEntity_Actor& xClient,
										 const Asura_Hash_ID uNewBlueprintHash,
										 const bool bInstant)
{
	const Asura_Blueprint*	pxVisionModeBlueprint	= GetInventoryBlueprint(uNewBlueprintHash);
	const Asura_Blueprint*	pxOldVisionModeBlueprint= GetInventoryBlueprint(m_uVisionModeBlueprintHash);
	Asura_Value				xValue;

#if !defined(AVP_SUBMISSION)
	// (AAM - 17.10.2007) In Tools, allow vision modes to be disabled entirely based on console var.
	// People doing debugging work need to see what's going on without e.g. alien fisheye
	if(dvs_bDisableVisionModes) return;
#endif
	const Asura_Hash_ID uOldBlueprintHash = m_uVisionModeBlueprintHash;

	if(uNewBlueprintHash == uOldBlueprintHash) return;

	// Play sound, unless we're setting things up for the first time
	if(!bInstant)
	{

		const Asura_Hash_ID		uDefaultParameterHash	= 0xB09A30CC;	//Asura_GetHashID("VisionMode01");
		const Asura_Blueprint*	pxActorBlueprint		= xClient.GetBlueprint();
		const Asura_Hash_ID		uDefaultBlueprintHash	= ((pxActorBlueprint != NULL) && pxActorBlueprint->GetParameterValueByHashID(uDefaultParameterHash, xValue))
														? xValue.GetHashIDValue()
														: ASURA_HASH_ID_UNSET;

		if (m_iVisionModeChangeSoundHandle != ASURA_INVALID_HANDLE)
		{
			Asura_Sound_Event_System::FinishedWithHandle(m_iVisionModeChangeSoundHandle);
		}

		// Play the one-shot sound...
		if(uOldBlueprintHash == uDefaultBlueprintHash)
		{
			const Asura_Sound_Event*	pxSoundEvent	= xClient.GetSoundEventFromBlueprints(0x63809556);	//Asura_GetHashID("VisionMode.Sound.Enter");

			// Entering vision modes
			if(pxSoundEvent != NULL)
			{
				Asura_Sound_Event_System::PlayEvent(pxSoundEvent, &m_iVisionModeChangeSoundHandle);
			}
		}
		else if(uNewBlueprintHash != uDefaultBlueprintHash)
		{
			const Asura_Sound_Event*	pxSoundEvent	= xClient.GetSoundEventFromBlueprints(0x08CB54F2);	//Asura_GetHashID("VisionMode.Sound.Change");

			// Changing to a different mode
			if(pxSoundEvent != NULL)
			{
				Asura_Sound_Event_System::PlayEvent(pxSoundEvent, &m_iVisionModeChangeSoundHandle);
			}
		}
		else
		{
			const Asura_Sound_Event*	pxSoundEvent	= xClient.GetSoundEventFromBlueprints(0xC96762E0);	//Asura_GetHashID("VisionMode.Sound.Exit");

			// Back to normal vision
			if(pxSoundEvent != NULL)
			{
				Asura_Sound_Event_System::PlayEvent(pxSoundEvent, &m_iVisionModeChangeSoundHandle);
			}
		}
	}

	// Play the looping sound (if we have one...
	Asura_Sound_Event_System::Stop( m_iVisionModeLoopSoundHandle );

	if(pxVisionModeBlueprint != NULL)
	{
		if(pxVisionModeBlueprint->GetParameterValueByHashID(0x32DF1802, xValue))	//Asura_GetHashID("Sound.Looped"), xValue))
		{
			const Asura_Hash_ID	uLoopedSoundHash	= xValue.GetHashIDValue();

			if(uLoopedSoundHash != ASURA_HASH_ID_UNSET)
			{
				const Asura_Sound_Event*	pxSoundEvent	= Asura_Sound_Event_Storage::FindEvent(uLoopedSoundHash);

				Asura_Sound_Event_System::PlayEvent( pxSoundEvent, &m_iVisionModeLoopSoundHandle );
			}
		}
	}

	Asura_Hash_ID uOldMixerHash = ASURA_HASH_ID_UNSET;
	Asura_Hash_ID uNewMixerHash = ASURA_HASH_ID_UNSET;

	if( pxOldVisionModeBlueprint && pxOldVisionModeBlueprint->GetParameterValueByHashID(0x6A3DCBB9, xValue))//Asura_GetHashID("SoundMixerPreset"), xValue))
	{
		if ( xValue.GetHashIDValue() != ASURA_HASH_ID_UNSET )
		{
			uOldMixerHash = xValue.GetHashIDValue();
		}
	}

	if( pxVisionModeBlueprint && pxVisionModeBlueprint->GetParameterValueByHashID(0x6A3DCBB9, xValue))	//Asura_GetHashID("SoundMixerPreset"), xValue))
	{
		if ( xValue.GetHashIDValue() != ASURA_HASH_ID_UNSET )
		{
			uNewMixerHash = xValue.GetHashIDValue();
		}
	}

	if(uOldMixerHash != uNewMixerHash)
	{
		if(uOldMixerHash != ASURA_HASH_ID_UNSET)
		{
			Asura_Sound_Mixer_System::UnqueuePreset(uOldMixerHash, 0.0f);
		}	

		if(uNewMixerHash != ASURA_HASH_ID_UNSET)
		{
			Asura_Sound_Mixer_System::QueuePreset(uNewMixerHash, 0.0f);
		}
	}

	// Pass on to the static one, which is also called by Tools through the menu bar
	AVP_Game_Core::SetVisionMode(uNewBlueprintHash, uOldBlueprintHash, bInstant);

	m_uVisionModeBlueprintHash = uNewBlueprintHash;
}

void AVP_Actor_HUDHandler::SetTorchHDROverride( const Asura_Hash_ID uBlueprintHash )
{
	const Asura_Blueprint*	pxBlueprint	= GetInventoryBlueprint(uBlueprintHash);

	if(pxBlueprint != NULL)
	{
		AVP_Game_Core::GetHDRSettingsFromBlueprint(*pxBlueprint, s_xTorchHDRSettings);

		if ( s_bAllowTorchOverride )
		{
			Asura_Camera::SetHDRSettings( s_xTorchHDRSettings );
		}
	}

	s_bTorchOverride = true;
}

void AVP_Actor_HUDHandler::UnSetTorchHDROverride()
{
	Asura_Camera::SetHDRSettings( AVP_Game_Core::GetVisionModeHDRSettings());
	s_bTorchOverride = false;
}

void AVP_Actor_HUDHandler::OnApplyHealth(const float fHealthIncrement)
{
	if(fHealthIncrement > 10.0f)
	{
		Asura_GUIMenu_Widget_Group*	pxItem	= static_cast<Asura_GUIMenu_Widget_Group*>(AVP_GUIMenu_System::GetHUDElement(static_cast<AVP_GUIMenu_System::STORED_WIDGETS>(AVP_GUIMenu_System::DAMAGE_GP)));

		if(pxItem != NULL)
		{
			Asura_GUIMenu_Animator*	pxAnimator	= pxItem->GetAnimatorBySequenceHash(0x36244AD8);//HealthFade

			m_fHealthFadeTime = 1.1f;
			if(pxAnimator != NULL)
			{
				pxAnimator->Restart();
			}
		}

		SetFSFXAttackSustainDecayValue
		(
			FSFX_STIM,
			uAVP_BLUEPRINT_PARAM_INCREASEHEALTH_FSFX,
			uAVP_BLUEPRINT_PARAM_INCREASEHEALTH_FSFXSTRENGTH,
			uAVP_BLUEPRINT_PARAM_INCREASEHEALTH_FSFXATTACKDURATION,
			uAVP_BLUEPRINT_PARAM_INCREASEHEALTH_FSFXSUSTAINDURATION,
			uAVP_BLUEPRINT_PARAM_INCREASEHEALTH_FSFXDECAYDURATION
		);

		SetHUDHealthState( HUD_STAT_GAIN );
	}
}

DEBUGVAR float dbg_fMinTimeBetweenAcidPFX = 0.2f;

void AVP_Actor_HUDHandler::OnApplyDamage( const AVP_EntityDamage_ApplyToEntity& xDamage )
{
	//Update damage FSFX
	if ( xDamage.GetAmount() > 0.0f )
	{
		m_fDamageFadeTime = 1.1f;
		Asura_GUIMenu_Widget_Group* pxItem = static_cast<Asura_GUIMenu_Widget_Group*>(AVP_GUIMenu_System::GetHUDElement(static_cast<AVP_GUIMenu_System::STORED_WIDGETS>(AVP_GUIMenu_System::DAMAGE_GP)));
		if( pxItem )
		{
			Asura_GUIMenu_Animator* pxAnimator = pxItem->GetAnimatorBySequenceHash(0x963D126B);//DamageFade
			if(pxAnimator)
			{
				pxAnimator->Restart();
			}
		}

		if( xDamage.GetTypeHash() == uAVP_BLUEPRINT_NAME_DAMAGE_PLASMA 
			|| xDamage.GetTypeHash() == uAVP_BLUEPRINT_NAME_DAMAGE_PLASMA_DISRUPTION 
			|| xDamage.GetTypeHash() == uAVP_BLUEPRINT_NAME_DAMAGE_PLASMA_IMPACT )
		{
			s_bShowHitByPlasma = true;
			m_fHitByPlasmaTimer = m_fHitByPlasmaFadeTime;
		}

		if( xDamage.GetTypeHash() == uAVP_BLUEPRINT_NAME_DAMAGE_ACID || AVP_Settings::s_bAcidCheat )
		{
			// Set GUI bool
			s_bShowHitByAcid = true;

			// Play Acid effect if its not been done recently.
			if (m_fHitByAcidTimer < (m_fHitByAcidFadeTime - dbg_fMinTimeBetweenAcidPFX) )
			{
				PlayHitByAcidPFX();
			}

			// Set decay timer for GUI bool
			m_fHitByAcidTimer = m_fHitByAcidFadeTime; 

			// FSFX 
			SetFSFXAttackSustainDecayValue(
				FSFX_ACIDDAMAGE,
				uAVP_BLUEPRINT_PARAM_DAMAGE_FSFX_ACID,
				uAVP_BLUEPRINT_PARAM_DAMAGE_FSFXSTRENGTH_ACID,
				uAVP_BLUEPRINT_PARAM_DAMAGE_FSFXATTACKDURATION_ACID,
				uAVP_BLUEPRINT_PARAM_DAMAGE_FSFXSUSTAINDURATION_ACID,
				uAVP_BLUEPRINT_PARAM_DAMAGE_FSFXDECAYDURATION_ACID
				);
		} 
		else
		{
			SetFSFXAttackSustainDecayValue (
				FSFX_DAMAGE,
				uAVP_BLUEPRINT_PARAM_DAMAGE_FSFX,
				uAVP_BLUEPRINT_PARAM_DAMAGE_FSFXSTRENGTH,
				uAVP_BLUEPRINT_PARAM_DAMAGE_FSFXATTACKDURATION,
				uAVP_BLUEPRINT_PARAM_DAMAGE_FSFXSUSTAINDURATION,
				uAVP_BLUEPRINT_PARAM_DAMAGE_FSFXDECAYDURATION
				);
		}

		SetHUDHealthState( HUD_STAT_LOSS );
	}
}

void AVP_Actor_HUDHandler::OnDeath(const AVP_EntityDamage_ApplyToEntity& xDamage)
{
	SetFSFXValue(FSFX_DEATH, uAVP_BLUEPRINT_PARAM_DEATH_FSFX, uAVP_BLUEPRINT_PARAM_DEATH_FSFXSTRENGTH, uAVP_BLUEPRINT_PARAM_DEATH_FSFXFADEDURATION);
	StopSoundEvent(m_iBreathingLoopHandle);

	// We're dead, close the HUD menu
	AVP_GUIMenu_System::Deactivate(AVP_GUIMenu_System::GUIMENU_ID_HUD);
	AVP_GUIMenu_System::Deactivate(AVP_GUIMenu_System::GUIMENU_ID_WEAPONSELECTOR);
	
	// JG - 01 September 2008 - TODO: Move all this code to a different state handler, different from playing, 
	// where the players stays until it respawns (multiplayer only for now, until single player campaign needs 
	// death cams and that kind of stuff)
	if (AVP_Settings::IsMultiPlayer())
	{
		// Clear all FSFX
		Asura_FSFX_System::ClearAllHandlerTemplates();
		
		// Deathcam vision mode
		SetVisionMode( m_xOwner, uAVP_BLUEPRINT_PARAM_DEATHCAM_VISION_MODE, false );
	}
}


////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Actor_HUDHandler::OnBeginFalling
// Author       : Andy Tate
// Date         : 30-Jun-2008
////////////////////////////////////////////////////////////////////////////////

void AVP_Actor_HUDHandler::OnBeginFalling(void)
{
	StopSoundEvent(m_iAdrenalineLoopHandle);
}

/// End of function 'AVP_Actor_HUDHandler::OnBeginFalling'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Actor_HUDHandler::OnBeginLanding
// Author       : Andy Tate
// Date         : 30-Jun-2008
////////////////////////////////////////////////////////////////////////////////

void AVP_Actor_HUDHandler::OnBeginLanding(void)
{
	StopSoundEvent(m_iAdrenalineLoopHandle);
}

/// End of function 'AVP_Actor_HUDHandler::OnBeginLanding'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Actor_HUDHandler::OnBeginMovingFast
// Author       : Andy Tate
// Date         : 30-Jun-2008
////////////////////////////////////////////////////////////////////////////////

void AVP_Actor_HUDHandler::OnBeginMovingFast(void)
{
	SetFSFXValue(FSFX_SPRINT, uAVP_BLUEPRINT_PARAM_SPRINT_FSFX, 1.0f, 0.5f);
	PlaySoundEvent(uAVP_BLUEPRINT_PARAM_SPRINT_SOUND_BEGIN, NULL);
	PlaySoundEvent(uAVP_BLUEPRINT_PARAM_SPRINT_SOUND_LOOP, &m_iAdrenalineLoopHandle);

	m_fTargetSprintFOV = m_fSprintFOVDecrease;
}

/// End of function 'AVP_Actor_HUDHandler::OnBeginMovingFast'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Actor_HUDHandler::OnEndMovingFast
// Author       : Andy Tate
// Date         : 30-Jun-2008
////////////////////////////////////////////////////////////////////////////////

void AVP_Actor_HUDHandler::OnEndMovingFast(void)
{
	SetFSFXValue(FSFX_SPRINT, uAVP_BLUEPRINT_PARAM_SPRINT_FSFX, 0.0f, 0.5f);
	StopSoundEvent(m_iAdrenalineLoopHandle);
	PlaySoundEvent(uAVP_BLUEPRINT_PARAM_SPRINT_SOUND_END, NULL);

	m_fTargetSprintFOV = 0.0f;
}

/// End of function 'AVP_Actor_HUDHandler::OnEndMovingFast'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Actor_HUDHandler::OnBeginZoomingIn
// Author       : Andy Tate
// Date         : 30-Jun-2008
////////////////////////////////////////////////////////////////////////////////

void AVP_Actor_HUDHandler::OnBeginZoomingIn(const u_int uZoomLevel)
{
	SetFSFXValue(FSFX_ZOOM, uAVP_BLUEPRINT_PARAM_ZOOM_FSFX, 0.5f, 0.5f);
	PlaySoundEvent(uAVP_BLUEPRINT_PARAM_ZOOM_SOUND_ZOOMIN, NULL);
}

/// End of function 'AVP_Actor_HUDHandler::OnBeginZoomingIn'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Actor_HUDHandler::OnBeginZoomingOut
// Author       : Andy Tate
// Date         : 30-Jun-2008
////////////////////////////////////////////////////////////////////////////////

void AVP_Actor_HUDHandler::OnBeginZoomingOut(const u_int uZoomLevel)
{
	SetFSFXValue(FSFX_ZOOM, uAVP_BLUEPRINT_PARAM_ZOOM_FSFX, 0.2f, 0.2f);
	PlaySoundEvent(uAVP_BLUEPRINT_PARAM_ZOOM_SOUND_ZOOMOUT, NULL);
}

/// End of function 'AVP_Actor_HUDHandler::OnBeginZoomingOut'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Actor_HUDHandler::OnEndZooming
// Author       : Andy Tate
// Date         : 30-Jun-2008
////////////////////////////////////////////////////////////////////////////////

void AVP_Actor_HUDHandler::OnEndZooming(const u_int uZoomLevel)
{
	SetFSFXValue(FSFX_ZOOM, uAVP_BLUEPRINT_PARAM_ZOOM_FSFX, 0.0f, 0.5f);
}

/// End of function 'AVP_Actor_HUDHandler::OnEndZooming'. ///

void AVP_Actor_HUDHandler::OnReceiveObjective(const Asura_Guid uObjectiveGuid )
{
	s_uObjectiveToShow = uObjectiveGuid;

	// Reset objective timer
	m_fObjectiveTimer         = 0.0f;
	s_bShowObjective          = true;
	s_bShowObjectiveAdded     = true;
	s_bShowObjectiveCompleted = false;
}

void AVP_Actor_HUDHandler::OnCompleteObjective(const Asura_Guid uObjectiveGuid )
{
	s_uObjectiveToShow = uObjectiveGuid;

	// Reset objective timer
	m_fObjectiveTimer         = 0.0f;
	s_bShowObjective          = true;
	s_bShowObjectiveAdded     = false;
	s_bShowObjectiveCompleted = true;
}

void AVP_Actor_HUDHandler::OnBeginCutscene()
{
	m_bInCutscene = true;

	if ( GetPlayerBlueprint() )
	{
		for ( u_int uItr = 0; uItr < NUM_FSFX_TYPES; ++uItr )
		{
			if ( m_uCurrentFSFXParameterHash[ uItr ] != ASURA_HASH_ID_UNSET )
			{
				AVP_Game_Core::ResetFSFXValue( *GetPlayerBlueprint(), m_uCurrentFSFXParameterHash[ uItr ] );
			}
		}
	}
}

void AVP_Actor_HUDHandler::OnEndCutscene()
{
	m_bInCutscene = false;

	if ( GetPlayerBlueprint() )
	{
		for ( u_int uItr = 0; uItr < NUM_FSFX_TYPES; ++uItr )
		{
			if ( m_uCurrentFSFXParameterHash[ uItr ] != ASURA_HASH_ID_UNSET )
			{
				AVP_Game_Core::SetFSFXValue( *GetPlayerBlueprint(), m_uCurrentFSFXParameterHash[ uItr ], m_fDesiredFSFXValue[ uItr ], 0.0f );
				m_fDesiredFSFXValue[ uItr ] = 0.0f;
				m_uCurrentFSFXParameterHash[ uItr ] = ASURA_HASH_ID_UNSET;
			}
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
// Private functions...
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Protected functions...
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Actor_HUDHandler::GetActorBlueprint
// Author       : Andy Tate
// Date         : 30-Jun-2008
////////////////////////////////////////////////////////////////////////////////

const Asura_Blueprint* AVP_Actor_HUDHandler::GetActorBlueprint(void) const
{
	return Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_ACTORS, m_xOwner.GetBlueprintHashID());
}

/// End of function 'AVP_Actor_HUDHandler::GetActorBlueprint'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Actor_HUDHandler::GetPlayerBlueprint
// Author       : Andy Tate
// Date         : 30-Jun-2008
////////////////////////////////////////////////////////////////////////////////

const Asura_Blueprint* AVP_Actor_HUDHandler::GetPlayerBlueprint(void) const
{
	return Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_PLAYERS, m_xOwner.GetBlueprintHashID());
}

/// End of function 'AVP_Actor_HUDHandler::GetPlayerBlueprint'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Actor_HUDHandler::GetInventoryBlueprint
// Author       : Andy Tate
// Date         : 30-Jun-2008
////////////////////////////////////////////////////////////////////////////////

const Asura_Blueprint* AVP_Actor_HUDHandler::GetInventoryBlueprint(const Asura_Hash_ID uItemHash)
{
	return Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_INVENTORY_ITEMS, uItemHash);
}

/// End of function 'AVP_Actor_HUDHandler::GetInventoryBlueprint'. ///

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Actor_HUDHandler::ConsoleCmd_GetPlayerName
// Author       : Fredrik Svensson
// Date         : 06-Apr-2009
////////////////////////////////////////////////////////////////////////////////

bool AVP_Actor_HUDHandler::ConsoleCmd_GetPlayerName( bool bHelp )
{
	if( bHelp )
	{
		Asura_CommandConsole::Printf(L"Gets the player name, platform specific and mode specific for SP or MP");
		return true;
	}
	else
	{
		if( AVP_Settings::IsMultiPlayer() )
		{
			#ifdef ASURA_SUPPORT_LOBBY
			Asura_CommandConsole::Printf(L"%s", Asura_Lobby_System::GetLocalPlayerName() );
			#endif // ASURA_SUPPORT_LOBBY
			return true;
		}
		else
		{
			const AVP_Profile* pxProfile = AVP_Settings::GetCurrentProfile();
			Asura_String xString = pxProfile->GetName().GetString();
			Asura_CommandConsole::Printf( "%s", xString.GetString() );
			return true;
		}
	}
}

/// End of function 'AVP_Actor_HUDHandler::ConsoleCmd_GetPlayerName'. ///

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Actor_HUDHandler::PlaySoundEvent
// Author       : Andy Tate
// Date         : 30-Jun-2008
////////////////////////////////////////////////////////////////////////////////

bool AVP_Actor_HUDHandler::PlaySoundEvent(const Asura_Blueprint& xBlueprint,
										  const Asura_Hash_ID uSoundParameterHash,
										  Asura_Handle* piHandle)
{
	Asura_Value	xValue;

	if(uSoundParameterHash == ASURA_HASH_ID_UNSET)
	{
		Asura_Assert(false, "Parameter-hash not filled in when attempting to play a sound-event.");
		return(false);
	}
	else if(xBlueprint.GetParameterValueByHashID(uSoundParameterHash, xValue))
	{
		const Asura_Hash_ID	uSoundEventHash	= xValue.GetHashIDValue();

		if(uSoundEventHash == ASURA_HASH_ID_UNSET)
		{
			return(false);
		}
		else
		{
			const Asura_Sound_Event*	pxSoundEvent	= Asura_Sound_Event_Storage::FindEvent(uSoundEventHash);

			Asura_Assert( piHandle == NULL || *piHandle == ASURA_INVALID_HANDLE, "Handle already set for this sound, not going to play as it will cause a mem leak and probably crash xaudio" );
			if ( piHandle == NULL || *piHandle == ASURA_INVALID_HANDLE )
			{
				Asura_Sound_Event_System::PlayEvent(pxSoundEvent, piHandle);
				return(true);
			}
			else
			{
				return(false);
			}
		}
	}
	else
	{
		return(false);
	}
}

/// End of function 'AVP_Actor_HUDHandler::PlaySoundEvent'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Actor_HUDHandler::PlaySoundEvent
// Author       : Andy Tate
// Date         : 30-Jun-2008
////////////////////////////////////////////////////////////////////////////////

bool AVP_Actor_HUDHandler::PlaySoundEvent(const Asura_Hash_ID uSoundParameterHash,
										  Asura_Handle* piHandle)
{
	const Asura_Blueprint*	pxBlueprint	= GetPlayerBlueprint();

	if(pxBlueprint == NULL)
	{
		return(false);
	}
	else
	{
		return(PlaySoundEvent(*pxBlueprint, uSoundParameterHash, piHandle));
	}
}

/// End of function 'AVP_Actor_HUDHandler::PlaySoundEvent'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Actor_HUDHandler::StopSoundEvent
// Author       : Andy Tate
// Date         : 30-Jun-2008
////////////////////////////////////////////////////////////////////////////////

void AVP_Actor_HUDHandler::StopSoundEvent(Asura_Handle& iHandle)
{
	Asura_Sound_Event_System::Stop(iHandle);
}


////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Actor_HUDHandler::SetFSFXValue
// Author       : Andy Tate
// Date         : 30-Jun-2008
////////////////////////////////////////////////////////////////////////////////

bool AVP_Actor_HUDHandler::SetFSFXValue(const FSFXType eType,
										const Asura_Hash_ID uFSFXParameterHash,
										const float fValue,
										const float fTime)
{
	m_fDesiredFSFXValue[ eType ] = fValue;
	m_uCurrentFSFXParameterHash[ eType ] = uFSFXParameterHash;
	if ( m_bInCutscene )
	{
		return true;
	}

	const Asura_Blueprint*	pxBlueprint	= GetPlayerBlueprint();

	if(pxBlueprint == NULL)
	{
		return(false);
	}
	else
	{
		return(AVP_Game_Core::SetFSFXValue(*pxBlueprint, uFSFXParameterHash, fValue, fTime));
	}
}
// Date         : 18-Jul-2008
////////////////////////////////////////////////////////////////////////////////

bool AVP_Actor_HUDHandler::SetFSFXValue(const FSFXType eType,
										const Asura_Hash_ID uFSFXParameterHash,
										const Asura_Hash_ID uValueParameterHash,
										const Asura_Hash_ID uTimeParameterHash)
{
	const Asura_Blueprint*	pxBlueprint	= GetPlayerBlueprint();

	if(pxBlueprint == NULL)
	{
		return(false);
	}
	else
	{
		Asura_Value	xValue;

		if(pxBlueprint->GetParameterValueByHashID(uValueParameterHash, xValue))
		{
			const float	fValue	= xValue.GetFloatValue();
			const float	fTime	= pxBlueprint->GetParameterValueByHashID(uTimeParameterHash, xValue)
								? xValue.GetFloatValue()
								: 0.0f;

			return(SetFSFXValue(eType, uFSFXParameterHash, fValue, fTime));
		}
		else
		{
			return(false);
		}
	}
}

/// End of function 'AVP_Actor_HUDHandler::SetFSFXValue'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Actor_HUDHandler::SetFSFXAttackSustainDecayValue
// Author       : Andy Tate
// Date         : 30-Jun-2008
////////////////////////////////////////////////////////////////////////////////

bool AVP_Actor_HUDHandler::SetFSFXAttackSustainDecayValue(const FSFXType eType,
														  const Asura_Hash_ID uFSFXParameterHash,
														  const Asura_Hash_ID uStrengthParameterHash,
														  const Asura_Hash_ID uAttackDurationParameterHash,
														  const Asura_Hash_ID uSustainDurationParameterHash,
														  const Asura_Hash_ID uDecayDurationParameterHash)
{
	m_fDesiredFSFXValue[ eType ] = 0.0f;
	m_uCurrentFSFXParameterHash[ eType ] = uFSFXParameterHash;

	if ( m_bInCutscene )
	{
		return true;
	}

	const Asura_Blueprint*	pxBlueprint	= GetPlayerBlueprint();

	if(pxBlueprint == NULL)
	{
		return(false);
	}
	else
	{
		Asura_Value	xValue;

		if(uFSFXParameterHash == ASURA_HASH_ID_UNSET)
		{
			Asura_Assert(false, "Parameter-hash not filled in when attempting to set a FSFX.");
			return(false);
		}
		else if(pxBlueprint->GetParameterValueByHashID(uFSFXParameterHash, xValue))
		{
			const Asura_Hash_ID	uFSFXHash	= xValue.GetHashIDValue();

			if(uFSFXHash == ASURA_HASH_ID_UNSET)
			{
				return(false);
			}
			else
			{
				float	fStrength			= 1.0f;
				float	fAttackDuration		= 0.0f;
				float	fSustainDuration	= 0.0f;
				float	fDecayDuration		= 0.0f;

				if(pxBlueprint->GetParameterValueByHashID(uStrengthParameterHash, xValue))
				{
					fStrength	= xValue.GetFloatValue();
				}
				if(pxBlueprint->GetParameterValueByHashID(uAttackDurationParameterHash, xValue))
				{
					fAttackDuration	= xValue.GetFloatValue();
				}
				if(pxBlueprint->GetParameterValueByHashID(uSustainDurationParameterHash, xValue))
				{
					fSustainDuration	= xValue.GetFloatValue();
				}
				if(pxBlueprint->GetParameterValueByHashID(uDecayDurationParameterHash, xValue))
				{
					fDecayDuration	= xValue.GetFloatValue();
				}

				AVP_Game_Core::GetFSFXHandler()->SetAttackSustainDecayValues(uFSFXHash, fStrength, 0.0f, fAttackDuration, fSustainDuration, fDecayDuration);
				return(true);
			}
		}
		else
		{
			return(false);
		}
	}
}

/// End of function 'AVP_Actor_HUDHandler::SetFSFXAttackSustainDecayValue'. ///




/// End of function 'AVP_Actor_HUDHandler::ResetFSFXValue'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Actor_HUDHandler::ResetFSFXValue
// Author       : Andy Tate
// Date         : 30-Jun-2008
////////////////////////////////////////////////////////////////////////////////

bool AVP_Actor_HUDHandler::ResetFSFXValue(const FSFXType eType, const Asura_Hash_ID uParameterHash)
{
	m_fDesiredFSFXValue[ eType ] = 0.0f;
	m_uCurrentFSFXParameterHash[ eType ] = ASURA_HASH_ID_UNSET;

	if ( m_bInCutscene )
	{
		return true;
	}

	const Asura_Blueprint*	pxBlueprint	= GetPlayerBlueprint();

	if(pxBlueprint == NULL)
	{
		return(false);
	}
	else
	{
		return(AVP_Game_Core::ResetFSFXValue(*pxBlueprint, uParameterHash));
	}
}

bool AVP_Actor_HUDHandler::IsHUDEnabled(void)
{
	return s_bHUDEnabled;
}

void AVP_Actor_HUDHandler::SetHUDEnabled(const bool bSet)	
{ 
	if ( s_bHUDEnabled != bSet )
	{
		s_bHUDEnabled = bSet;
		Asura_Hash_ID uHUDHash =  AVP_GUIMenu_System::GetMenuHash( AVP_GUIMenu_System::GUIMENU_ID_HUD );
		Asura_GUIMenu_System::SetMenuPageActiveByID( uHUDHash, bSet );

		if( s_bHUDSubLevelLoaded && s_uCurrentHUDSubLevelPage )
		{
			// if a hud sub level has been loaded make sure it is shown/not shown as well. 
			Asura_GUIMenu_System::SetMenuPageActiveByID( s_uCurrentHUDSubLevelPage, bSet );
		}

		//if (AVP_Settings::IsMultiPlayer())
		//{
		//	Asura_GUIMenu_System::SetMenuPageActiveByID( s_uAVP_MULTIPLAYER_GENERIC_HUD_MENU, bSet ); 
		//}
	}
}

bool* AVP_Actor_HUDHandler::GetShowWeaponSelectorConsoleVarPtr()
{
	return &s_bShowWeaponSelector;
}

void AVP_Actor_HUDHandler::SetHUDHealthState( u_int uHUDHealthState )
{
	s_uHUDHealthState = uHUDHealthState;
	s_fHealthStateTimer = 0.0f;
}

void AVP_Actor_HUDHandler::SetHUDAmmoState( u_int uHUDAmmoState )
{
	s_uHUDAmmoState = uHUDAmmoState;
	s_fAmmoStateTimer = 0.0f;
}

void AVP_Actor_HUDHandler::SetHUDEnergyState( u_int uHUDEnergyState )
{
	s_uHUDEnergyState = uHUDEnergyState;
	s_fEnergyStateTimer = 0.0f;
}

void AVP_Actor_HUDHandler::RenderMultiplayerHUD( const AVP_ClientEntity_Actor& xClient )
{
	// Get local player info 
	Asura_Guid uLocalPlayerGuid = AVP_Game_Core::GetPlayerGuid();
	AVP_ClientEntity_PlayerInfo* pxLocalPlayerInfo  = AVP_ClientEntity_PlayerInfo::FindEntity( uLocalPlayerGuid ); 

	if (!pxLocalPlayerInfo)
	{
		Asura_Assert( pxLocalPlayerInfo, "Couldn't find local player info while rendering multiplayer HUD" );
		return; 
	}
	
	// Loop through all players info
	const Asura_Hashed_List<AVP_ClientEntity_PlayerInfo>* pxPlayerInfoList = AVP_ClientEntity_PlayerInfo::GetList(); 
	Asura_Hashed_List_ConstIt<AVP_ClientEntity_PlayerInfo> xPlayerInfoListConstIt( pxPlayerInfoList ); 
	while (!xPlayerInfoListConstIt.Done())
	{
		// Current player info
		const AVP_ClientEntity_PlayerInfo* pxCurrentPlayerInfo = xPlayerInfoListConstIt.GetCurrent(); 
		xPlayerInfoListConstIt.Next();

		if (pxCurrentPlayerInfo)
		{
			// Skip the local player 
			if (pxCurrentPlayerInfo->GetGuid() == pxLocalPlayerInfo->GetGuid()) continue;

			// Find this player puppet
			Asura_Guid uCurrentPlayerPuppetGuid = pxCurrentPlayerInfo->GetPuppetGuid(); 
			if (uCurrentPlayerPuppetGuid != ASURA_GUID_UNREGISTERED)
			{
				AVP_ClientEntity_Actor* pxCurrentPlayerPuppet = AVP_ClientEntity_Actor::FindEntity( uCurrentPlayerPuppetGuid ); 
				if (pxCurrentPlayerPuppet)
				{				
					// Player puppet position
					Asura_Vector_3 xCurrentPlayerWorldPosition( pxCurrentPlayerPuppet->GetCurrentPosition() ); 

					// Player name position
					xCurrentPlayerWorldPosition.SetY( xCurrentPlayerWorldPosition.GetY() - 2.0f );
					
					// Projected player position on screen
					Asura_Vector_3 xCurrentPlayerScreenPosition( xCurrentPlayerWorldPosition );
					Asura_Camera::ProjectWorldCoordsToScreenSpace( xCurrentPlayerScreenPosition, true ); 

					u_int uPlayerColour = 0xFFFFFFFF; 
					bool bShowPlayerName = false;
					bool bShowPlayerMarker = false; 
					bool bIsMarkerInScreen = Asura_Camera::IsSphereInFrustum(xCurrentPlayerWorldPosition, 0.25f);

					// Don't show markers if they are outside the screen
					if (bIsMarkerInScreen)
					{
						AVP_GUIMenu_System::STORED_WIDGETS uPlayerIcon = AVP_GUIMenu_System::MULTIPLAYER_ENEMY_ARROW; 

						// Team based game?			
						if (AVP_Multiplayer_GameRules::IsTeamBasedGame())
						{
							uPlayerColour = 0xFFFF0000; // Enemy team colour: RED

							// Render HUD info over player team mates
							if (pxCurrentPlayerInfo->GetMultiplayerTeam() == pxLocalPlayerInfo->GetMultiplayerTeam())
							{
								uPlayerColour = 0xFF0000FF; // Player team colour: BLUE
								uPlayerIcon = AVP_GUIMenu_System::MULTIPLAYER_TEAM_ARROW; 
								bShowPlayerName = true;		// Always show team mate names in team based games
								bShowPlayerMarker = true; 
							}	
						}	

						// Persecutor!
						if (pxLocalPlayerInfo->GetPersecutorGuid() == pxCurrentPlayerInfo->GetGuid())
						{
							uPlayerIcon = AVP_GUIMenu_System::MULTIPLAYER_PERSECUTOR_ARROW; 
							bShowPlayerMarker = true;
						}
					
						if (bShowPlayerMarker)
						{
							// GUIMenu icons
							Asura_GUIMenu_Root* pxItem = AVP_GUIMenu_System::GetHUDElement( uPlayerIcon, s_uAVP_MULTIPLAYER_GENERIC_HUD_MENU, false );
							if( pxItem )
							{
								Asura_GUIMenu_Element_Image* pxImageItem = static_cast<Asura_GUIMenu_Element_Image*>(pxItem);
								if ( pxImageItem )
								{
									Asura_Bounding_Rectangle xNewBoundingBox( pxImageItem->GetScaledWorldBounds() ); 
									Asura_Vector_2 xInstancePosition( xCurrentPlayerScreenPosition.GetX(), xCurrentPlayerScreenPosition.GetY() ); 
									Asura_Vector_2 xIconOrigin( pxImageItem->GetPosOrigin() );
									Asura_Vector_2 xIconSize( xNewBoundingBox.GetDimension() ); 
									xIconOrigin.x *= xIconSize.x;
									xIconOrigin.y *= xIconSize.y;
									Asura_Vector_2 xInstanceDisplacement = xInstancePosition - ( pxImageItem->GetScaledWorldPos() + xIconOrigin );
									xNewBoundingBox.Displace( xInstanceDisplacement );
									pxImageItem->Render( ASURA_GUIMENU_ACTION_FLAG_ALL, xNewBoundingBox );
								}
							}
						}
				
						// Check proximity before rendering player names
						float fDistanceSquaredToPlayer = (xClient.GetCurrentPosition() - xCurrentPlayerWorldPosition).MagnitudeSquared();
						bShowPlayerName = bShowPlayerName && fDistanceSquaredToPlayer < 400.0f; 
						if (bShowPlayerName)
						{
							const Asura_UnicodeChar* pwcCurrentPlayerName = pxCurrentPlayerInfo->GetPlayerName();

							// TODO: add proper HUD stuff here, debug info for now
							Asura_Font_System::Print( xCurrentPlayerScreenPosition.GetX(), xCurrentPlayerScreenPosition.GetY(), uPlayerColour,
								ASURA_TEXTFORMAT_CENTREJUSTIFIED | ASURA_TEXTFORMAT_FORMATSTRING, "%S", pwcCurrentPlayerName );
						}
					}
				}
				else
				{
					Asura_Assert( pxCurrentPlayerPuppet, "Invalid player actor found while rendering multiplayer HUD" ); 
				}
			}
			else
			{
				// Valid, i.e. this player is dead and hasn't respawned yet
			}
		}
		else
		{
			Asura_Assert( pxCurrentPlayerInfo, "Invalid player info found while rendering multiplayer HUD" ); 
		}
	}
}

#if defined(ASURA_TOOLS)
bool AVP_Actor_HUDHandler::IsCnsl_bForceFixedExposure()
{
	return dvs_bForceFixedExposure;
}

#endif // ASURA_TOOLS

void AVP_Actor_HUDHandler::PlayHitByAcidPFX()
{
	static const Asura_Hash_ID uMarkerHashID = 0x002FBC62; // Asura_GetHashID("eyes")
	const Asura_Blueprint*	pxBlueprint	= GetPlayerBlueprint();
	if(pxBlueprint)
	{
		Asura_Value xTempValue;
		if(pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_DAMAGE_PFX_ACID, xTempValue))
		{
			m_xOwner.AttachPFX(uMarkerHashID, xTempValue.GetHashIDValue(), true);
		} 
		else
		{
			Asura_Assert(false, "AVP_Actor_HUDHandler *ACID DMG* couldnt find acid PFX.");
		}
	}
	else
	{
		Asura_Assert(false ,"AVP_Actor_HUDHandler *ACID DMG* couldnt find player blueprint.");
	}
}

u_int AVP_Actor_HUDHandler::ApplyCameraPhoton(const Asura_Vector_3& xCameraOffset, float fRed, float fGreen, float fBlue, float fFadeInTime, float fFadeOutTime, float fPower, float fRange)
{
	// Find a slot/update an existing slot (if position is roughly the same we assume the intention was a continuation) and put our photon there.
	// Return the index plus 1, since ID 0 is used to mean invalid.
	u_int uBestIndex = 0;
	bool bFoundValidSlot = false;
	for (u_int u=0; u<MAX_HUD_PHOTONS; ++u)
	{
		if (m_axHUDPhotons[u].m_pxPhoton)
		{
			// Photon exists, see if we should overwrite (do this regardless if we've found an earlier empty slot.
			if (xCameraOffset.ApproximatelyEquals(m_axHUDPhotons[u].m_xCameraOffset))
			{
				uBestIndex = u;
				bFoundValidSlot = true;
			}
		}
		else if (!bFoundValidSlot)
		{
			// First empty slot.
			uBestIndex = u;
			bFoundValidSlot = true;
		}
	}

	if (bFoundValidSlot)
	{
		m_axHUDPhotons[uBestIndex].m_xCameraOffset = xCameraOffset;
		m_axHUDPhotons[uBestIndex].m_fRed = fRed;
		m_axHUDPhotons[uBestIndex].m_fGreen = fGreen;
		m_axHUDPhotons[uBestIndex].m_fBlue = fBlue;
		m_axHUDPhotons[uBestIndex].m_fFadeInRate = (fFadeInTime > 0.0f) ? (1.0f / fFadeInTime) : 0.0f;
		m_axHUDPhotons[uBestIndex].m_fFadeOutRate = (fFadeOutTime > 0.0f) ? (1.0f / fFadeOutTime) : 0.0f;
		m_axHUDPhotons[uBestIndex].m_fPower = fPower;
		m_axHUDPhotons[uBestIndex].m_fRange = fRange;
		m_axHUDPhotons[uBestIndex].m_bRunning = true; // Leave the fade value alone in case this is a continuation.

		return uBestIndex + 1;
	}
	else
	{
		return 0;
	}
}

void AVP_Actor_HUDHandler::FinishCameraPhoton(u_int uPhotonID)
{
	if (uPhotonID == 0)
	{
		return;
	}
	else
	{
		// Just flag as no longer running, the update will handle the rest.
		m_axHUDPhotons[uPhotonID - 1].m_bRunning = false;
	}
}

/// End of file. ///
