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

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

#include "Core/Asura.h"

// This file's header...
#include "Entity/PhysicalObject/Actor/Vertebrates/Predator/AVP_ClientActor_Predator.h"

// Asura independent header-files...
#include "Blueprint/Asura_Blueprint.h"
#include "Blueprint/Asura_Blueprint_System.h"
#if defined(ASURA_USE_MATERIAL_RESPONSE_SYSTEM)
#include "Core/Asura_MaterialResponse_System.h"
#endif	// defined(ASURA_USE_MATERIAL_RESPONSE_SYSTEM)
#include "Core/Asura_Timers.h"
#include "Network/Asura_Message.h"
#include "Rendering/Asura_Font_System.h"
#include "Rendering/Asura_Viewport.h"
#include "SpecialFX/Asura_Decal_Manager.h"
#include "Animation/Asura_AnimationBlend.h"
#include "Animation/Asura_AnimationController_Animation.h"
#include "Core/Asura_Timers.h"

// Game independent header-files...
#include "Actor/AVP_Actor_Selector.h"
#include "Actor/AVP_Actor_InteractionHandler.h"
#include "Actor/AVP_Actor_PickupHandler.h"
#include "Actor/Vertebrates/AVP_Vertebrate_Description.h"
#include "Actor/Vertebrates/AVP_Vertebrate_HUDHandler.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_AIAnimStateData.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_AnimationHandler.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_CameraHandler.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_Description.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_Focus.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_HUDHandler.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_InputHandler.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_InteractionHandler.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_JumpHandler.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_MeleeCounter_System.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_PlayerAnimStateData.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_PlayerAnimStateHandler.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_Recon.h"
#include "Blueprint/AVP_Blueprint_HashIDs.h"
#include "Core/AVP_Game_Core.h"
#include "Entity/AVP_Entity_Classification.h"
#include "Entity/AVP_Messages.h"
#include "Entity/Damage/AVP_EntityDamage_Apply.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Predator/AVP_Messages_Predator.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Predator/AVP_ServerActor_Predator.h"
#include "Entity/PhysicalObject/Projectile/AVP_ClientProjectile_Disc.h"
#include "Inventory/AVP_Inventory_Group.h"
#include "Inventory/AVP_Inventory_HashIDs.h"
#include "Inventory/AVP_Inventory_System.h"
#include "Inventory/Items/AVP_InventoryItem_PredatorCloak.h"
#include "Inventory/Items/AVP_InventoryItem_Stim.h"
#include "Inventory/Items/AVP_InventoryItem_Weapon.h"
#include "Inventory/Items/Weapons/AVP_InventoryWeapon_Disc.h"
#include "Mesh/AVP_PolygonFlags.h"
#include "Moves/AVP_Move_Interaction.h"
#include "Moves/AVP_Movement_System.h"
#include "Moves/Vertebrates/Predator/AVP_Predator_MovesBranch.h"
#include "Moves/Vertebrates/Predator/AVP_Predator_MovesJump.h"
#include "Moves/Vertebrates/Predator/AVP_Predator_MovesInteraction.h"
#include "Moves/Vertebrates/Predator/AVP_Predator_MovesMelee.h"
#include "SpecialFX/AVP_CloakEffect.h"

#define NUM_WEAPON_SLOTS 4

#define NUM_VISION_SLOTS 4

////////////////////////////////////////////////////////////////////////////////
// Constant declarations...
////////////////////////////////////////////////////////////////////////////////
//DVSVAR float	dvs_fDownwardMovementMultiplier		= 1.0f; // temp

// Predator stats refill/drain speeds...

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

Asura_Hashed_List<AVP_ClientActor_Predator>	AVP_ClientActor_Predator::s_xList;

static const int g_aiWeaponSelectorKey[ NUM_WEAPON_SLOTS ] = 
{
	AVP_Actor_InputHandler::WEAPON_SELECTOR_SLOT_UP,
	AVP_Actor_InputHandler::WEAPON_SELECTOR_SLOT_RIGHT,
	AVP_Actor_InputHandler::WEAPON_SELECTOR_SLOT_DOWN,
	AVP_Actor_InputHandler::WEAPON_SELECTOR_SLOT_LEFT
};

static const AVP_GUIMenu_System::STORED_WIDGETS g_aeWeaponSelectorSlotGuiElement[ NUM_WEAPON_SLOTS ] = 
{
	AVP_GUIMenu_System::WEAPON_SELECTOR_SLOT_UP,
	AVP_GUIMenu_System::WEAPON_SELECTOR_SLOT_RIGHT,
	AVP_GUIMenu_System::WEAPON_SELECTOR_SLOT_DOWN,
	AVP_GUIMenu_System::WEAPON_SELECTOR_SLOT_LEFT
};

static const AVP_Actor_Selector::Selector_Directions g_aiWeaponValidSlots[ NUM_WEAPON_SLOTS ] = 
{
	AVP_Actor_Selector::SELECTOR_TOP,
	AVP_Actor_Selector::SELECTOR_RIGHT,
	AVP_Actor_Selector::SELECTOR_BOTTOM,
	AVP_Actor_Selector::SELECTOR_LEFT,
};

// static const AVP_GUIMenu_System::STORED_WIDGETS g_aeWeaponSelectorSlotHighlightGuiElement[ NUM_WEAPON_SLOTS ] =
// {
// 	AVP_GUIMenu_System::WEAPON_SELECTOR_SLOT_UP_HIGHLIGHT,
// 	AVP_GUIMenu_System::WEAPON_SELECTOR_SLOT_RIGHT_HIGHLIGHT,
// 	AVP_GUIMenu_System::WEAPON_SELECTOR_SLOT_DOWN_RIGHT_HIGHLIGHT,
// 	AVP_GUIMenu_System::WEAPON_SELECTOR_SLOT_DOWN_LEFT_HIGHLIGHT,
// 	AVP_GUIMenu_System::WEAPON_SELECTOR_SLOT_LEFT_HIGHLIGHT
// };

static const int g_aiVisionSelectorKey[ NUM_VISION_SLOTS ] = 
{
	AVP_Actor_InputHandler::VISION_SELECTOR_SLOT_UP,
	AVP_Actor_InputHandler::VISION_SELECTOR_SLOT_RIGHT,
	AVP_Actor_InputHandler::VISION_SELECTOR_SLOT_DOWN,
	AVP_Actor_InputHandler::VISION_SELECTOR_SLOT_LEFT,
};

static const AVP_GUIMenu_System::STORED_WIDGETS g_aeVisionSelectorSlotGuiElement[ NUM_VISION_SLOTS ] = 
{
	AVP_GUIMenu_System::VISION_SELECTOR_SLOT_UP,
	AVP_GUIMenu_System::VISION_SELECTOR_SLOT_RIGHT,
	AVP_GUIMenu_System::VISION_SELECTOR_SLOT_DOWN,
	AVP_GUIMenu_System::VISION_SELECTOR_SLOT_LEFT
};

////////////////////////////////////////////////////////////////////////////////
// Function Declarations...
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_ClientActor_Predator::RefillEnergy
// Author       : Andy Tate
// Date         : 6-Oct-2006
////////////////////////////////////////////////////////////////////////////////

float AVP_ClientActor_Predator::RefillEnergy(const float fTimeStep,
											  const float fCurrent,
											  const float fDifference,
											  const float fChargeParameter)
{
	return fCurrent + ( fChargeParameter * fTimeStep );
}

/// End of function 'AVP_ClientActor_Predator::RefillEnergy'. ///

bool AVP_ClientActor_Predator::InitialiseInventory(void)
{
	if(PARENT::InitialiseInventory())
	{
		AVP_Inventory_Group*	pxPermanentlyActiveGroup	= m_pxInventorySystem->GetPermanentlyActiveItemGroup();
		AddPermenantlyActiveItems(pxPermanentlyActiveGroup);

		if ( AVP_Game_Core::IsLocalPlayer( GetGuid() ) )
		{
			m_pxWeaponSelector = new AVP_Actor_Selector( *this, NUM_WEAPON_SLOTS, g_aiWeaponSelectorKey, g_aiWeaponValidSlots, uAVP_INVENTORY_GROUPHASH_WEAPON, AVP_Actor_HUDHandler::GetShowWeaponSelectorConsoleVarPtr() );
			m_pxWeaponSelector->SetSlotGuiElements( g_aeWeaponSelectorSlotGuiElement );
	
			/*m_pxVisionSelector = new AVP_Actor_Selector( *this, NUM_VISION_SLOTS, g_aiVisionSelectorKey, NULL, uAVP_INVENTORY_GROUPHASH_VISIONMODE, AVP_Predator_HUDHandler::GetShowVisionSelectorConsoleVarPtr() );
			m_pxVisionSelector->SetSlotGuiElements( g_aeVisionSelectorSlotGuiElement );
			m_pxVisionSelector->SetControlMap( &( GetInputHandler()->GetMapVisionSelector() ) );*/
		}

		return(true);
	}
	else
	{
		return(false);
	}
}

void AVP_ClientActor_Predator::AddPermenantlyActiveItems(AVP_Inventory_Group* pxGroup)
{
	AVP_InventoryItem_Cloak* pxCloak = new AVP_InventoryItem_Cloak(*pxGroup);
	if ( pxCloak )
	{
		pxCloak->InitialiseFromBlueprint();
	}

	const Asura_Blueprint* pxBlueprint = GetBlueprint();
	if(pxBlueprint != NULL)
	{
		Asura_Value	xValue;
		if(pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_STIM, xValue))
		{
			AVP_InventoryItem_Stim* pxStim = new AVP_InventoryItem_Stim(*pxGroup, xValue.GetHashIDValue(), "Stim");
			if ( pxStim )
			{
				pxStim->InitialiseFromBlueprint();
			}
		}
	}
}

bool AVP_ClientActor_Predator::InitialiseMoves( void )
{
	if(PARENT::InitialiseMoves())
	{
		Asura_Movement_System& xMovementSystem = *m_pxMovementSystem;

		// Melee Moves. Most of these require information from the wristblades blueprint.
		const AVP_Inventory_System* pxInventory = GetInventorySystem();
		if (pxInventory)
		{
			const AVP_InventoryGroup_Weapons* pxWeaponsGroup = static_cast<const AVP_InventoryGroup_Weapons*>(pxInventory->GetGroup(uAVP_INVENTORY_GROUPHASH_WEAPON));
			if (pxWeaponsGroup)
			{
				const AVP_Inventory_Item* pxMeleeItem = pxWeaponsGroup->GetItemOfType(AVP_INVENTORYITEMTYPE_WEAPON_MELEE);
				if (pxMeleeItem)
				{
					const Asura_Blueprint* pxBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_INVENTORY_ITEMS, pxMeleeItem->GetBlueprintHash());
					if (pxBlueprint)
					{
						Asura_Value xValue;
						Asura_Hash_ID uFirstPersonMeleeBlueprintHash = ASURA_HASH_ID_UNSET;
						Asura_Hash_ID uThirdPersonMeleeBlueprintHash = ASURA_HASH_ID_UNSET;
						if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_MELEE_FIRSTPERSON, xValue))
						{
							uFirstPersonMeleeBlueprintHash = xValue.GetHashIDValue();
						}
						if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_MELEE_THIRDPERSON, xValue))
						{
							uThirdPersonMeleeBlueprintHash = xValue.GetHashIDValue();
						}

						new AVP_Predator_Move_Melee_Wristblade_SlowAttack(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);

						new AVP_Predator_Move_Melee_FarCounter(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);

						new AVP_Predator_Move_Melee_CounterAlienJumpAttack_Throw_Left(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_CounterAlienJumpAttack_Throw_Right(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_CounterAlienJumpAttack_Hit_Left(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_CounterAlienJumpAttack_Hit_Right(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);

						AVP_Move_Melee_Pounce_Attack_Return_Countered* pxCounteredMove = new AVP_Move_Melee_Pounce_Attack_Return_Countered(xMovementSystem);
						AVP_Move_Melee_Pounce_Attack_Return_Miss* pxMissMove = new AVP_Move_Melee_Pounce_Attack_Return_Miss(xMovementSystem);
						AVP_Move_Melee_Pounce_Attack_Return_Hit* pxHitMove = new AVP_Move_Melee_Pounce_Attack_Return_Hit(xMovementSystem);
						AVP_Move_Melee_Pounce_Attack_Start* pxStartMove = new AVP_Move_Melee_Pounce_Attack_Start(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						// These moves need some additional set up from our blueprints.
						if (pxStartMove && pxHitMove && pxCounteredMove && pxMissMove)
						{
							AVP_Blueprint_ParameterEnumerator_PounceVariations_MoveData xEnumerator(uAVP_BLUEPRINT_TYPE_MOVESPREDATOR, *pxStartMove, *pxHitMove, *pxCounteredMove, *pxMissMove);
							pxBlueprint->EnumerateParameters(AVP_Vertebrate_MeleeCounter_System::GetPounceAttackBaseParameterName(), 2, xEnumerator);
						}

						new AVP_Predator_Move_Melee_QuickFinisher_Return_Countered(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_QuickFinisher_Return_Miss(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_QuickFinisher_Return_Hit(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_QuickFinisher_Start(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);

						new AVP_Predator_Move_Melee_Wristblade_QuickAttack_Return_Countered(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_Wristblade_QuickAttack_Return_Miss(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_Wristblade_QuickAttack_Return_Hit(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_Wristblade_QuickAttack_Start(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);

						new AVP_Predator_Move_Melee_Wristblade_PowerAttack_Return_Countered(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_Wristblade_PowerAttack_Return_Miss(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_Wristblade_PowerAttack_Return_Hit(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_Wristblade_PowerAttack_Start(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);

						new AVP_Predator_Move_MeleeCharge_End(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_MeleeCharge_Loop(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_MeleeCharge_Start(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);

						new AVP_Predator_Move_Melee_PickupHuman_Return_Hit(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_PickupHuman_Return_Countered(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_PickupHuman_Return_Miss(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_PickupHuman_Start(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);

						new AVP_Predator_Move_Melee_StealthPickupHuman_Return_Hit(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_StealthPickupHuman_Return_Countered(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_StealthPickupHuman_Return_Miss(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_StealthPickupHuman_Start(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);

						new AVP_Predator_Move_Melee_PickupDownedAlien_Return_Hit(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_PickupDownedAlien_Return_Countered(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_PickupDownedAlien_Return_Miss(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_PickupDownedAlien_Start(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);

						new AVP_Predator_Move_Melee_PickupAlienCrouching_Return_Hit(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_PickupAlienCrouching_Return_Countered(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_PickupAlienCrouching_Return_Miss(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_PickupAlienCrouching_Start(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);

						new AVP_Predator_Move_Melee_PickupAlienStanding_Return_Hit(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_PickupAlienStanding_Return_Countered(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_PickupAlienStanding_Return_Miss(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_PickupAlienStanding_Start(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);

						new AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Return_Hit(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Return_Countered(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Return_Miss(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Start(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);

						new AVP_Predator_Move_Melee_StealthPickupAlienStanding_Return_Hit(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_StealthPickupAlienStanding_Return_Countered(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_StealthPickupAlienStanding_Return_Miss(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_StealthPickupAlienStanding_Start(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
					

						// predalien pounce / grapple
						new AVP_Predator_Move_Melee_PredalienPounceAttack_Return_Miss(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_PredalienPounceAttack_Return_Countered(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_PredalienPounceAttack_Return_Hit(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_PredalienPounceAttack_Grapple1(xMovementSystem);
						new AVP_Predator_Move_Melee_PredalienPounceAttack_Start1(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_PredalienPounceAttack_Grapple2(xMovementSystem);
						new AVP_Predator_Move_Melee_PredalienPounceAttack_Start2(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
						new AVP_Predator_Move_Melee_PredalienPounceAttack_GrappleKill(xMovementSystem);
						new AVP_Predator_Move_Melee_PredalienPounceAttack_StartKill(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);

						// predalien counters
						new AVP_Predator_Move_Melee_CounterPredalienLeftClawAttack(xMovementSystem);
						new AVP_Predator_Move_Melee_CounterPredalienRightClawAttack(xMovementSystem);
						new AVP_Predator_Move_Melee_CounterPredalienJumpDownAttack(xMovementSystem);
						new AVP_Predator_Move_Melee_CounterPredalienTailSwipe(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);

					}
				}
			}
		}

		new AVP_Predator_Move_Melee_CounterAlienLeftClawAttack(xMovementSystem);
		new AVP_Predator_Move_Melee_CounterAlienRightClawAttack(xMovementSystem);

		new AVP_Predator_Move_Melee_CounterAlienStandingTailStab_Kill(xMovementSystem);
		new AVP_Predator_Move_Melee_CounterAlienStandingTailStab_Countered(xMovementSystem);
		new AVP_Predator_Move_Melee_CounterAlienStandingTailStab_Start(xMovementSystem);

		new AVP_Predator_Move_Melee_CounterAlienPounceAttack(xMovementSystem);

		new AVP_Predator_Move_Melee_CounterAlienCrawlStandAttackLeft(xMovementSystem);
		new AVP_Predator_Move_Melee_CounterAlienCrawlStandAttackRight(xMovementSystem);

		// Jump moves
		new AVP_Move_Predator_JumpTarget(xMovementSystem);
		new AVP_Move_Predator_PreJumpTarget(xMovementSystem);


		// Branch moves
		new AVP_Move_Predator_MountBranch(xMovementSystem);
		new AVP_Move_Predator_DismountBranch(xMovementSystem);

		// Interaction moves
		// Lock
		new AVP_Predator_Move_Interaction_StandStill(xMovementSystem);
		new AVP_Predator_Move_Interaction_PlugKey(xMovementSystem);
		new AVP_Predator_Move_Interaction_UnPlugKey(xMovementSystem);
		new AVP_Predator_Move_Interaction_TurnLeft(xMovementSystem);
		new AVP_Predator_Move_Interaction_TurnRight(xMovementSystem);

		// Battery
		new AVP_Predator_Move_Interaction_UseBattery(xMovementSystem);

		// Retinal scanner
		new AVP_Predator_Move_Interaction_UseHead(xMovementSystem);
		Asura_Move* pxIntMove = xMovementSystem.GetMove( AVP_Move_Interaction_BeginWeaponAway::GetStaticHash() );
		Asura_Assert( pxIntMove, "" );
		if ( pxIntMove )
		{
			pxIntMove->AddNextMove( AVP_Predator_Move_Interaction_UseHead::GetStaticHash() );
			pxIntMove->AddNextMove( AVP_Predator_Move_Interaction_UseBattery::GetStaticHash() );
		}



		return(true);
	}
	else
	{
		return(false);
	}
}



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

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_ClientActor_Predator::AVP_ClientActor_Predator
// Author       : Andy Tate
// Date         : 3-Oct-2006
////////////////////////////////////////////////////////////////////////////////

AVP_ClientActor_Predator::AVP_ClientActor_Predator()
: AVP_ClientActor_Vertebrate(AVP_PolygonFlag_IgnoreForPredatorCollision)
, m_pxWeaponSelector(NULL)
//, m_pxVisionSelector(NULL)
, m_uDiscGuid( ASURA_GUID_UNREGISTERED )
, m_uHeldProjectileGuid( ASURA_GUID_UNREGISTERED )
, m_uTargetGuid( ASURA_GUID_UNREGISTERED )
, m_bLockOn( false )
, m_xDynamicEnergy(100.0f, 0.0f, 100.0f)
, m_fEnergyRechargePerSec(10.0f)
, m_fEnergyDurationBeforeRefill(1.0f)
, m_fFallingSpeedThreshold(10.0f)
, m_fEnergyLossDueToFall(50.0f)
, m_fEnergyLossOnTargetedJump(50.0f)
, m_fCloakedEnergyDrainStanding( 0.0f )
, m_fCloakedEnergyDrainWalking( 0.0f )
, m_fCloakedEnergyDrainRunning( 0.0f )
, m_fCloakedEnergyDrainSprinting( 0.0f )
, m_uPredatorFlags(0)
{
	Classification = AVP_ENTITYCLASS_PREDATOR;

	// Initialise the entity...
	SetTimeLagType(TimeLag_LocalPlayer);

	// Don't forget to store us in the list...
	s_xList.AddToList(this);
}

/// End of function 'AVP_ClientActor_Predator::AVP_ClientActor_Predator'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_ClientActor_Predator::~AVP_ClientActor_Predator
// Author       : Andy Tate
// Date         : 3-Oct-2006
////////////////////////////////////////////////////////////////////////////////

AVP_ClientActor_Predator::~AVP_ClientActor_Predator ()
{
	// Remove whatever we need to...
	delete(m_pxWeaponSelector);
	//delete(m_pxVisionSelector);

	// if the recon mode has been attached to this predator entity then unattach it. 
	if ( IsPlayer() )
	{
		if( ( AVP_Predator_Recon::GetRecon().GetOwnerSet() ) && ( GetGuid() == AVP_Predator_Recon::GetRecon().GetOwnerGuid() ) )
		{
			AVP_Predator_Recon::GetRecon().SetOwner( NULL );
		}
	}

	// Don't forget to remove us from the list...
	s_xList.RemoveFromList(this);
}

/// End of function 'AVP_ClientActor_Predator::~AVP_ClientActor_Predator'. ///


void AVP_ClientActor_Predator::ReadFromClientCreateStream(Asura_Chunk_Memory_Stream& xStream, float fServerTime)
{
	u_int uVersion = 0;
	xStream >> uVersion;

	Asura_Assert(uVersion <= AVP_ServerActor_Predator::CURRENT_CLIENTCREATE_VERSION, "Bad chunk version in predator client create!");

	// Call the base-function...
	PARENT::ReadFromClientCreateStream( xStream, fServerTime );

	float fEnergy;
	xStream >> fEnergy;

	m_xDynamicEnergy.Set(fEnergy, true);
}

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_ClientActor_Predator::ProcessClientUpdate
// Author       : Andy Tate
// Date         : 17-Oct-2006
////////////////////////////////////////////////////////////////////////////////

void AVP_ClientActor_Predator::ProcessClientUpdate(const AVP_Message_PredatorClientUpdate* pxData,
													const float fServerTime,
													const bool bProcessPosAndOri)
{
	// Call the base-function...
	PARENT::ProcessClientUpdate( pxData, fServerTime, bProcessPosAndOri );
	
	// Handle the predator...
	m_uDiscGuid					= pxData->GetDiscGuid();
	m_uHeldProjectileGuid		= pxData->GetHeldProjectileGuid();
	m_eAlertLevel				= static_cast<AVP_ClientActor_Vertebrate::AVP_AlertLevel>( pxData->GetAlertLevel() );
	m_uTargetGuid				= pxData->GetTargetGuid(); 
	m_bLockOn					= pxData->IsLockOn(); 

	if ( !AVP_Game_Core::IsLocalPlayer( GetGuid() ))
	{
		SetCrouching( pxData->IsCrouching(), false );
	}
	AVP_Vertebrate_HUDHandler::SetGrabTargetInRange( pxData->GetEnemyInMeleeRange() );
	AVP_Vertebrate_HUDHandler::SetPounceTargetInRange( pxData->IsInPounceRange() );
}

/// End of function 'AVP_ClientActor_Predator::ProcessClientUpdate'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_ClientActor_Predator::ProcessClientPickup
// Author       : Andy Tate
// Date         : 2-Nov-2006
////////////////////////////////////////////////////////////////////////////////

void AVP_ClientActor_Predator::ProcessClientPickup(const AVP_Message_ActorClientPickup* pxData,
													const float fServerTime)
{
	if(pxData != NULL)
	{
		Asura_Assert(false, "Unexpected type of pickup.");

//		const Asura_Guid			uPickupGuid		= pxData->GetPickupGuid();
//		const Asura_Entity_Client*	pxClient		= Asura_Entity_Client::FindEntity(uPickupGuid);
//		const u_int					uClassification	= pxClient->GetClassification();
//
//		// What sort of pick-up is it?
//		switch(uClassification)
//		{
//			default:
//			{
//				Asura_Assert(false, "Unexpected type of pickup.");
//				break;
//			}
//		}
	}
}

/// End of function 'AVP_ClientActor_Predator::ProcessClientPickup'. ///



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

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_ClientActor_Predator::Create
// Author       : Andy Tate
// Date         : 3-Oct-2006
////////////////////////////////////////////////////////////////////////////////

AVP_ClientActor_Predator* AVP_ClientActor_Predator::Create(const Asura_Message* pxMessage)
{
	AVP_ClientActor_Predator*	pxClient	= new AVP_ClientActor_Predator;

	// Initialise the entity...
	pxClient->HandleMessage(pxMessage);

	// Return the entity...
	return(pxClient);
}

/// End of function 'AVP_ClientActor_Predator::Create'. ///

void AVP_ClientActor_Predator::PostCreateInitialise(void)
{
	//If we do not have an animation handler yet, create it so we can set the skin.
	if ( !m_pxAnimationHandler && GetBlueprintHashID() != ASURA_HASH_ID_UNSET )
	{
		CreateAnimationHandler();
	}

	PARENT::PostCreateInitialise();

	if ( IsPlayer() )
	{
		if ( m_pxPlayerStateHandler == NULL )
		{
			m_pxPlayerStateHandler = new AVP_Predator_PlayerAnimStateHandler( *this );
		}
		m_pxPlayerStateHandler->Initialise();

		// As a seperate issue if this is the local player then initialise the predator recon mode as well. 
		AVP_Predator_Recon::GetRecon().PostPlayerCreateInitialise();
	}
}


////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_ClientActor_Predator::Update
// Author       : Andy Tate
// Date         : 3-Oct-2006
////////////////////////////////////////////////////////////////////////////////

void AVP_ClientActor_Predator::Update(void)
{
	// Firstly, ensure that the parent is up-to-date...
	PARENT::Update();

	if (!m_bDeadBody)
	{
		// Update all energy related stuff
		UpdatePredatorEnergy();

		// Update Predator Recon Mode if this is the player predator. 
		if( IsPlayer() )
		{
			if( ( AVP_Predator_Recon::GetRecon().GetOwnerSet() ) && ( GetGuid() == AVP_Predator_Recon::GetRecon().GetOwnerGuid() ) )
			{
				AVP_Predator_Recon::GetRecon().UpdatePredRecon();
			}
		}
	}
}

/// End of function 'AVP_ClientActor_Predator::Update'. ///

void AVP_ClientActor_Predator::UpdatePredatorEnergy(void)
{
	// Update the dynamic energy
	const float	fTimeStep	= Asura_Timers::GetGameTimeSlice();
	m_xDynamicEnergy.Update(fTimeStep, m_fEnergyRechargePerSec, NULL, RefillEnergy);

	// And attempt to refill if not in use
	if(m_xDynamicEnergy.GetTimeAtDesiredValue() > m_fEnergyDurationBeforeRefill)
	{
		if(!IsCloaked(true))
		{
			m_xDynamicEnergy.SetToMaximum(false);
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_ClientActor_Predator::HandleMessage
// Author       : Andy Tate
// Date         : 3-Oct-2006
////////////////////////////////////////////////////////////////////////////////

bool AVP_ClientActor_Predator::HandleMessage(const Asura_Message* pxMessage)
{
	// What sort of message is it?
	switch(pxMessage->GetMsgID())
	{
	case ASURA_MSG_CLIENTUPDATE:
		{
			const bool	bIsLocalPlayer	= IsPlayer() && AVP_Game_Core::IsLocalPlayer(GetPlayerInfoGuid());

			ProcessClientUpdate(static_cast<const AVP_Message_PredatorClientUpdate*>(pxMessage->GetData()), pxMessage->GetSentTime(), !bIsLocalPlayer);
			return(true);
		}

	case AVP_MSGID_PICKUP_DISC:
		{
			ProcessClientPickup(static_cast<const AVP_Message_ActorClientPickup*>(pxMessage->GetData()), pxMessage->GetSentTime());
			return(true);
		}

	case AVP_MSGID_DISC_LASER_TRACKING_OFF:	// FALL THROUGHT !!!!
	case AVP_MSGID_DISC_LASER_TRACKING_ON:
		{
			AVP_InventoryItem_Weapon* pxCurrentWeapon = m_pxInventorySystem ? static_cast<AVP_InventoryItem_Weapon*>(m_pxInventorySystem->GetCurrentItem(uAVP_INVENTORY_GROUPHASH_WEAPON)) : NULL;
			if ( pxCurrentWeapon ) 
			{ 
				// Just make sure that it is disc;
				if( pxCurrentWeapon->GetItemType()==AVP_INVENTORYITEMTYPE_PREDATORDISC )
				{
					AVP_InventoryWeapon_Disc* pxDisc = static_cast<AVP_InventoryWeapon_Disc*>(pxCurrentWeapon);

					bool bLaserTrackingModeOn = pxMessage->GetMsgID() == AVP_MSGID_DISC_LASER_TRACKING_ON ? true : false;

					pxDisc->SetLaserTargetMode( bLaserTrackingModeOn );
				}
			}

			return(true);
		}

	case AVP_MSGID_REQUEST_INTERACTION:
		{
			Asura_Assert(false, "Shouldn't get here.");
			return(true);
		}

	case AVP_MSGID_REPLENISH_PREDATOR_ENERGY:
		{
			m_xDynamicEnergy.SetMax( m_fMaxEnergy );
			m_xDynamicEnergy.SetToMaximum(true);
			return(true);
		}

	case AVP_MSGID_REQUEST_CLOAK_ON:
		{
			if ( AVP_Game_Core::IsLocalPlayer( GetGuid() ) )
			{
				AVP_Inventory_System*			pxInvSys = GetInventorySystem();
				AVP_InventoryItem_Cloak*		pxCloak = pxInvSys ? static_cast< AVP_InventoryItem_Cloak* >( pxInvSys->GetItem( uAVP_INVENTORY_ITEMHASH_CLOAK ) ) : NULL;
				Asura_Assert( pxCloak, "No cloak found" );
				if ( pxCloak )
				{
					if ( pxCloak->IsIdling( true ) && GetDynamicEnergy() && GetDynamicEnergy()->GetCurrentValue() > 0.0f )
					{
						pxCloak->RequestBeginUsage( AVP_InventoryItem_Cloak::UT_CLOAK, AVP_InventoryItem_Cloak::TT_AUTOMATIC );
					}
				}
			}
			return true;
		}

	case AVP_MSGID_REQUEST_CLOAK_OFF:
		{
			if ( AVP_Game_Core::IsLocalPlayer( GetGuid() ) )
			{
				AVP_Inventory_System*			pxInvSys = GetInventorySystem();
				AVP_InventoryItem_Cloak*		pxCloak = pxInvSys ? static_cast< AVP_InventoryItem_Cloak* >( pxInvSys->GetItem( uAVP_INVENTORY_ITEMHASH_CLOAK ) ) : NULL;
				Asura_Assert( pxCloak, "No cloak found" );
				if ( pxCloak )
				{
					if ( pxCloak->IsUsing( true ) )
					{
						pxCloak->RequestEndUsage( AVP_InventoryItem_Cloak::TT_AUTOMATIC );
					}
				}
			}
		}
		return true;

	default:
		{
			return(PARENT::HandleMessage(pxMessage));
		}
	}		// End of switch.
}

/// End of function 'AVP_ClientActor_Predator::HandleMessage'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_ClientActor_Predator::RenderHUD
// Author       : Andy Tate
// Date         : 6-Oct-2006
////////////////////////////////////////////////////////////////////////////////
void AVP_ClientActor_Predator::RenderHUD(void) const
{
	PARENT::RenderHUD();

	AVP_Predator_Recon::GetRecon().RenderPredRecon();
}

/// End of function 'AVP_ClientActor_Predator::RenderHUD'. ///


////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_ClientActor_Predator::OnBeginTargetedJump
// Author       : Andy Tate
// Date         : 14-Dec-2006
////////////////////////////////////////////////////////////////////////////////

void AVP_ClientActor_Predator::OnBeginTargetedJump(void)
{
	AVP_Predator_HUDHandler*	pxHUDHandler	= static_cast<AVP_Predator_HUDHandler*>(m_pxHUDHandler);

	if(pxHUDHandler != NULL)
	{
		pxHUDHandler->OnBeginTargetedJump();
	}

	m_xDynamicEnergy.Remove(m_fEnergyLossOnTargetedJump, false);
}

/// End of function 'AVP_ClientActor_Predator::OnBeginTargetedJump'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_ClientActor_Predator::OnEndTargetedJump
// Author       : Andy Tate
// Date         : 30-Jun-2008
////////////////////////////////////////////////////////////////////////////////

void AVP_ClientActor_Predator::OnEndTargetedJump(void)
{
	AVP_Predator_HUDHandler*	pxHUDHandler	= static_cast<AVP_Predator_HUDHandler*>(m_pxHUDHandler);

	if(pxHUDHandler != NULL)
	{
		pxHUDHandler->OnEndTargetedJump();
	}
}

/// End of function 'AVP_ClientActor_Predator::OnEndTargetedJump'. ///


////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_ClientActor_Predator::OnApplyDamage
// Author       : Chris Wallace
// Date         : 19-Dec-2008
////////////////////////////////////////////////////////////////////////////////

void AVP_ClientActor_Predator::OnApplyDamage(const AVP_EntityDamage_ApplyToEntity& xDamage)
{
	PARENT::OnApplyDamage(xDamage);

	AVP_Vertebrate_CameraHandler* pxCameraHandler = static_cast< AVP_Vertebrate_CameraHandler* >( GetCameraHandler() );

	if ( xDamage.GetAmount() > 0.0f )
	{
		if ( pxCameraHandler && xDamage.GetAmount() > 0.0f )
		{
			pxCameraHandler->SetZoomLevel( *this, 0 );
		}
	}
}

/// End of function 'AVP_ClientEntity_Actor::OnApplyDamage'. ///

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_ClientActor_Predator::OnBeginLanding
// Author       : Chris Wallace
// Date         : 14-Dec-2006
////////////////////////////////////////////////////////////////////////////////

void AVP_ClientActor_Predator::OnBeginLanding(void)
{
	Asura_Vector_3 xVel;
	GetCurrentVelocity(xVel);
	float fSpeed = xVel.y;

	if(fSpeed > m_fFallingSpeedThreshold)
	{
		m_xDynamicEnergy.Remove(m_fEnergyLossDueToFall, false);
	}
	
	PARENT::OnBeginLanding();
}

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_ClientActor_Predator::MakePlayer
// Author       : Chris Wallace
// Date         : 5-Feb-2007
////////////////////////////////////////////////////////////////////////////////

void AVP_ClientActor_Predator::MakePlayer(Asura_Guid uPlayerGuid)
{
	if (uPlayerGuid == m_uPlayerInfoGuid) { return; }
	// Check if all local players on this machine is aware of their puppets yet, since MakePlayer can fall over if they aren't.
	if (!AVP_Game_Core::GetCanMakePlayerActors()) { return; }

	const bool bLocalPlayer = AVP_Game_Core::IsLocalPlayer(uPlayerGuid);

	PARENT::MakePlayer(uPlayerGuid);

	if( m_pxPlayerStateHandler == NULL )
	{
		m_pxPlayerStateHandler = new AVP_Predator_PlayerAnimStateHandler( *this );
	}
	m_pxPlayerStateHandler->Initialise();

	if (bLocalPlayer)
	{
		if(!m_pxCameraHandler)
		{
			m_pxCameraHandler	= new AVP_Predator_CameraHandler(Guid);	
			m_pxCameraHandler->Reset();
		}

		if(!m_pxHUDHandler)
		{
			m_pxHUDHandler	= new AVP_Predator_HUDHandler(*this);
		}

		if(!m_pxInputHandler)
		{
			m_pxInputHandler	= new AVP_Predator_InputHandler(Guid);
			m_pxInputHandler->Reset();
			if (m_pxInputHandler)
			{
				m_pxInputHandler->RefreshBlueprintData();
			}
		}

		if(!m_pxJumpHandler)
		{
			m_pxJumpHandler		= new AVP_Predator_JumpHandler(*this);
		}

		if (!m_pxFocus)
		{
			m_pxFocus = new AVP_Predator_Focus(*this);
		}

		if (!m_pxInteractionHandler)
		{
			m_pxInteractionHandler = new AVP_Predator_InteractionHandler(*this);
		}

		// Initialise recon mode for this predator player in single player games only
		if (AVP_Settings::IsSinglePlayer())
		{
			AVP_Predator_Recon::GetRecon().SetOwner( this );
		}
	}
}

/// End of function 'AVP_ClientActor_Predator::MakePlayer'. ///

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_ClientActor_Predator::MakeAI
// Author       : Chris Wallace
// Date         : 5-Feb-2007
////////////////////////////////////////////////////////////////////////////////

void AVP_ClientActor_Predator::MakeAI()
{
	PARENT::MakeAI();
}

/// End of function 'AVP_ClientActor_Predator::MakeAI'. ///

void AVP_ClientActor_Predator::OnBeginJumping(void)
{
	PARENT::OnBeginJumping();
}

void AVP_ClientActor_Predator::OnCountering(void)
{

}


void AVP_ClientActor_Predator::UpdateLock( void )
{
}

void AVP_ClientActor_Predator::CreateAnimationHandler()
{
	Asura_Assert( m_pxAnimationHandler == NULL, "Already got an animation handler" );
	m_pxAnimationHandler = new AVP_Predator_AnimationHandler(*this);
	m_pxAnimationHandler->Initialise();
}

void AVP_ClientActor_Predator::InitialiseFromBlueprint( const Asura_Blueprint& xBlueprint )
{
    PARENT::InitialiseFromBlueprint( xBlueprint );

    Asura_Value xValue;
    if(xBlueprint.GetParameterValueByHashID(0xFBF83CEC, xValue))	//Asura_GetHashID("MaxEnergy"), xValue))
    {
		m_fMaxEnergy = xValue.GetFloatValue();
        m_xDynamicEnergy.SetMax( m_fMaxEnergy );
        m_xDynamicEnergy.SetToMaximum(true);
    }
	if(xBlueprint.GetParameterValueByHashID(0x2a03535a, xValue))	//Asura_GetHashID("MinEnergy"), xValue))
	{
		m_fMinEnergy = xValue.GetFloatValue();
	}
	if ( xBlueprint.GetParameterValueByHashID( uAVP_BLUEPRINT_PARAM_NUMENERGYBLOCKS, xValue ) )
	{
		m_fEnergyPerBlock = m_fMaxEnergy / xValue.GetIntValue();
	}

	if ( xBlueprint.GetParameterValueByHashID(0x8f79c3a1, xValue) )	// Energy.RechargePerSec
	{
		m_fEnergyRechargePerSec = xValue.GetFloatValue();
	}

	if ( xBlueprint.GetParameterValueByHashID(0xc349f5af, xValue) )	// Energy.DurationBeforeRefill
	{
		m_fEnergyDurationBeforeRefill = xValue.GetFloatValue();
	}

	if(xBlueprint.GetParameterValueByHashID(0x6EBD2A1F, xValue))	//Asura_GetHashID("EnergyLossDueToFall"), xValue))
	{
		m_fEnergyLossDueToFall = xValue.GetFloatValue();
	}
	if(xBlueprint.GetParameterValueByHashID(0x08dbf805, xValue))	//Asura_GetHashID("EnergyLossOnTargetedJump"), xValue))
	{
		m_fEnergyLossOnTargetedJump = xValue.GetFloatValue();
	}
	if(xBlueprint.GetParameterValueByHashID(0xF22DB863, xValue))	//Asura_GetHashID("FallSpeedForEnergyLossThreshold"), xValue))
	{
		m_fFallingSpeedThreshold = xValue.GetFloatValue();
	}
}


void AVP_ClientActor_Predator::GetCurrentBlockBlueprintHashes(Asura_Hash_ID& uBlueprintTypeHash, Asura_Hash_ID& uFirstPersonBlueprintHash, Asura_Hash_ID& uThirdPersonBlueprintHash) const
{
	uBlueprintTypeHash = uAVP_BLUEPRINT_TYPE_MOVESPREDATOR;
	uFirstPersonBlueprintHash = uThirdPersonBlueprintHash = ASURA_HASH_ID_UNSET;

	const AVP_InventoryItem_Weapon* pxCurrentWeapon = m_pxInventorySystem ? static_cast<const AVP_InventoryItem_Weapon*>(m_pxInventorySystem->GetCurrentItem(uAVP_INVENTORY_GROUPHASH_WEAPON)) : NULL;
	if (!pxCurrentWeapon) { return; }

	const Asura_Blueprint* pxBlueprint = pxCurrentWeapon->GetBlueprint();
	if (!pxBlueprint) { return; }

	Asura_Value xValue;

	// The predator has one special case - the wristblades have two poses to choose between. Wristblades are our only melee weapon type.
	if (m_bEnemyInMeleeRange && (pxCurrentWeapon->GetItemType() == AVP_INVENTORYITEMTYPE_WEAPON_MELEE))
	{
		// There's an enemy in melee range, so we're in the ready pose. Choose the other block set.
		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_BLOCKWRISTBLADESREADY_FIRSTPERSON, xValue))
		{
			uFirstPersonBlueprintHash = xValue.GetHashIDValue();
		}

		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_BLOCKWRISTBLADESREADY_THIRDPERSON, xValue))
		{
			uThirdPersonBlueprintHash = xValue.GetHashIDValue();
		}
		return;
	}

	// Otherwise, use the standard parameter ids.
	if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_BLOCK_FIRSTPERSON, xValue))
	{
		uFirstPersonBlueprintHash = xValue.GetHashIDValue();
	}

	if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_BLOCK_THIRDPERSON, xValue))
	{
		uThirdPersonBlueprintHash = xValue.GetHashIDValue();
	}
}

bool AVP_ClientActor_Predator::IsBoneInTorso( const int iBoneID )
{
	return AVP_Predator_Description::GetElementFromBoneID( iBoneID ) == AVP_SET_BODY;
}

void AVP_ClientActor_Predator::GetFootPosition( u_int uFootItr, Asura_Vector_3& xFootPos )
{
	if ( m_pxAnimationHandler )
	{
		m_pxAnimationHandler->GetAnimation()->GetBoneLocation( AVP_Predator_Description::GetFootBoneID( uFootItr, m_pxAnimationHandler->IsFirstPerson() ), &xFootPos, NULL, true );
	}
}


DEBUGVAR float dbg_fTargetedJumpLowTestsYOffset = -0.5f;
DEBUGVAR float dbg_fTargetedJumpLowTestsXOffset = 0.25f;

bool AVP_ClientActor_Predator::GetCanUseTargetedJump(const Asura_Vector_3& xTargetPosition, int& iJumpVariation) const
{
	const Asura_Blueprint* pxBlueprint = GetCurrentTargetedJumpBlueprint();
	if (!pxBlueprint) { return false; }

	// To simplify our approximation, just use the y part of the head marker offset. Should still be good enough.
	// Since the jump may change our orientation and look values, attempting to be exact here is pretty much always going to fail.
	Asura_Vector_3 xHeadOffset;
	if (!GetMarkerLocationFromHash(AVP_Vertebrate_Description::GetMarkerPointHashID(AVP_Vertebrate_Description::MPID_EYES), &xHeadOffset, NULL, false)) { return false; }

	const Asura_Vector_3& xMyPos = GetCurrentPosition();

	Asura_Vector_3 xFlatOffset = xTargetPosition - xMyPos;
	const float fHeightOffset = Asura_Maths::Abs(xFlatOffset.y);
	const float fHeightOffsetSign = Asura_Maths::Sign(xFlatOffset.y);
	xFlatOffset.y = 0.0f;
	const float fFlatDistanceSquared = xFlatOffset.MagnitudeSquared();

	if (fFlatDistanceSquared < 0.001f) { return false; }

	Asura_Matrix_3x3 xFlatOri;
	Asura_Maths::OrientationFromDirection(xFlatOri, xFlatOffset); // This normalises the vector internally, so no need to do so in advance.

	Asura_Vector_3 xStarts[3];
	Asura_Vector_3 xTargets[3];
	Asura_Vector_3 xMidpoints[3];

	const Asura_Vector_3 xHeadHeightOffset(0.0f, xHeadOffset.y, 0.0f);
	const Asura_Vector_3 xLowLeftOffset(-dbg_fTargetedJumpLowTestsXOffset, dbg_fTargetedJumpLowTestsYOffset, 0.0f);
	const Asura_Vector_3 xLowRightOffset(dbg_fTargetedJumpLowTestsXOffset, dbg_fTargetedJumpLowTestsYOffset, 0.0f);

	xStarts[0] = xMyPos + xHeadHeightOffset;
	xTargets[0] = xTargetPosition + xHeadHeightOffset;
	xStarts[1] = xMyPos + (xLowLeftOffset * xFlatOri);
	xTargets[1] = xTargetPosition + (xLowLeftOffset * xFlatOri);
	xStarts[2] = xMyPos + (xLowRightOffset * xFlatOri);
	xTargets[2] = xTargetPosition + (xLowRightOffset * xFlatOri);

	for (int i=0; i<3; ++i)
	{
		xMidpoints[i] = (xStarts[i] + xTargets[i]) * 0.5f;
	}

	Asura_Value xValue;
	float fBestMaxFlatDistanceSquared = Asura_Maths::LargeFloat;
	float fBestMinHeightChange = 0.0f; // This will always be positive, regardless of the sign of the actual change.
	float fBestHeadroom = 0.0f;
	int iBestVariation = -1;

	for (int i=0; i<pxBlueprint->GetNumParameters(); ++i)
	{
		if (pxBlueprint->GetParameterValueByIndex(i, xValue))
		{
			const Asura_Blueprint* pxVariationBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MOVESPREDATOR, xValue.GetHashIDValue());
			if (!pxVariationBlueprint) { continue; }

			float fMaxFlatDistanceSquared;
			float fMinHeightChange;
			float fHeadroom;

			if (!pxVariationBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_MAXDISTANCE, xValue)) { continue; }
			fMaxFlatDistanceSquared = xValue.GetFloatValue();
			fMaxFlatDistanceSquared *= fMaxFlatDistanceSquared;

			if (!pxVariationBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_HEIGHTCHANGE, xValue)) { continue; }
			fMinHeightChange = xValue.GetFloatValue();

			if (!pxVariationBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_HEADROOM, xValue)) { continue; }
			fHeadroom = xValue.GetFloatValue();

			// First, make sure its height change is appropriate. 0 height change is always a valid option.
			if ((fMinHeightChange != 0.0f) && (fHeightOffsetSign != Asura_Maths::Sign(fMinHeightChange))) { continue; }
			fMinHeightChange = Asura_Maths::Abs(fMinHeightChange);
			if (fMinHeightChange < fBestMinHeightChange) { continue; }
			if (fMinHeightChange > fHeightOffset) { continue; }

			// Next, make sure it's within valid distance.
			if (fMaxFlatDistanceSquared < fFlatDistanceSquared) { continue; }
			// Only need to compare with the best if our height changes are equal since that's the priority comparison.
			if ((fMinHeightChange == fBestMinHeightChange) && (fMaxFlatDistanceSquared > fBestMaxFlatDistanceSquared)) { continue; }

			// Finally, the headroom check. We want the greatest clearance we think should be safe. We're rapidly approaching needing LOS tests...
			// Headroom is only a deciding factor if the other two values are equal to the previous best.
			if ((fMinHeightChange == fBestMinHeightChange) && (fMaxFlatDistanceSquared == fBestMaxFlatDistanceSquared) && (fHeadroom < fBestHeadroom)) { continue; }

			// We need two LOS tests to make a reasonable guess - from the current head position to an approximation of head position at the midpoint, and from there to the end head position.
			// AJG - 10/09/08 - Now doing this three times to reduce the instances where we jump through geometry.
			bool bFailedLOS = false;
			for (int j=0; j<3; ++j)
			{
				const Asura_Vector_3 xHeadroomMidpoint = xMidpoints[j] + Asura_Vector_3(0.0f, -fHeadroom, 0.0f);

				Asura_Vector_3 xDir = xHeadroomMidpoint - xStarts[j];
				float fDistance = xDir.Normalise();
				Asura_LOS_InputData xInput(xStarts[j], xDir, Guid, fDistance, false, m_usFlagsToIgnore | AsuraPolygonFlag_NoCollisions);
				const Asura_LOS_OutputData* pxOutput = Asura_LOS::TestAgainstEverything(&xInput);
				if (pxOutput->m_fDistanceToIntersection < fDistance)
				{
					bFailedLOS = true;
					break;
				}

				xDir = xTargets[j] - xHeadroomMidpoint;
				fDistance = xDir.Normalise();
				xInput.m_xOrigin = xHeadroomMidpoint;
				xInput.m_xDirection = xDir;
				xInput.m_fInitialMaximumRange = fDistance;
				pxOutput = Asura_LOS::TestAgainstEverything(&xInput);
				if (pxOutput->m_fDistanceToIntersection < fDistance)
				{
					bFailedLOS = true;
					break;
				}
			}

			if (bFailedLOS) { continue; }

			// Finally, this can be considered successful. Store the values.
			fBestMaxFlatDistanceSquared = fMaxFlatDistanceSquared;
			fBestMinHeightChange = fMinHeightChange;
			fBestHeadroom = fHeadroom;
			iBestVariation = i;
		}
	}

	if (iBestVariation >= 0)
	{
		iJumpVariation = iBestVariation;
		return true;
	}
	else
	{
		return false;
	}
}

void AVP_ClientActor_Predator::GetTargetedJumpAnimationsForVariation(const int iJumpVariation, Asura_Hash_ID& uFirstPersonAnim, Asura_Hash_ID& uThirdPersonAnim) const
{
	uFirstPersonAnim = ASURA_HASH_ID_UNSET;
	uThirdPersonAnim = ASURA_HASH_ID_UNSET;

	const Asura_Blueprint* pxBlueprint = GetCurrentTargetedJumpBlueprint();
	if (!pxBlueprint) { return; }

	Asura_Value xValue;
	if (!pxBlueprint->GetParameterValueByIndex(iJumpVariation, xValue))
	{
		Asura_Assert(false, "Invalid targeted jump variation.");
		// Try variation 0 as a fallback.
		if (!pxBlueprint->GetParameterValueByIndex(0, xValue)) { return; }
	}

	const Asura_Blueprint* pxVariationBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MOVESPREDATOR, xValue.GetHashIDValue());
	if (!pxVariationBlueprint) { return; }

	if (pxVariationBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_FIRSTPERSONANIM, xValue))
	{
		uFirstPersonAnim = xValue.GetHashIDValue();
	}

	if (pxVariationBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_THIRDPERSONANIM, xValue))
	{
		uThirdPersonAnim = xValue.GetHashIDValue();
	}
}

const Asura_Blueprint* AVP_ClientActor_Predator::GetCurrentTargetedJumpBlueprint() const
{
	// This comes from the current weapon.
	if (!m_pxInventorySystem) { return NULL; }
	const AVP_Inventory_Item* pxCurrentWeapon = m_pxInventorySystem->GetCurrentItem(uAVP_INVENTORY_GROUPHASH_WEAPON);
	if (!pxCurrentWeapon) { return NULL; }

	const Asura_Blueprint* pxWeaponBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_INVENTORY_ITEMS, pxCurrentWeapon->GetBlueprintHash());
	if (!pxWeaponBlueprint) { return NULL; }

	Asura_Value xValue;
	if (!pxWeaponBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_TARGETEDJUMPSET, xValue)) { return NULL; }

	const Asura_Blueprint* pxJumpBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MOVESPREDATOR, xValue.GetHashIDValue());
	if (!pxJumpBlueprint) { return NULL; }

	return pxJumpBlueprint;
}

void AVP_ClientActor_Predator::RegainEnergyFromTrophyKill( AVP_ENTITY_CLASSIFICATION eClass )
{
	float fEnergyBlocksToRegain = 1.0f;
	if ( eClass == AVP_ENTITYCLASS_HUMAN )
	{ 
		fEnergyBlocksToRegain = 2.0f;
	}

	m_xDynamicEnergy.SetMax( Asura_Maths::Min( GetMaxEnergy(), m_xDynamicEnergy.GetMax() + ( fEnergyBlocksToRegain * GetEnergyPerBlock() ) ) );
	m_xDynamicEnergy.Add( fEnergyBlocksToRegain * GetEnergyPerBlock(), true );
}

const AVP_Actor_AnimStateData* AVP_ClientActor_Predator::GetAnimStateDataForWeapon( const Asura_Hash_ID uWeaponBPHash ) const
{
	if ( IsAIActor() )
	{
		return AVP_Predator_AIAnimStateData::GetAnimStateData( GetAnimStateBlueprintType(), uWeaponBPHash, GetAIAnimState() );
	}
	else if ( IsPlayer() && m_pxAnimationHandler && m_pxPlayerStateHandler )
	{
		return AVP_Predator_PlayerAnimStateData::GetSingleton().GetAnimStateData( GetAnimStateBlueprintType(), uWeaponBPHash, m_pxAnimationHandler->IsFirstPerson(), IsCrouching(), IsJumping(), IsFalling(), static_cast< const AVP_Vertebrate_PlayerAnimStateHandler* >( m_pxPlayerStateHandler )->GetBestMoveSpeed() );
	}
	else
	{
		Asura_Assertf( false, ( "Couldn't get state data for entity %d", GetGuid() ) );
		return NULL;
	}
}

void AVP_ClientActor_Predator::SetCrouching( const bool bSet, const bool bCheckIfPossible )
{
	bool bDoIt = true;
	if ( bCheckIfPossible && AVP_Game_Core::IsLocalPlayer( GetGuid() ) )
	{
		const AVP_Inventory_System* pxInvSys = GetInventorySystem();
		if ( pxInvSys )
		{
			const AVP_Inventory_Item* pxItem = pxInvSys->GetCurrentItem( uAVP_INVENTORY_GROUPHASH_WEAPON );
			if ( pxItem )
			{
				const AVP_Actor_AnimStateData* pxStateData = AVP_Predator_PlayerAnimStateData::GetSingleton().GetAnimStateData( GetAnimStateBlueprintType(), pxItem->GetBlueprintHash(), AVP_Game_Core::IsLocalPlayer( GetGuid() ), bSet, false, false, AVP_Vertebrate_PlayerAnimStateHandler::MOVESPEED_IDLE );
				const AVP_Collision_Descriptor* pxCollDesc = pxStateData ? AVP_Collision_Descriptor::GetDataByHash( pxStateData->GetCollisionDescriptorHash() ) : NULL;
				if ( pxCollDesc )
				{
					const Asura_Collision_Box* pxCollBox = pxCollDesc->GetCollisionBox();
					if ( pxCollBox )
					{
						bDoIt = CanChangeCollisionObject( *pxCollBox );
					}
				}
			}
		}
	}
	if ( bDoIt )
	{
		m_bCrouching = bSet;
	}
}

const AVP_Actor_AnimStateData* AVP_ClientActor_Predator::GetStateDataFromMesssageData( const u_int uState, const AVP_Message_Actor_ClientUpdate* pxActorData )
{
	if ( GetInventorySystem() )
	{
		const AVP_Inventory_Item* pxItem = GetInventorySystem()->GetCurrentItem( uAVP_INVENTORY_GROUPHASH_WEAPON );
		if ( pxItem )
		{
			return AVP_Predator_AIAnimStateData::GetAnimStateData( GetAnimStateBlueprintType(), pxItem->GetBlueprintHash(), uState );
		}
	}
	//else
	return NULL;
}

const AVP_Actor_AnimStateData* AVP_ClientActor_Predator::GetStateData( const u_int uState, const u_int uGroundType, const u_int uLimbDamage, const bool bIsAiming, const u_int uCoverType)
{
	if ( GetInventorySystem() )
	{
		const AVP_Inventory_Item* pxItem = GetInventorySystem()->GetCurrentItem( uAVP_INVENTORY_GROUPHASH_WEAPON );
		if ( pxItem )
		{
			return AVP_Predator_AIAnimStateData::GetAnimStateData( GetAnimStateBlueprintType(), pxItem->GetBlueprintHash(), uState );
		}
	}
	//else
	return NULL;
}


/// End of file. ///
