
///////////////////////////////////////////////////////////////////////////////
//
// File   : AVP_Predator_MovesMelee.cpp
// Author : Chris Wallace
// Date   : 23-Jan-2008
//
// Copyright (C) 2008 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

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

#include "Core/Asura.h"


// This file's header...
#include "Moves/Vertebrates/Predator/AVP_Predator_MovesMelee.h"

// Asura independent header-files...
#include "Animation/Asura_Animation.h"
#include "Animation/Asura_AnimationAttachment.h"
#include "Animation/Asura_AnimationController_Animation.h"
#include "Blueprint/Asura_Blueprint.h"
#include "Blueprint/Asura_Blueprint_System.h"
#include "Network/Asura_Message.h"
#include "SpecialFX/PFX/Asura_PFX_Entity_Effect.h"

// Game independent header-files...
#include "Actor/AVP_Actor_AnimationHandler.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_MeleeCounter_System.h"
#include "Animation/AVP_AnimFlags.h"
#include "Blueprint/AVP_Blueprint_HashIDs.h"
#include "Core/AVP_Settings.h"
#include "Entity/AVP_Messages.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Alien/AVP_ClientActor_Alien.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/AVP_Vertebrate_Messages.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Predator/AVP_ClientActor_Predator.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Human/AVP_ServerActor_Human.h"
#include "Entity/PhysicalObject/Gib/AVP_ClientEntity_Gib.h"
#include "Moves/Vertebrates/Alien/AVP_Alien_MovesMelee.h"
#include "Moves/Vertebrates/Predalien/AVP_Predalien_MovesMelee.h"
#include "Rendering/Asura_Project_Skin_Elements.h"


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

static const float g_fTweenInDuration = 0.1f;
static const float g_fTweenOutDuration = 0.1f;
static const float g_fLongTweenInDuration = 0.2f;

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


////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Predator_Move_MeleeCharge_Start
// Author       : Anthony Gregson
// Date         : 02/05/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_MeleeCharge_Start::AVP_Predator_Move_MeleeCharge_Start(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash())
{
	AddNextMove(AVP_Predator_Move_MeleeCharge_Loop::GetStaticHash());

	m_bRestrictedMovement = true;
	m_bAllowMeleeTargetUpdate = true;

	const Asura_Blueprint* pxFirstPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash);
	const Asura_Blueprint* pxThirdPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uThirdPersonBlueprintHash);
	if (pxFirstPersonBlueprint || pxThirdPersonBlueprint)
	{
		SetupAnimHashesFromBlueprint(pxFirstPersonBlueprint, pxThirdPersonBlueprint, "PowerChargeStart");
	}

	if (m_pxAVPAnimationData)
	{
		m_pxAVPAnimationData->SetTweenData(g_fLongTweenInDuration, 0.0f, true);
		m_pxAVPAnimationData->SetLeaveAnimAtEnd(true);
		m_pxAVPAnimationData->SetDontCalculateVelocity(true);
		m_pxAVPAnimationData->SetDontCalculateAngularVelocity(true);
	}
}



////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Predator_Move_MeleeCharge_Loop
// Author       : Anthony Gregson
// Date         : 02/05/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_MeleeCharge_Loop::AVP_Predator_Move_MeleeCharge_Loop(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash())
{
	// TODO - we still need to change the name of this flag to something more sensible (or remove it and just use the animation flag).
	m_bLoopAtEnd = true;

	m_bRestrictedMovement = true;
	m_bAllowMeleeTargetUpdate = true;

	const Asura_Blueprint* pxFirstPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash);
	const Asura_Blueprint* pxThirdPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uThirdPersonBlueprintHash);
	if (pxFirstPersonBlueprint || pxThirdPersonBlueprint)
	{
		SetupAnimHashesFromBlueprint(pxFirstPersonBlueprint, pxThirdPersonBlueprint, "PowerChargeLoop");
	}

	if (m_pxAVPAnimationData)
	{
		m_pxAVPAnimationData->SetTweenData(g_fTweenInDuration, g_fTweenOutDuration, true);
		m_pxAVPAnimationData->SetLeaveAnimAtEnd(true);
		m_pxAVPAnimationData->SetDontCalculateVelocity(true);
		m_pxAVPAnimationData->SetDontCalculateAngularVelocity(true);
	}
}


////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Predator_Move_MeleeCharge_End
// Author       : Anthony Gregson
// Date         : 28/05/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_MeleeCharge_End::AVP_Predator_Move_MeleeCharge_End(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash())
{
	m_bAllowMeleeTargetUpdate = true;

	const Asura_Blueprint* pxFirstPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash);
	const Asura_Blueprint* pxThirdPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uThirdPersonBlueprintHash);
	if (pxFirstPersonBlueprint || pxThirdPersonBlueprint)
	{
		SetupAnimHashesFromBlueprint(pxFirstPersonBlueprint, pxThirdPersonBlueprint, "PowerChargeStart");
	}

	if (m_pxAVPAnimationData)
	{
		m_pxAVPAnimationData->SetAnimFlags(AACA_FLAG_REVERSED);
		m_pxAVPAnimationData->SetTweenData(g_fTweenInDuration, g_fTweenOutDuration, true);
		m_pxAVPAnimationData->SetLeaveAnimAtEnd(true);
		m_pxAVPAnimationData->SetDontCalculateVelocity(true);
		m_pxAVPAnimationData->SetDontCalculateAngularVelocity(true);
	}
}



////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Predator_Move_Melee_Wristblade_QuickAttack_Start
// Author       : Anthony Gregson
// Date         : 02/05/08
////////////////////////////////////////////////////////////////////////////////
AVP_Predator_Move_Melee_Wristblade_QuickAttack_Start::AVP_Predator_Move_Melee_Wristblade_QuickAttack_Start(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Predator_Move_Melee_Wristblade_QuickAttack_Return_Hit::GetStaticHash(), AVP_Predator_Move_Melee_Wristblade_QuickAttack_Return_Countered::GetStaticHash(), AVP_Predator_Move_Melee_Wristblade_QuickAttack_Return_Miss::GetStaticHash())
{
	SetAlwaysCheckNextMoves(false);

	const Asura_Blueprint* pxFirstPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash);
	const Asura_Blueprint* pxThirdPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uThirdPersonBlueprintHash);
	if (pxFirstPersonBlueprint || pxThirdPersonBlueprint)
	{
		Asura_Value xValue;
		// Go through each of the parameter types

		if (pxFirstPersonBlueprint)
		{
			AVP_Blueprint_ParameterEnumerator_MeleeVariations_MultipleParameters xFPEnumerator(*this, false);

			pxFirstPersonBlueprint->EnumerateParameters(AVP_Predator_MeleeCounter_System::GetLeftQuickAttackBaseParameterName(), 2, xFPEnumerator);
			pxFirstPersonBlueprint->EnumerateParameters(AVP_Predator_MeleeCounter_System::GetRightQuickAttackBaseParameterName(), 2, xFPEnumerator);

			xFPEnumerator.EnumeratedAllParameters();
		}

		if (pxThirdPersonBlueprint)
		{
			AVP_Blueprint_ParameterEnumerator_MeleeVariations_MultipleParameters xTPEnumerator(*this, true);

			pxThirdPersonBlueprint->EnumerateParameters(AVP_Predator_MeleeCounter_System::GetLeftQuickAttackBaseParameterName(), 2, xTPEnumerator);
			pxThirdPersonBlueprint->EnumerateParameters(AVP_Predator_MeleeCounter_System::GetRightQuickAttackBaseParameterName(), 2, xTPEnumerator);

			xTPEnumerator.EnumeratedAllParameters();
		}

		SetVariation(0);
	}

	if (m_pxAVPAnimationData)
	{
		m_pxAVPAnimationData->SetTweenData(g_fLongTweenInDuration, 0.0f, true);
		m_pxAVPAnimationData->SetLeaveAnimAtEnd(true);
		m_pxAVPAnimationData->SetDontCalculateVelocity(true);
		m_pxAVPAnimationData->SetDontCalculateAngularVelocity(true);
	}
}


bool AVP_Predator_Move_Melee_Wristblade_QuickAttack_Start::Start(const Asura_Msg_Move* pxStartMsg)
{
	bool bSuccess = PARENT::Start(pxStartMsg);
	if (!bSuccess) { return false; }

	const AVP_ClientEntity_Actor& xOwner = GetAVPParentSystem().GetActorOwner();

	if (xOwner.IsPlayer() && !m_bTargetChaseActive) { return true; }

	const AVP_Msg_Melee_Move* pxMeleeStart = static_cast<const AVP_Msg_Melee_Move*>(pxStartMsg);
	const AVP_ClientEntity_PhysicalObject* pxTarget = AVP_ClientEntity_PhysicalObject::FindEntity(pxMeleeStart->GetTargetGuid());
	if (!pxTarget) { return true; }

	Asura_Vector_3 xTargetPosition;
	pxTarget->GetMeleeOrigin(xTargetPosition);
	xTargetPosition.y = pxTarget->GetCurrentPosition().y;
	Asura_Vector_3 xFlatDirection = xTargetPosition - xOwner.GetCurrentPosition();;
	xFlatDirection.y = 0.0f;
	xFlatDirection.Normalise();
	
	Asura_Matrix_3x3 pxOrientationToEnemy;

	Asura_Maths::OrientationFromDirection(pxOrientationToEnemy, xFlatDirection);

	bool bHasAnimation = m_pxAVPAnimationData && m_pxAVPAnimationData->HasValidAnimation();
	float fDuration = bHasAnimation ? m_pxAVPAnimationData->GetAnimationDuration() : 0.500f;

	m_xOrientationInterpolationData.SetFinal(pxOrientationToEnemy);
	m_xOrientationInterpolationData.SetDuration(fDuration);

	InitialiseOrientationInterpolation(m_xOrientationInterpolationData);

	return true;
}


////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Predator_Move_Melee_Wristblade_QuickAttack_Return_Hit
// Author       : Anthony Gregson
// Date         : 02/05/08
////////////////////////////////////////////////////////////////////////////////

const char* AVP_Predator_Move_Melee_Wristblade_QuickAttack_Return_Hit::s_szParameterNameLeft = "QuickAttackLeftHit";
const char* AVP_Predator_Move_Melee_Wristblade_QuickAttack_Return_Hit::s_szParameterNameRight = "QuickAttackRightHit";

AVP_Predator_Move_Melee_Wristblade_QuickAttack_Return_Hit::AVP_Predator_Move_Melee_Wristblade_QuickAttack_Return_Hit(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash())
{
	const Asura_Blueprint* pxFirstPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash);
	const Asura_Blueprint* pxThirdPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uThirdPersonBlueprintHash);
	if (pxFirstPersonBlueprint || pxThirdPersonBlueprint)
	{
		Asura_Value xValue;
		// Go through each of the parameter types

		if (pxFirstPersonBlueprint)
		{
			AVP_Blueprint_ParameterEnumerator_MeleeVariations_MultipleParameters xFPEnumerator(*this, false);

			pxFirstPersonBlueprint->EnumerateParameters(s_szParameterNameLeft, 2, xFPEnumerator);
			pxFirstPersonBlueprint->EnumerateParameters(s_szParameterNameRight, 2, xFPEnumerator);

			xFPEnumerator.EnumeratedAllParameters();
		}

		if (pxThirdPersonBlueprint)
		{
			AVP_Blueprint_ParameterEnumerator_MeleeVariations_MultipleParameters xTPEnumerator(*this, true);

			pxThirdPersonBlueprint->EnumerateParameters(s_szParameterNameLeft, 2, xTPEnumerator);
			pxThirdPersonBlueprint->EnumerateParameters(s_szParameterNameRight, 2, xTPEnumerator);

			xTPEnumerator.EnumeratedAllParameters();
		}

		SetVariation(0);
	}

	if (m_pxAVPAnimationData)
	{
		m_pxAVPAnimationData->SetTweenData(g_fTweenInDuration, g_fTweenOutDuration, true);
		m_pxAVPAnimationData->SetLeaveAnimAtEnd(true);
	}

	m_bClearQueuedMeleeRequests = true;
}

////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Predator_Move_Melee_Wristblade_QuickAttack_Return_Countered
// Author       : Anthony Gregson
// Date         : 02/05/08
////////////////////////////////////////////////////////////////////////////////

const char* AVP_Predator_Move_Melee_Wristblade_QuickAttack_Return_Countered::s_szParameterNameLeft = "QuickAttackLeftCountered";
const char* AVP_Predator_Move_Melee_Wristblade_QuickAttack_Return_Countered::s_szParameterNameRight = "QuickAttackRightCountered";

AVP_Predator_Move_Melee_Wristblade_QuickAttack_Return_Countered::AVP_Predator_Move_Melee_Wristblade_QuickAttack_Return_Countered(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash())
{
	const Asura_Blueprint* pxFirstPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash);
	const Asura_Blueprint* pxThirdPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uThirdPersonBlueprintHash);
	if (pxFirstPersonBlueprint || pxThirdPersonBlueprint)
	{
		Asura_Value xValue;
		// Go through each of the parameter types

		if (pxFirstPersonBlueprint)
		{
			AVP_Blueprint_ParameterEnumerator_MeleeVariations_MultipleParameters xFPEnumerator(*this, false);

			pxFirstPersonBlueprint->EnumerateParameters(s_szParameterNameLeft, 2, xFPEnumerator);
			pxFirstPersonBlueprint->EnumerateParameters(s_szParameterNameRight, 2, xFPEnumerator);

			xFPEnumerator.EnumeratedAllParameters();
		}

		if (pxThirdPersonBlueprint)
		{
			AVP_Blueprint_ParameterEnumerator_MeleeVariations_MultipleParameters xTPEnumerator(*this, true);

			pxThirdPersonBlueprint->EnumerateParameters(s_szParameterNameLeft, 2, xTPEnumerator);
			pxThirdPersonBlueprint->EnumerateParameters(s_szParameterNameRight, 2, xTPEnumerator);

			xTPEnumerator.EnumeratedAllParameters();
		}

		SetVariation(0);
	}

	if (m_pxAVPAnimationData)
	{
		m_pxAVPAnimationData->SetTweenData(g_fTweenInDuration, g_fTweenOutDuration, true);
		m_pxAVPAnimationData->SetLeaveAnimAtEnd(true);
	}
}

////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Predator_Move_Melee_Wristblade_QuickAttack_Return_Miss
// Author       : Anthony Gregson
// Date         : 02/05/08
////////////////////////////////////////////////////////////////////////////////

const char* AVP_Predator_Move_Melee_Wristblade_QuickAttack_Return_Miss::s_szParameterNameLeft = "QuickAttackLeftMiss";
const char* AVP_Predator_Move_Melee_Wristblade_QuickAttack_Return_Miss::s_szParameterNameRight = "QuickAttackRightMiss";

AVP_Predator_Move_Melee_Wristblade_QuickAttack_Return_Miss::AVP_Predator_Move_Melee_Wristblade_QuickAttack_Return_Miss(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash())
{
	const Asura_Blueprint* pxFirstPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash);
	const Asura_Blueprint* pxThirdPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uThirdPersonBlueprintHash);
	if (pxFirstPersonBlueprint || pxThirdPersonBlueprint)
	{
		Asura_Value xValue;
		// Go through each of the parameter types

		if (pxFirstPersonBlueprint)
		{
			AVP_Blueprint_ParameterEnumerator_MeleeVariations_MultipleParameters xFPEnumerator(*this, false);

			pxFirstPersonBlueprint->EnumerateParameters(s_szParameterNameLeft, 2, xFPEnumerator);
			pxFirstPersonBlueprint->EnumerateParameters(s_szParameterNameRight, 2, xFPEnumerator);

			xFPEnumerator.EnumeratedAllParameters();
		}

		if (pxThirdPersonBlueprint)
		{
			AVP_Blueprint_ParameterEnumerator_MeleeVariations_MultipleParameters xTPEnumerator(*this, true);

			pxThirdPersonBlueprint->EnumerateParameters(s_szParameterNameLeft, 2, xTPEnumerator);
			pxThirdPersonBlueprint->EnumerateParameters(s_szParameterNameRight, 2, xTPEnumerator);

			xTPEnumerator.EnumeratedAllParameters();
		}

		SetVariation(0);
	}

	if (m_pxAVPAnimationData)
	{
		m_pxAVPAnimationData->SetTweenData(g_fTweenInDuration, g_fTweenOutDuration, true);
		m_pxAVPAnimationData->SetLeaveAnimAtEnd(true);
		m_pxAVPAnimationData->SetDontCalculateVelocity(true);
		m_pxAVPAnimationData->SetDontCalculateAngularVelocity(true);
	}
}


////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Predator_Move_Melee_Wristblade_PowerAttack_Start
// Author       : Anthony Gregson
// Date         : 02/05/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_Wristblade_PowerAttack_Start::AVP_Predator_Move_Melee_Wristblade_PowerAttack_Start(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "PowerAttackStart",
		 AVP_Predator_Move_Melee_Wristblade_PowerAttack_Return_Hit::GetStaticHash(), AVP_Predator_Move_Melee_Wristblade_PowerAttack_Return_Countered::GetStaticHash(), AVP_Predator_Move_Melee_Wristblade_PowerAttack_Return_Miss::GetStaticHash())
{
}

////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Predator_Move_Melee_Wristblade_PowerAttack_Return_Hit
// Author       : Anthony Gregson
// Date         : 02/05/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_Wristblade_PowerAttack_Return_Hit::AVP_Predator_Move_Melee_Wristblade_PowerAttack_Return_Hit(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "PowerAttackHit")
{
	m_bClearQueuedMeleeRequests = true;
}

////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Predator_Move_Melee_Wristblade_PowerAttack_Return_Countered
// Author       : Anthony Gregson
// Date         : 02/05/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_Wristblade_PowerAttack_Return_Countered::AVP_Predator_Move_Melee_Wristblade_PowerAttack_Return_Countered(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "PowerAttackCountered")
{
}

////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Predator_Move_Melee_Wristblade_PowerAttack_Return_Miss
// Author       : Anthony Gregson
// Date         : 02/05/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_Wristblade_PowerAttack_Return_Miss::AVP_Predator_Move_Melee_Wristblade_PowerAttack_Return_Miss(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "PowerAttackMiss")
{
}


////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Predator_Move_Melee_Wristblade_SlowAttack
// Author       : Anthony Gregson
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_Wristblade_SlowAttack::AVP_Predator_Move_Melee_Wristblade_SlowAttack(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash())
{
	const Asura_Blueprint* pxFirstPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash);
	const Asura_Blueprint* pxThirdPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uThirdPersonBlueprintHash);
	if (pxFirstPersonBlueprint || pxThirdPersonBlueprint)
	{
		SetupAnimHashesFromBlueprint(pxFirstPersonBlueprint, pxThirdPersonBlueprint, "WristbladesFarRightAttack");
	}

	if (m_pxAVPAnimationData)
	{
		m_pxAVPAnimationData->SetTweenData(g_fTweenInDuration, g_fTweenOutDuration, true);
		m_pxAVPAnimationData->SetLeaveAnimAtEnd(true);
		m_pxAVPAnimationData->SetDontCalculateVelocity(true);
		m_pxAVPAnimationData->SetDontCalculateAngularVelocity(true);
	}

	m_bClearQueuedMeleeRequests = true;
}



////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Predator_Move_Melee_FarCounter
// Author       : Anthony Gregson
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_FarCounter::AVP_Predator_Move_Melee_FarCounter(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash())
{
	const Asura_Blueprint* pxFirstPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash);
	const Asura_Blueprint* pxThirdPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uThirdPersonBlueprintHash);
	if (pxFirstPersonBlueprint || pxThirdPersonBlueprint)
	{
		SetupAnimHashesFromBlueprint(pxFirstPersonBlueprint, pxThirdPersonBlueprint, "WristbladesFarCounter");
	}

	if (m_pxAVPAnimationData)
	{
		m_pxAVPAnimationData->SetTweenData(g_fTweenInDuration, g_fTweenOutDuration, true);
		m_pxAVPAnimationData->SetLeaveAnimAtEnd(true);
	}

	m_bClearQueuedMeleeRequests = true;
}


////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Predator_Move_Melee_CounterAlienJumpAttack_Throw
// Author       : Anthony Gregson
////////////////////////////////////////////////////////////////////////////////

DEBUGVAR float dbg_fAlienThrowAimDirectionAngVel = Asura_Maths::DegToRad(720); //720 degrees per seconds

AVP_Predator_Move_Melee_CounterAlienJumpAttack_Throw::AVP_Predator_Move_Melee_CounterAlienJumpAttack_Throw(Asura_Movement_System& xParentSystem, const Asura_Hash_ID uHash)
: PARENT(xParentSystem, uHash)
{
	SetOrientationUsage(ORIENTATION_SET_DIRECTLY);
	SetAimDirectionUsage(AVP_ClientEntity_Actor::AIM_DIRECTION_RESET);
	SetAimDirectionAngVel(dbg_fAlienThrowAimDirectionAngVel);
}

bool AVP_Predator_Move_Melee_CounterAlienJumpAttack_Throw::Start(const Asura_Msg_Move* pxStartMsg)
{
	// AVP_Move_Melee currently changes the aim direction lerp scale each start, so we need to set it back to ours here.
	const bool bSuccess = PARENT::Start(pxStartMsg);

	SetAimDirectionAngVel(dbg_fAlienThrowAimDirectionAngVel);

	return bSuccess;
}


////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Predator_Move_Melee_CounterAlienJumpAttack_Throw_Left
// Author       : Anthony Gregson
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_CounterAlienJumpAttack_Throw_Left::AVP_Predator_Move_Melee_CounterAlienJumpAttack_Throw_Left(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash())
{
	const Asura_Blueprint* pxFirstPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash);
	const Asura_Blueprint* pxThirdPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uThirdPersonBlueprintHash);
	if (pxFirstPersonBlueprint || pxThirdPersonBlueprint)
	{
		SetupAnimHashesFromBlueprint(pxFirstPersonBlueprint, pxThirdPersonBlueprint, "AlienBuzzCounterThrowLeft");
	}

	if (m_pxAVPAnimationData)
	{
		m_pxAVPAnimationData->SetTweenData(g_fTweenInDuration, g_fTweenOutDuration, true);
		m_pxAVPAnimationData->SetLeaveAnimAtEnd(true);
	}

	m_bClearQueuedMeleeRequests = true;
}


////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Predator_Move_Melee_CounterAlienJumpAttack_Throw_Right
// Author       : Anthony Gregson
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_CounterAlienJumpAttack_Throw_Right::AVP_Predator_Move_Melee_CounterAlienJumpAttack_Throw_Right(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash())
{
	const Asura_Blueprint* pxFirstPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash);
	const Asura_Blueprint* pxThirdPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uThirdPersonBlueprintHash);
	if (pxFirstPersonBlueprint || pxThirdPersonBlueprint)
	{
		SetupAnimHashesFromBlueprint(pxFirstPersonBlueprint, pxThirdPersonBlueprint, "AlienBuzzCounterThrowRight");
	}

	if (m_pxAVPAnimationData)
	{
		m_pxAVPAnimationData->SetTweenData(g_fTweenInDuration, g_fTweenOutDuration, true);
		m_pxAVPAnimationData->SetLeaveAnimAtEnd(true);
	}

	m_bClearQueuedMeleeRequests = true;
}


////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Predator_Move_Melee_CounterAlienJumpAttack_Hit_Left
// Author       : Anthony Gregson
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_CounterAlienJumpAttack_Hit_Left::AVP_Predator_Move_Melee_CounterAlienJumpAttack_Hit_Left(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash())
{
	const Asura_Blueprint* pxFirstPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash);
	const Asura_Blueprint* pxThirdPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uThirdPersonBlueprintHash);
	if (pxFirstPersonBlueprint || pxThirdPersonBlueprint)
	{
		SetupAnimHashesFromBlueprint(pxFirstPersonBlueprint, pxThirdPersonBlueprint, "AlienBuzzCounterHitLeft");
	}

	if (m_pxAVPAnimationData)
	{
		m_pxAVPAnimationData->SetTweenData(g_fTweenInDuration, g_fTweenOutDuration, true);
		m_pxAVPAnimationData->SetLeaveAnimAtEnd(true);
	}

	m_bClearQueuedMeleeRequests = true;
	SetAimDirectionUsage(AVP_ClientEntity_Actor::AIM_DIRECTION_RESET);
}

void AVP_Predator_Move_Melee_CounterAlienJumpAttack_Hit_Left::UpdateStates(const float fTimeStep)
{
	if ((GetAnimFlagsForLastFrame() & AVP_ANIMFLAG_MELEE_DAMAGE) != 0)
	{
		const AVP_ClientActor_Vertebrate* pxTarget = AVP_ClientActor_Vertebrate::FindEntity(m_uTargetGuid);
		if (pxTarget)
		{
			GetAVPParentSystem().GetActorOwner().CreatePFXEffect(pxTarget->GetBloodSquirtPFXHash(), AVP_Predator_Description::GetMarkerPointHashID(AVP_Predator_Description::BLADE_LEFT_MARKER_POINT_HASH), true);
		}
	}

	PARENT::UpdateStates(fTimeStep);
}


////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Predator_Move_Melee_CounterAlienJumpAttack_Hit_Right
// Author       : Anthony Gregson
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_CounterAlienJumpAttack_Hit_Right::AVP_Predator_Move_Melee_CounterAlienJumpAttack_Hit_Right(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash())
{
	const Asura_Blueprint* pxFirstPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash);
	const Asura_Blueprint* pxThirdPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uThirdPersonBlueprintHash);
	if (pxFirstPersonBlueprint || pxThirdPersonBlueprint)
	{
		SetupAnimHashesFromBlueprint(pxFirstPersonBlueprint, pxThirdPersonBlueprint, "AlienBuzzCounterHitRight");
	}

	if (m_pxAVPAnimationData)
	{
		m_pxAVPAnimationData->SetTweenData(g_fTweenInDuration, g_fTweenOutDuration, true);
		m_pxAVPAnimationData->SetLeaveAnimAtEnd(true);
	}

	m_bClearQueuedMeleeRequests = true;
	SetAimDirectionUsage(AVP_ClientEntity_Actor::AIM_DIRECTION_RESET);
}

void AVP_Predator_Move_Melee_CounterAlienJumpAttack_Hit_Right::UpdateStates(const float fTimeStep)
{
	if ((GetAnimFlagsForLastFrame() & AVP_ANIMFLAG_MELEE_DAMAGE) != 0)
	{
		const AVP_ClientActor_Vertebrate* pxTarget = AVP_ClientActor_Vertebrate::FindEntity(m_uTargetGuid);
		if (pxTarget)
		{
			GetAVPParentSystem().GetActorOwner().CreatePFXEffect(pxTarget->GetBloodSquirtPFXHash(), AVP_Predator_Description::GetMarkerPointHashID(AVP_Predator_Description::BLADE_RIGHT_MARKER_POINT_HASH), true);
		}
	}

	PARENT::UpdateStates(fTimeStep);
}


////////////////////////////////////////////////////////////////////////////////
// Class	    : AVP_Predator_Move_Melee_QuickFinisher_Start
// Author       : Anthony Gregson
// Date         : 15/02/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_QuickFinisher_Start::AVP_Predator_Move_Melee_QuickFinisher_Start(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "WristbladesQuickFinisherAttack",
		 AVP_Predator_Move_Melee_QuickFinisher_Return_Hit::GetStaticHash(), AVP_Predator_Move_Melee_QuickFinisher_Return_Countered::GetStaticHash(), AVP_Predator_Move_Melee_QuickFinisher_Return_Miss::GetStaticHash())
{
}

////////////////////////////////////////////////////////////////////////////////
// Class	    : AVP_Predator_Move_Melee_QuickFinisher_Return_Hit
// Author       : Anthony Gregson
// Date         : 15/02/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_QuickFinisher_Return_Hit::AVP_Predator_Move_Melee_QuickFinisher_Return_Hit(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "WristbladesQuickFinisherHit")
{
	m_bClearQueuedMeleeRequests = true;
}

////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_QuickFinisher_Return_Countered
// Author       : Anthony Gregson
// Date         : 15/02/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_QuickFinisher_Return_Countered::AVP_Predator_Move_Melee_QuickFinisher_Return_Countered(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "WristbladesQuickFinisherCountered")
{
}

////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_QuickFinisher_Return_Miss
// Author       : Anthony Gregson
// Date         : 15/02/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_QuickFinisher_Return_Miss::AVP_Predator_Move_Melee_QuickFinisher_Return_Miss(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "WristbladesQuickFinisherMiss")
{
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_CounterAlienLeftClawAttack
// Author       : Anthony Gregson
// Date         : 12/03/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_CounterAlienLeftClawAttack::AVP_Predator_Move_Melee_CounterAlienLeftClawAttack(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash()) // Because we use unique parameter names for this, we have to set up the animations ourselves.
{
	m_bNoBranching = true;

	const Asura_Blueprint* pxBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_GRAPPLEPREDATOR, uAVP_BLUEPRINT_NAME_PREDATORCOUNTER_STANDINGALIENCLAW);
	if (pxBlueprint)
	{
		Asura_Hash_ID uFirstPersonHash = ASURA_HASH_ID_UNSET;
		Asura_Hash_ID uThirdPersonHash = ASURA_HASH_ID_UNSET;
		Asura_Value xValue;
		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_PREDATORLEFTCLAW_FIRSTPERSON, xValue))
		{
			uFirstPersonHash = xValue.GetHashIDValue();
		}
		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_PREDATORLEFTCLAW_THIRDPERSON, xValue))
		{
			uThirdPersonHash = xValue.GetHashIDValue();
		}
		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_INITIALOFFSET, xValue))
		{
			m_fInitialVictimForwardOffset = xValue.GetFloatValue();
		}

		SetAnimHashes(uFirstPersonHash, uThirdPersonHash);

		if (m_pxAVPAnimationData)
		{
			m_pxAVPAnimationData->SetTweenData(g_fTweenInDuration, g_fTweenOutDuration, true);
			m_pxAVPAnimationData->SetLeaveAnimAtEnd(true);
		}

		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_ALIENLEFTCLAW_FIRSTPERSON, xValue))
		{
			m_uFirstPersonVictimAnimID = xValue.GetHashIDValue();
		}
		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_ALIENLEFTCLAW_THIRDPERSON, xValue))
		{
			m_uThirdPersonVictimAnimID = xValue.GetHashIDValue();
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_CounterAlienRightClawAttack
// Author       : Anthony Gregson
// Date         : 12/03/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_CounterAlienRightClawAttack::AVP_Predator_Move_Melee_CounterAlienRightClawAttack(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash()) // Because we use unique parameter names for this, we have to set up the animations ourselves.
{
	m_bNoBranching = true;

	const Asura_Blueprint* pxBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_GRAPPLEPREDATOR, uAVP_BLUEPRINT_NAME_PREDATORCOUNTER_STANDINGALIENCLAW);
	if (pxBlueprint)
	{
		Asura_Hash_ID uFirstPersonHash = ASURA_HASH_ID_UNSET;
		Asura_Hash_ID uThirdPersonHash = ASURA_HASH_ID_UNSET;
		Asura_Value xValue;
		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_PREDATORRIGHTCLAW_FIRSTPERSON, xValue))
		{
			uFirstPersonHash = xValue.GetHashIDValue();
		}
		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_PREDATORRIGHTCLAW_THIRDPERSON, xValue))
		{
			uThirdPersonHash = xValue.GetHashIDValue();
		}
		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_INITIALOFFSET, xValue))
		{
			m_fInitialVictimForwardOffset = xValue.GetFloatValue();
		}

		SetAnimHashes(uFirstPersonHash, uThirdPersonHash);

		if (m_pxAVPAnimationData)
		{
			m_pxAVPAnimationData->SetTweenData(g_fTweenInDuration, g_fTweenOutDuration, true);
			m_pxAVPAnimationData->SetLeaveAnimAtEnd(true);
		}

		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_ALIENRIGHTCLAW_FIRSTPERSON, xValue))
		{
			m_uFirstPersonVictimAnimID = xValue.GetHashIDValue();
		}
		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_ALIENRIGHTCLAW_THIRDPERSON, xValue))
		{
			m_uThirdPersonVictimAnimID = xValue.GetHashIDValue();
		}
	}
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_CounterAlienStandingTailStab_Start
// Author       : Anthony Gregson
// Date         : 14/03/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_CounterAlienStandingTailStab_Start::AVP_Predator_Move_Melee_CounterAlienStandingTailStab_Start(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_ALIEN, uAVP_BLUEPRINT_NAME_PREDATORCOUNTER_STANDINGTAILSTAB,
		 AVP_Predator_Move_Melee_CounterAlienStandingTailStab_Kill::GetStaticHash(), AVP_Predator_Move_Melee_CounterAlienStandingTailStab_Countered::GetStaticHash())
{
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_CounterAlienStandingTailStab_Kill
// Author       : Anthony Gregson
// Date         : 14/03/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_CounterAlienStandingTailStab_Kill::AVP_Predator_Move_Melee_CounterAlienStandingTailStab_Kill(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_ALIEN, uAVP_BLUEPRINT_NAME_PREDATORCOUNTER_STANDINGTAILSTAB)
{
	m_bAlwaysFatal = true;
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_CounterAlienStandingTailStab_Countered
// Author       : Anthony Gregson
// Date         : 14/03/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_CounterAlienStandingTailStab_Countered::AVP_Predator_Move_Melee_CounterAlienStandingTailStab_Countered(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_ALIEN, uAVP_BLUEPRINT_NAME_PREDATORCOUNTER_STANDINGTAILSTAB)
{
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_CounterAlienStandingTailStab_Countered
// Author       : Anthony Gregson
// Date         : 14/03/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_CounterAlienPounceAttack::AVP_Predator_Move_Melee_CounterAlienPounceAttack(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_ALIEN, uAVP_BLUEPRINT_NAME_PREDATORCOUNTER_ALIENPOUNCE)
{
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupHuman_Start
// Author       : Anthony Gregson
// Date         : 13/03/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupHuman_Start::AVP_Predator_Move_Melee_PickupHuman_Start(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "PickupHumanAttack",
		 AVP_Predator_Move_Melee_PickupHuman_Return_Hit::GetStaticHash(), AVP_Predator_Move_Melee_PickupHuman_Return_Countered::GetStaticHash(), AVP_Predator_Move_Melee_PickupHuman_Return_Miss::GetStaticHash())
{
	AddNextMove(AVP_Move_Melee_Grapple_Start::GetStaticHash());

	m_bClearQueuedMeleeRequests = true;
}


////////////////////////////////////////////////////////////////////////////////
// Class	    : AVP_Predator_Move_Melee_PickupHuman_Return_Hit
// Author       : Anthony Gregson
// Date         : 13/03/08
////////////////////////////////////////////////////////////////////////////////

// Currently hit and miss both use the same animation, set up with just one parameter.
static const char* g_szHumanPickupMissParameterName = "PickupHumanMiss";

AVP_Predator_Move_Melee_PickupHuman_Return_Hit::AVP_Predator_Move_Melee_PickupHuman_Return_Hit(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szHumanPickupMissParameterName)
{
	m_bClearQueuedMeleeRequests = true;
}

bool AVP_Predator_Move_Melee_PickupHuman_Return_Hit::ShouldStart() const
{
	// If the parent says we can start, check that the entity is of a type that we don't attach on to.
	if (!PARENT::ShouldStart()) { return false; }

	// There's only one move we can have come from.
	const AVP_Predator_Move_Melee_PickupHuman_Start* pxCurrentMove = static_cast<const AVP_Predator_Move_Melee_PickupHuman_Start*>(GetParentSystem().GetCurrentMove());
	if (!pxCurrentMove) { return false; }

	const AVP_ClientEntity_Actor* pxVictim = AVP_ClientEntity_Actor::FindEntity(pxCurrentMove->GetHitEntity());
	// TODO - These next two checks take the safe option of using this move if our victim has gone missing or died, but we should possibly be going into miss in that case.
	if (!pxVictim) { return true; }
	if (pxVictim->IsDead()) { return true; }

	switch (pxVictim->GetClassification())
	{
	default:
		return true;

		// These entity classifications are attached to, so don't start this move.
	case AVP_ENTITYCLASS_MARINE:
	case AVP_ENTITYCLASS_CIVILIAN:
	case AVP_ENTITYCLASS_ANDROID:
		return false;
	}
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupHuman_Return_Countered
// Author       : Anthony Gregson
// Date         : 13/03/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupHuman_Return_Countered::AVP_Predator_Move_Melee_PickupHuman_Return_Countered(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "PickupHumanCountered")
{
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupHuman_Return_Miss
// Author       : Anthony Gregson
// Date         : 13/03/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupHuman_Return_Miss::AVP_Predator_Move_Melee_PickupHuman_Return_Miss(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szHumanPickupMissParameterName)
{
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupHuman_Grapple_Start
// Author       : Anthony Gregson
// Date         : 13/03/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupHuman_Grapple_Start::AVP_Predator_Move_Melee_PickupHuman_Grapple_Start(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_HUMAN, uAVP_BLUEPRINT_NAME_PICKUPHUMAN,
		 AVP_Predator_Move_Melee_PickupHuman_Grapple_TrophyKill::GetStaticHash(), AVP_Predator_Move_Melee_PickupHuman_Grapple_Countered::GetStaticHash())
{
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupHuman_Grapple_TrophyKill
// Author       : Anthony Gregson
// Date         : 13/03/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupHuman_Grapple_TrophyKill::AVP_Predator_Move_Melee_PickupHuman_Grapple_TrophyKill(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_HUMAN, uAVP_BLUEPRINT_NAME_PICKUPHUMAN)
, m_pxTrophyAttachment(NULL)
, m_uTrophyMarkerPoint(ASURA_HASH_ID_UNSET)
, m_uTrophyAnim(ASURA_HASH_ID_UNSET)
{
	const Asura_Blueprint* pxBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(GetBlueprintType(AVP_Settings::AVP_SPECIES_PREDATOR), uAVP_BLUEPRINT_NAME_PICKUPHUMAN);
	if (pxBlueprint)
	{
		Asura_Value xValue;
		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_MARKERPOINT, xValue))
		{
			m_uTrophyMarkerPoint = xValue.GetHashIDValue();
		}

		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_TROPHYANIM, xValue))
		{
			m_uTrophyAnim = xValue.GetHashIDValue();
		}
	}

	m_bAlwaysFatal = true;
}

AVP_Predator_Move_Melee_PickupHuman_Grapple_TrophyKill::~AVP_Predator_Move_Melee_PickupHuman_Grapple_TrophyKill()
{
	DetachTrophy();
}

bool AVP_Predator_Move_Melee_PickupHuman_Grapple_TrophyKill::ShouldStart() const
{
	const AVP_Move_Melee_GenericPuppeteer_Start* pxCurrentMove = static_cast<const AVP_Move_Melee_GenericPuppeteer_Start*>(GetParentSystem().GetCurrentMove());
	if (pxCurrentMove)
	{
		if (pxCurrentMove->GetCountered()) { return false; }

		if (pxCurrentMove->GetFinalAttackType() == AVP_MELEEATTACK_TYPE_NONE) { return false; }

		// Make sure the enemy isn't invulnerable, as a kill move is a bit broken in that situation.
		// This means finding the puppet entity connected to the previous move.
		const AVP_ClientEntity_Actor* pxPuppet = AVP_ClientEntity_Actor::FindEntity(pxCurrentMove->GetCurrentPuppet());
		if (!pxPuppet || pxPuppet->IsInvulnerable()) { return false; }

		return true;
	}

	return false;
}

void AVP_Predator_Move_Melee_PickupHuman_Grapple_TrophyKill::Abort()
{
	DetachTrophy();

	PARENT::Abort();
}

void AVP_Predator_Move_Melee_PickupHuman_Grapple_TrophyKill::Finish()
{
	DetachTrophy();

	PARENT::Finish();
}

void AVP_Predator_Move_Melee_PickupHuman_Grapple_TrophyKill::UpdateStates(const float fTimeStep)
{
	if (m_uLastStatesUpdateFrameStamp != Asura_Timers::GetFrameNumber()) // Make sure we don't do this twice because of the external update.
	{
		const u_int uAnimFlags = GetAnimFlagsForLastFrame();
		if (uAnimFlags & AVP_ANIMFLAG_GRAPPLE_APPLY_DAMAGE)
		{
			//// Send OnHeadRipped message (AJK 08/01/2009)
			//const AVP_ServerActor_Human* pxTarget = AVP_ServerActor_Human::FindEntity(m_uCurrentPuppet);
			//if ( pxTarget )
			//{
			//	pxTarget->OnHeadRipped();
			//}

			AttachTrophy();
			AVP_ClientActor_Predator* pxPred = AVP_ClientActor_Predator::FindEntity( GetParentSystem().GetOwnerGuid() );
			if ( pxPred )
			{
				pxPred->RegainEnergyFromTrophyKill( AVP_ENTITYCLASS_HUMAN );
			}
		}
		if (uAnimFlags & AVP_ANIMFLAG_TRIGGER_DETACHMENT)
		{
			DetachTrophy();
		}
	}

	PARENT::UpdateStates(fTimeStep);
}

void AVP_Predator_Move_Melee_PickupHuman_Grapple_TrophyKill::AttachTrophy()
{
	Asura_Assert(!m_pxTrophyAttachment, "Already have a trophy attached");
	if (m_pxTrophyAttachment) { return; }

	if (m_uTrophyMarkerPoint == ASURA_HASH_ID_UNSET) { return; }

	const AVP_ClientActor_Vertebrate* pxTarget = AVP_ClientActor_Vertebrate::FindEntity(m_uCurrentPuppet);
	if (!pxTarget) { return; }

	Asura_Animation* pxOwnerAnim = GetAVPParentSystem().GetActorOwner().GetShapeInstance().GetAnimation();
	if (!pxOwnerAnim) { return; }

	const Asura_Blueprint* pxSkinElementBlueprint = pxTarget->GetSkinElementBlueprint(AVP_SET_HEAD);
	if (!pxSkinElementBlueprint) { return; }

	Asura_Value xValue;
	if (!pxSkinElementBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_SKINELEMENT_GIBSKIN, xValue)) { return; }

	const Asura_Hash_ID uSkin = xValue.GetHashIDValue();
	if (uSkin == ASURA_HASH_ID_UNSET) { return; }

	Asura_Animation* pxAnim = new Asura_Animation(uSkin);
	if (!pxAnim) { return; }

	if (m_uTrophyAnim != ASURA_HASH_ID_UNSET)
	{
		Asura_AnimationController_Animation* pxController = pxAnim->CreateControllerAnimation(m_uTrophyAnim, AAC_FLAG_ACTIVE, 1, m_uTrophyAnim, NULL);
		if (pxController)
		{
			pxController->Play();
		}
	}

	Asura_AnimationAttachment_Animation* pxAttachment = new Asura_AnimationAttachment_Animation(pxAnim, true);
	if (!pxAttachment)
	{
		delete pxAnim;
		return;
	}

	pxAttachment->SetDeleteAnimOnUnlink(true);

	// Don't allow it to delete with the anim, as we need to keep track of it here.
	if (!pxAttachment->LinkAttachment(pxOwnerAnim, m_uTrophyMarkerPoint, false))
	{
		delete pxAttachment;
		return;
	}

	m_pxTrophyAttachment = pxAttachment;

	// We also want to attach the same pfx we normally do to a gib.
	AVP_ClientEntity_Gib::PFXAttachData axPFXAttachData[uAVP_VERTEBRATE_GIB_MAX_PFX_ATTACHMENTS];
	u_int uNumPFXAttachments = 0;
	AVP_ClientEntity_Gib::FillPFXDetailsFromBlueprint(pxSkinElementBlueprint, axPFXAttachData, uNumPFXAttachments);
	const u_short usPFXFlags = ASURA_PFX_EFFECT_CAMERA_FLAGS;

	for (u_int u=0; u<uNumPFXAttachments; ++u)
	{
		const Asura_Hash_ID uPFXHash = axPFXAttachData[u].m_uPFXID;
		const Asura_Hash_ID uMarkerHash = axPFXAttachData[u].m_uMarkerID;
		if ((uPFXHash != ASURA_HASH_ID_UNSET) && (uMarkerHash != ASURA_HASH_ID_UNSET))
		{
			Asura_AnimationAttachment* pxAttachment = new Asura_AnimationAttachment_PFX(uPFXHash, usPFXFlags);
			if (pxAttachment)
			{
				pxAttachment->LinkAttachment(pxAnim, uMarkerHash, true);
			}
		}
	}
}

void AVP_Predator_Move_Melee_PickupHuman_Grapple_TrophyKill::DetachTrophy()
{
	if (!m_pxTrophyAttachment) { return; }

	if (m_pxTrophyAttachment->IsLinked())
	{
		m_pxTrophyAttachment->UnlinkAttachment();
	}
	delete m_pxTrophyAttachment;
	m_pxTrophyAttachment = NULL;
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupHuman_Grapple_Countered
// Author       : Anthony Gregson
// Date         : 13/03/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupHuman_Grapple_Countered::AVP_Predator_Move_Melee_PickupHuman_Grapple_Countered(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_HUMAN, uAVP_BLUEPRINT_NAME_PICKUPHUMAN)
{
}

bool AVP_Predator_Move_Melee_PickupHuman_Grapple_Countered::ShouldStart() const
{
	const AVP_Move_Melee_GenericPuppeteer_Start* pxCurrentMove = static_cast<const AVP_Move_Melee_GenericPuppeteer_Start*>(GetParentSystem().GetCurrentMove());
	if (pxCurrentMove)
	{
		if (pxCurrentMove->GetCountered()) { return true; }

		if (pxCurrentMove->GetFinalAttackType() == AVP_MELEEATTACK_TYPE_NONE) { return true; }

		// Make sure this starts if the enemy is invulnerable, as a kill move is a bit broken in that situation.
		// This means finding the puppet entity connected to the previous move.
		const AVP_ClientEntity_Actor* pxPuppet = AVP_ClientEntity_Actor::FindEntity(pxCurrentMove->GetCurrentPuppet());
		if (!pxPuppet || pxPuppet->IsInvulnerable()) { return true; }

		return false;
	}

	return false;
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_StealthPickupHuman_Start
// Author       : Anthony Gregson
// Date         : 30/09/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_StealthPickupHuman_Start::AVP_Predator_Move_Melee_StealthPickupHuman_Start(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "StealthPickupHumanAttack",
		 AVP_Predator_Move_Melee_StealthPickupHuman_Return_Hit::GetStaticHash(), AVP_Predator_Move_Melee_StealthPickupHuman_Return_Countered::GetStaticHash(), AVP_Predator_Move_Melee_StealthPickupHuman_Return_Miss::GetStaticHash())
{
	AddNextMove(AVP_Move_Melee_Grapple_Start::GetStaticHash());

	m_bClearQueuedMeleeRequests = true;
}


////////////////////////////////////////////////////////////////////////////////
// Class	    : AVP_Predator_Move_Melee_StealthPickupHuman_Return_Hit
// Author       : Anthony Gregson
// Date         : 30/09/08
////////////////////////////////////////////////////////////////////////////////

// Currently hit, countered and miss all use the same animation, set up with just one parameter.
static const char* g_szHumanStealthPickupReturnParameterName = "StealthPickupHumanReturn";

AVP_Predator_Move_Melee_StealthPickupHuman_Return_Hit::AVP_Predator_Move_Melee_StealthPickupHuman_Return_Hit(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szHumanStealthPickupReturnParameterName)
{
	m_bClearQueuedMeleeRequests = true;
}

bool AVP_Predator_Move_Melee_StealthPickupHuman_Return_Hit::ShouldStart() const
{
	// If the parent says we can start, check that the entity is of a type that we don't attach on to.
	if (!PARENT::ShouldStart()) { return false; }

	// There's only one move we can have come from.
	const AVP_Predator_Move_Melee_StealthPickupHuman_Start* pxCurrentMove = static_cast<const AVP_Predator_Move_Melee_StealthPickupHuman_Start*>(GetParentSystem().GetCurrentMove());
	if (!pxCurrentMove) { return false; }

	const AVP_ClientEntity_Actor* pxVictim = AVP_ClientEntity_Actor::FindEntity(pxCurrentMove->GetHitEntity());
	// TODO - These next two checks take the safe option of using this move if our victim has gone missing or died, but we should possibly be going into miss in that case.
	if (!pxVictim) { return true; }
	if (pxVictim->IsDead()) { return true; }

	switch (pxVictim->GetClassification())
	{
	default:
		return true;

		// Humans are attached to, so don't start this move.
	case AVP_ENTITYCLASS_ANDROID:
	case AVP_ENTITYCLASS_CIVILIAN:
	case AVP_ENTITYCLASS_MARINE:
		// However, we can only grab them if they aren't invulnerable.
		return pxVictim->IsInvulnerable();
	}
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_StealthPickupHuman_Return_Countered
// Author       : Anthony Gregson
// Date         : 30/09/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_StealthPickupHuman_Return_Countered::AVP_Predator_Move_Melee_StealthPickupHuman_Return_Countered(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szHumanStealthPickupReturnParameterName)
{
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_StealthPickupHuman_Return_Miss
// Author       : Anthony Gregson
// Date         : 30/09/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_StealthPickupHuman_Return_Miss::AVP_Predator_Move_Melee_StealthPickupHuman_Return_Miss(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szHumanStealthPickupReturnParameterName)
{
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_StealthPickupHuman_Grapple
// Author       : Anthony Gregson
// Date         : 30/09/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_StealthPickupHuman_Grapple::AVP_Predator_Move_Melee_StealthPickupHuman_Grapple(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_HUMAN, uAVP_BLUEPRINT_NAME_STEALTHPICKUPHUMAN)
{
	m_bAlwaysFatal = true;
}

void AVP_Predator_Move_Melee_StealthPickupHuman_Grapple::UpdateStates(const float fTimeStep)
{
	if (m_uLastStatesUpdateFrameStamp != Asura_Timers::GetFrameNumber()) // Make sure we don't do this twice because of the external update.
	{
		const u_int uAnimFlags = GetAnimFlagsForLastFrame();
		if (uAnimFlags & AVP_ANIMFLAG_GRAPPLE_APPLY_DAMAGE)
		{
			AVP_ClientActor_Predator* pxPred = AVP_ClientActor_Predator::FindEntity( GetParentSystem().GetOwnerGuid() );
			if ( pxPred )
			{
				pxPred->RegainEnergyFromTrophyKill( AVP_ENTITYCLASS_HUMAN );
			}
		}
	}

	PARENT::UpdateStates(fTimeStep);
}

bool AVP_Predator_Move_Melee_StealthPickupHuman_Grapple::Start(const Asura_Msg_Move* pxStartMsg)
{
	bool bSuccess = PARENT::Start(pxStartMsg);

	if (bSuccess)
	{
		// Unusually, we need to rotate the enemy to face away from us.
		m_xPuppetOrientationInterpolation.SetFinal(Asura_Maths::IdentityQuat);
	}

	return bSuccess;
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupDownedAlien_Start
// Author       : Anthony Gregson
// Date         : 07/07/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupDownedAlien_Start::AVP_Predator_Move_Melee_PickupDownedAlien_Start(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "PickupDownedAlienAttack",
		 AVP_Predator_Move_Melee_PickupDownedAlien_Return_Hit::GetStaticHash(), AVP_Predator_Move_Melee_PickupDownedAlien_Return_Countered::GetStaticHash(), AVP_Predator_Move_Melee_PickupDownedAlien_Return_Miss::GetStaticHash())
{
	AddNextMove(AVP_Move_Melee_Grapple_Start::GetStaticHash());

	m_bClearQueuedMeleeRequests = true;
}


////////////////////////////////////////////////////////////////////////////////
// Class	    : AVP_Predator_Move_Melee_PickupDownedAlien_Return_Hit
// Author       : Anthony Gregson
// Date         : 07/07/08
////////////////////////////////////////////////////////////////////////////////

// Currently hit and miss both use the same animation, set up with just one parameter.
static const char* g_szDownedAlienPickupMissParameterName = "PickupDownedAlienMiss";

AVP_Predator_Move_Melee_PickupDownedAlien_Return_Hit::AVP_Predator_Move_Melee_PickupDownedAlien_Return_Hit(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szDownedAlienPickupMissParameterName)
{
	m_bClearQueuedMeleeRequests = true;
}

bool AVP_Predator_Move_Melee_PickupDownedAlien_Return_Hit::ShouldStart() const
{
	// If the parent says we can start, check that the entity is of a type that we don't attach on to.
	if (!PARENT::ShouldStart()) { return false; }

	// There's only one move we can have come from.
	const AVP_Predator_Move_Melee_PickupDownedAlien_Start* pxCurrentMove = static_cast<const AVP_Predator_Move_Melee_PickupDownedAlien_Start*>(GetParentSystem().GetCurrentMove());
	if (!pxCurrentMove) { return false; }

	const AVP_ClientEntity_Actor* pxVictim = AVP_ClientEntity_Actor::FindEntity(pxCurrentMove->GetHitEntity());
	// TODO - These next two checks take the safe option of using this move if our victim has gone missing or died, but we should possibly be going into miss in that case.
	if (!pxVictim) { return true; }
	if (pxVictim->IsDead()) { return true; }

	switch (pxVictim->GetClassification())
	{
	default:
		return true;

		// The alien is attached to, so don't start this move.
	case AVP_ENTITYCLASS_ALIEN:
		// However, we can only grab them if they aren't invulnerable.
		return pxVictim->IsInvulnerable();
	}
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupDownedAlien_Return_Countered
// Author       : Anthony Gregson
// Date         : 07/07/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupDownedAlien_Return_Countered::AVP_Predator_Move_Melee_PickupDownedAlien_Return_Countered(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "PickupDownedAlienCountered")
{
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupDownedAlien_Return_Miss
// Author       : Anthony Gregson
// Date         : 07/07/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupDownedAlien_Return_Miss::AVP_Predator_Move_Melee_PickupDownedAlien_Return_Miss(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szDownedAlienPickupMissParameterName)
{
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupDownedAlien_Grapple_Start
// Author       : Anthony Gregson
// Date         : 14/10/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupDownedAlien_Grapple_Start::AVP_Predator_Move_Melee_PickupDownedAlien_Grapple_Start(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_ALIEN, uAVP_BLUEPRINT_NAME_PICKUPDOWNEDALIEN,
		 AVP_Predator_Move_Melee_PickupDownedAlien_Grapple_Success::GetStaticHash(), AVP_Predator_Move_Melee_PickupDownedAlien_Grapple_Countered::GetStaticHash())
{
}

////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupDownedAlien_Grapple_Success
// Author       : Anthony Gregson
// Date         : 14/10/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupDownedAlien_Grapple_Success::AVP_Predator_Move_Melee_PickupDownedAlien_Grapple_Success(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_ALIEN, uAVP_BLUEPRINT_NAME_PICKUPDOWNEDALIEN)
{
	m_bAlwaysFatal = true;
}

bool AVP_Predator_Move_Melee_PickupDownedAlien_Grapple_Success::ShouldStart() const
{
	const AVP_Move_Melee_GenericPuppeteer_Start* pxCurrentMove = static_cast<const AVP_Move_Melee_GenericPuppeteer_Start*>(GetParentSystem().GetCurrentMove());
	if (pxCurrentMove)
	{
		const AVP_ClientActor_Alien* pxAlien = AVP_ClientActor_Alien::FindEntity(pxCurrentMove->GetCurrentPuppet());
		if (pxAlien)
		{
			// If the alien is injured, always succeed.
			if (pxAlien->AreAnyElementsDamaged())
			{
				return true;
			}
		}
	}

	return PARENT::ShouldStart();
}

void AVP_Predator_Move_Melee_PickupDownedAlien_Grapple_Success::UpdateStates(const float fTimeStep)
{
	if (m_uLastStatesUpdateFrameStamp != Asura_Timers::GetFrameNumber()) // Make sure we don't do this twice because of the external update.
	{
		const u_int uAnimFlags = GetAnimFlagsForLastFrame();
		if (uAnimFlags & AVP_ANIMFLAG_GRAPPLE_APPLY_DAMAGE)
		{
			AVP_ClientActor_Predator* pxPred = AVP_ClientActor_Predator::FindEntity( GetParentSystem().GetOwnerGuid() );
			if ( pxPred )
			{
				pxPred->RegainEnergyFromTrophyKill( AVP_ENTITYCLASS_ALIEN );
			}
		}
	}

	PARENT::UpdateStates(fTimeStep);
}

////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupDownedAlien_Grapple_Countered
// Author       : Anthony Gregson
// Date         : 14/10/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupDownedAlien_Grapple_Countered::AVP_Predator_Move_Melee_PickupDownedAlien_Grapple_Countered(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_ALIEN, uAVP_BLUEPRINT_NAME_PICKUPDOWNEDALIEN)
{
}

bool AVP_Predator_Move_Melee_PickupDownedAlien_Grapple_Countered::ShouldStart() const
{
	const AVP_Move_Melee_GenericPuppeteer_Start* pxCurrentMove = static_cast<const AVP_Move_Melee_GenericPuppeteer_Start*>(GetParentSystem().GetCurrentMove());
	if (pxCurrentMove)
	{
		const AVP_ClientActor_Alien* pxAlien = AVP_ClientActor_Alien::FindEntity(pxCurrentMove->GetCurrentPuppet());
		if (pxAlien)
		{
			// If the alien is injured, always succeed.
			if (pxAlien->AreAnyElementsDamaged())
			{
				return false;
			}
		}
	}

	return PARENT::ShouldStart();
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupAlienCrouching_Start
// Author       : Anthony Gregson
// Date         : 05/11/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupAlienCrouching_Start::AVP_Predator_Move_Melee_PickupAlienCrouching_Start(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "PickupAllfoursAlienAttack",
		 AVP_Predator_Move_Melee_PickupAlienCrouching_Return_Hit::GetStaticHash(), AVP_Predator_Move_Melee_PickupAlienCrouching_Return_Countered::GetStaticHash(), AVP_Predator_Move_Melee_PickupAlienCrouching_Return_Miss::GetStaticHash())
{
	AddNextMove(AVP_Move_Melee_Grapple_Start::GetStaticHash());

	m_bClearQueuedMeleeRequests = true;
}


////////////////////////////////////////////////////////////////////////////////
// Class	    : AVP_Predator_Move_Melee_PickupAlienCrouching_Return_Hit
// Author       : Anthony Gregson
// Date         : 05/11/08
////////////////////////////////////////////////////////////////////////////////

// Currently hit and miss both use the same animation, set up with just one parameter.
static const char* g_szAlienCrouchingPickupMissParameterName = "PickupAllfoursAlienMiss";

AVP_Predator_Move_Melee_PickupAlienCrouching_Return_Hit::AVP_Predator_Move_Melee_PickupAlienCrouching_Return_Hit(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szAlienCrouchingPickupMissParameterName)
{
	m_bClearQueuedMeleeRequests = true;
}

bool AVP_Predator_Move_Melee_PickupAlienCrouching_Return_Hit::ShouldStart() const
{
	// If the parent says we can start, check that the entity is of a type that we don't attach on to.
	if (!PARENT::ShouldStart()) { return false; }

	// There's only one move we can have come from.
	const AVP_Predator_Move_Melee_PickupAlienCrouching_Start* pxCurrentMove = static_cast<const AVP_Predator_Move_Melee_PickupAlienCrouching_Start*>(GetParentSystem().GetCurrentMove());
	if (!pxCurrentMove) { return false; }

	const AVP_ClientEntity_Actor* pxVictim = AVP_ClientEntity_Actor::FindEntity(pxCurrentMove->GetHitEntity());
	// TODO - These next two checks take the safe option of using this move if our victim has gone missing or died, but we should possibly be going into miss in that case.
	if (!pxVictim) { return true; }
	if (pxVictim->IsDead()) { return true; }

	switch (pxVictim->GetClassification())
	{
	default:
		return true;

		// The alien is attached to, so don't start this move.
	case AVP_ENTITYCLASS_ALIEN:
		// However, we can only grab them if they aren't invulnerable.
		return pxVictim->IsInvulnerable();
	}
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupAlienCrouching_Return_Countered
// Author       : Anthony Gregson
// Date         : 05/11/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupAlienCrouching_Return_Countered::AVP_Predator_Move_Melee_PickupAlienCrouching_Return_Countered(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "PickupAllfoursAlienCountered")
{
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupAlienCrouching_Return_Miss
// Author       : Anthony Gregson
// Date         : 05/11/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupAlienCrouching_Return_Miss::AVP_Predator_Move_Melee_PickupAlienCrouching_Return_Miss(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szAlienCrouchingPickupMissParameterName)
{
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupAlienCrouching_Grapple_Start
// Author       : Anthony Gregson
// Date         : 05/11/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupAlienCrouching_Grapple_Start::AVP_Predator_Move_Melee_PickupAlienCrouching_Grapple_Start(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_ALIEN, uAVP_BLUEPRINT_NAME_PICKUPALIENCROUCHING,
		 AVP_Predator_Move_Melee_PickupAlienCrouching_Grapple_Success::GetStaticHash(), AVP_Predator_Move_Melee_PickupAlienCrouching_Grapple_Countered::GetStaticHash())
{
}

////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupAlienCrouching_Grapple_Success
// Author       : Anthony Gregson
// Date         : 05/11/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupAlienCrouching_Grapple_Success::AVP_Predator_Move_Melee_PickupAlienCrouching_Grapple_Success(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_ALIEN, uAVP_BLUEPRINT_NAME_PICKUPALIENCROUCHING)
{
	m_bAlwaysFatal = true;
}

void AVP_Predator_Move_Melee_PickupAlienCrouching_Grapple_Success::UpdateStates(const float fTimeStep)
{
	if (m_uLastStatesUpdateFrameStamp != Asura_Timers::GetFrameNumber()) // Make sure we don't do this twice because of the external update.
	{
		const u_int uAnimFlags = GetAnimFlagsForLastFrame();
		if (uAnimFlags & AVP_ANIMFLAG_GRAPPLE_APPLY_DAMAGE)
		{
			AVP_ClientActor_Predator* pxPred = AVP_ClientActor_Predator::FindEntity( GetParentSystem().GetOwnerGuid() );
			if ( pxPred )
			{
				pxPred->RegainEnergyFromTrophyKill( AVP_ENTITYCLASS_ALIEN );
			}
		}
	}

	PARENT::UpdateStates(fTimeStep);
}

////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupAlienCrouching_Grapple_Countered
// Author       : Anthony Gregson
// Date         : 05/11/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupAlienCrouching_Grapple_Countered::AVP_Predator_Move_Melee_PickupAlienCrouching_Grapple_Countered(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_ALIEN, uAVP_BLUEPRINT_NAME_PICKUPALIENCROUCHING)
{
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupAlienStanding_Start
// Author       : Anthony Gregson
// Date         : 05/11/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupAlienStanding_Start::AVP_Predator_Move_Melee_PickupAlienStanding_Start(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "PickupStandingAlienAttack",
		 AVP_Predator_Move_Melee_PickupAlienStanding_Return_Hit::GetStaticHash(), AVP_Predator_Move_Melee_PickupAlienStanding_Return_Countered::GetStaticHash(), AVP_Predator_Move_Melee_PickupAlienStanding_Return_Miss::GetStaticHash())
{
	AddNextMove(AVP_Move_Melee_Grapple_Start::GetStaticHash());

	m_bClearQueuedMeleeRequests = true;
}


////////////////////////////////////////////////////////////////////////////////
// Class	    : AVP_Predator_Move_Melee_PickupAlienStanding_Return_Hit
// Author       : Anthony Gregson
// Date         : 05/11/08
////////////////////////////////////////////////////////////////////////////////

// Currently hit and miss both use the same animation, set up with just one parameter.
static const char* g_szAlienStandingPickupMissParameterName = "PickupStandingAlienMiss";

AVP_Predator_Move_Melee_PickupAlienStanding_Return_Hit::AVP_Predator_Move_Melee_PickupAlienStanding_Return_Hit(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szAlienCrouchingPickupMissParameterName)
{
	m_bClearQueuedMeleeRequests = true;
}

bool AVP_Predator_Move_Melee_PickupAlienStanding_Return_Hit::ShouldStart() const
{
	// If the parent says we can start, check that the entity is of a type that we don't attach on to.
	if (!PARENT::ShouldStart()) { return false; }

	// There's only one move we can have come from.
	const AVP_Predator_Move_Melee_PickupAlienStanding_Start* pxCurrentMove = static_cast<const AVP_Predator_Move_Melee_PickupAlienStanding_Start*>(GetParentSystem().GetCurrentMove());
	if (!pxCurrentMove) { return false; }

	const AVP_ClientEntity_Actor* pxVictim = AVP_ClientEntity_Actor::FindEntity(pxCurrentMove->GetHitEntity());
	// TODO - These next two checks take the safe option of using this move if our victim has gone missing or died, but we should possibly be going into miss in that case.
	if (!pxVictim) { return true; }
	if (pxVictim->IsDead()) { return true; }

	switch (pxVictim->GetClassification())
	{
	default:
		return true;

		// The alien is attached to, so don't start this move.
	case AVP_ENTITYCLASS_ALIEN:
		// However, we can only grab them if they aren't invulnerable.
		return pxVictim->IsInvulnerable();
	}
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupAlienStanding_Return_Countered
// Author       : Anthony Gregson
// Date         : 05/11/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupAlienStanding_Return_Countered::AVP_Predator_Move_Melee_PickupAlienStanding_Return_Countered(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "PickupStandingAlienCountered")
{
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupAlienStanding_Return_Miss
// Author       : Anthony Gregson
// Date         : 05/11/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupAlienStanding_Return_Miss::AVP_Predator_Move_Melee_PickupAlienStanding_Return_Miss(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szAlienStandingPickupMissParameterName)
{
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupAlienStanding_Grapple_Start
// Author       : Anthony Gregson
// Date         : 05/11/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupAlienStanding_Grapple_Start::AVP_Predator_Move_Melee_PickupAlienStanding_Grapple_Start(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_ALIEN, uAVP_BLUEPRINT_NAME_PICKUPALIENSTANDING,
		 AVP_Predator_Move_Melee_PickupAlienStanding_Grapple_Success::GetStaticHash(), AVP_Predator_Move_Melee_PickupAlienStanding_Grapple_Countered::GetStaticHash())
{
}

////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupAlienStanding_Grapple_Success
// Author       : Anthony Gregson
// Date         : 05/11/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupAlienStanding_Grapple_Success::AVP_Predator_Move_Melee_PickupAlienStanding_Grapple_Success(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_ALIEN, uAVP_BLUEPRINT_NAME_PICKUPALIENSTANDING)
{
	m_bAlwaysFatal = true;
}

void AVP_Predator_Move_Melee_PickupAlienStanding_Grapple_Success::UpdateStates(const float fTimeStep)
{
	if (m_uLastStatesUpdateFrameStamp != Asura_Timers::GetFrameNumber()) // Make sure we don't do this twice because of the external update.
	{
		const u_int uAnimFlags = GetAnimFlagsForLastFrame();
		if (uAnimFlags & AVP_ANIMFLAG_GRAPPLE_APPLY_DAMAGE)
		{
			AVP_ClientActor_Predator* pxPred = AVP_ClientActor_Predator::FindEntity( GetParentSystem().GetOwnerGuid() );
			if ( pxPred )
			{
				pxPred->RegainEnergyFromTrophyKill( AVP_ENTITYCLASS_ALIEN );
			}
		}
	}

	PARENT::UpdateStates(fTimeStep);
}

////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_PickupAlienStanding_Grapple_Countered
// Author       : Anthony Gregson
// Date         : 05/11/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PickupAlienStanding_Grapple_Countered::AVP_Predator_Move_Melee_PickupAlienStanding_Grapple_Countered(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_ALIEN, uAVP_BLUEPRINT_NAME_PICKUPALIENSTANDING)
{
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Start
// Author       : Anthony Gregson
// Date         : 31/09/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Start::AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Start(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "StealthPickupAlienAttack",
		 AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Return_Hit::GetStaticHash(), AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Return_Countered::GetStaticHash(), AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Return_Miss::GetStaticHash())
{
	AddNextMove(AVP_Move_Melee_Grapple_Start::GetStaticHash());

	m_bClearQueuedMeleeRequests = true;
}


////////////////////////////////////////////////////////////////////////////////
// Class	    : AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Return_Hit
// Author       : Anthony Gregson
// Date         : 31/09/08
////////////////////////////////////////////////////////////////////////////////

// Currently hit, countered and miss all use the same animation, set up with just one parameter.
static const char* g_szCrouchingAlienStealthPickupReturnParameterName = "StealthPickupAlienReturn";

AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Return_Hit::AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Return_Hit(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szCrouchingAlienStealthPickupReturnParameterName)
{
	m_bClearQueuedMeleeRequests = true;
}

bool AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Return_Hit::ShouldStart() const
{
	// If the parent says we can start, check that the entity is of a type that we don't attach on to.
	if (!PARENT::ShouldStart()) { return false; }

	// There's only one move we can have come from.
	const AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Start* pxCurrentMove = static_cast<const AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Start*>(GetParentSystem().GetCurrentMove());
	if (!pxCurrentMove) { return false; }

	const AVP_ClientEntity_Actor* pxVictim = AVP_ClientEntity_Actor::FindEntity(pxCurrentMove->GetHitEntity());
	// TODO - These next two checks take the safe option of using this move if our victim has gone missing or died, but we should possibly be going into miss in that case.
	if (!pxVictim) { return true; }
	if (pxVictim->IsDead()) { return true; }

	switch (pxVictim->GetClassification())
	{
	default:
		return true;

		// Aliens are attached to, so don't start this move.
	case AVP_ENTITYCLASS_ALIEN:
		// However, we can only grab them if they aren't invulnerable.
		return pxVictim->IsInvulnerable();
	}
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Return_Countered
// Author       : Anthony Gregson
// Date         : 31/09/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Return_Countered::AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Return_Countered(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szCrouchingAlienStealthPickupReturnParameterName)
{
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Return_Miss
// Author       : Anthony Gregson
// Date         : 31/09/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Return_Miss::AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Return_Miss(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szCrouchingAlienStealthPickupReturnParameterName)
{
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Grapple
// Author       : Anthony Gregson
// Date         : 31/09/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Grapple::AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Grapple(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_ALIEN, uAVP_BLUEPRINT_NAME_STEALTHPICKUPALIENCROUCHING)
{
	m_bAlwaysFatal = true;
}

void AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Grapple::UpdateStates(const float fTimeStep)
{
	if (m_uLastStatesUpdateFrameStamp != Asura_Timers::GetFrameNumber()) // Make sure we don't do this twice because of the external update.
	{
		const u_int uAnimFlags = GetAnimFlagsForLastFrame();
		if (uAnimFlags & AVP_ANIMFLAG_GRAPPLE_APPLY_DAMAGE)
		{
			AVP_ClientActor_Predator* pxPred = AVP_ClientActor_Predator::FindEntity( GetParentSystem().GetOwnerGuid() );
			if ( pxPred )
			{
				pxPred->RegainEnergyFromTrophyKill( AVP_ENTITYCLASS_HUMAN );
			}
		}
	}

	PARENT::UpdateStates(fTimeStep);
}

bool AVP_Predator_Move_Melee_StealthPickupAlienCrouching_Grapple::Start(const Asura_Msg_Move* pxStartMsg)
{
	bool bSuccess = PARENT::Start(pxStartMsg);

	if (bSuccess)
	{
		// Unusually, we need to rotate the enemy to face away from us.
		m_xPuppetOrientationInterpolation.SetFinal(Asura_Maths::IdentityQuat);
	}

	return bSuccess;
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_StealthPickupAlienStanding_Start
// Author       : Anthony Gregson
// Date         : 31/09/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_StealthPickupAlienStanding_Start::AVP_Predator_Move_Melee_StealthPickupAlienStanding_Start(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "StealthPickupAlienStandingAttack",
		 AVP_Predator_Move_Melee_StealthPickupAlienStanding_Return_Hit::GetStaticHash(), AVP_Predator_Move_Melee_StealthPickupAlienStanding_Return_Countered::GetStaticHash(), AVP_Predator_Move_Melee_StealthPickupAlienStanding_Return_Miss::GetStaticHash())
{
	AddNextMove(AVP_Move_Melee_Grapple_Start::GetStaticHash());

	m_bClearQueuedMeleeRequests = true;
}


////////////////////////////////////////////////////////////////////////////////
// Class	    : AVP_Predator_Move_Melee_StealthPickupAlienStanding_Return_Hit
// Author       : Anthony Gregson
// Date         : 31/09/08
////////////////////////////////////////////////////////////////////////////////

// Currently hit, countered and miss all use the same animation, set up with just one parameter.
static const char* g_szStandingAlienStealthPickupReturnParameterName = "StealthPickupAlienStandingReturn";

AVP_Predator_Move_Melee_StealthPickupAlienStanding_Return_Hit::AVP_Predator_Move_Melee_StealthPickupAlienStanding_Return_Hit(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szStandingAlienStealthPickupReturnParameterName)
{
	m_bClearQueuedMeleeRequests = true;
}

bool AVP_Predator_Move_Melee_StealthPickupAlienStanding_Return_Hit::ShouldStart() const
{
	// If the parent says we can start, check that the entity is of a type that we don't attach on to.
	if (!PARENT::ShouldStart()) { return false; }

	// There's only one move we can have come from.
	const AVP_Predator_Move_Melee_StealthPickupAlienStanding_Start* pxCurrentMove = static_cast<const AVP_Predator_Move_Melee_StealthPickupAlienStanding_Start*>(GetParentSystem().GetCurrentMove());
	if (!pxCurrentMove) { return false; }

	const AVP_ClientEntity_Actor* pxVictim = AVP_ClientEntity_Actor::FindEntity(pxCurrentMove->GetHitEntity());
	// TODO - These next two checks take the safe option of using this move if our victim has gone missing or died, but we should possibly be going into miss in that case.
	if (!pxVictim) { return true; }
	if (pxVictim->IsDead()) { return true; }

	switch (pxVictim->GetClassification())
	{
	default:
		return true;

		// Aliens are attached to, so don't start this move.
	case AVP_ENTITYCLASS_ALIEN:
		// However, we can only grab them if they aren't invulnerable.
		return pxVictim->IsInvulnerable();
	}
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_StealthPickupAlienStanding_Return_Countered
// Author       : Anthony Gregson
// Date         : 31/09/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_StealthPickupAlienStanding_Return_Countered::AVP_Predator_Move_Melee_StealthPickupAlienStanding_Return_Countered(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szStandingAlienStealthPickupReturnParameterName)
{
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_StealthPickupAlienStanding_Return_Miss
// Author       : Anthony Gregson
// Date         : 31/09/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_StealthPickupAlienStanding_Return_Miss::AVP_Predator_Move_Melee_StealthPickupAlienStanding_Return_Miss(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szStandingAlienStealthPickupReturnParameterName)
{
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_StealthPickupAlienStanding_Grapple
// Author       : Anthony Gregson
// Date         : 31/09/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_StealthPickupAlienStanding_Grapple::AVP_Predator_Move_Melee_StealthPickupAlienStanding_Grapple(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_ALIEN, uAVP_BLUEPRINT_NAME_STEALTHPICKUPALIENSTANDING)
{
	m_bAlwaysFatal = true;
}

void AVP_Predator_Move_Melee_StealthPickupAlienStanding_Grapple::UpdateStates(const float fTimeStep)
{
	if (m_uLastStatesUpdateFrameStamp != Asura_Timers::GetFrameNumber()) // Make sure we don't do this twice because of the external update.
	{
		const u_int uAnimFlags = GetAnimFlagsForLastFrame();
		if (uAnimFlags & AVP_ANIMFLAG_GRAPPLE_APPLY_DAMAGE)
		{
			AVP_ClientActor_Predator* pxPred = AVP_ClientActor_Predator::FindEntity( GetParentSystem().GetOwnerGuid() );
			if ( pxPred )
			{
				pxPred->RegainEnergyFromTrophyKill( AVP_ENTITYCLASS_HUMAN );
			}
		}
	}

	PARENT::UpdateStates(fTimeStep);
}

bool AVP_Predator_Move_Melee_StealthPickupAlienStanding_Grapple::Start(const Asura_Msg_Move* pxStartMsg)
{
	bool bSuccess = PARENT::Start(pxStartMsg);

	if (bSuccess)
	{
		// Unusually, we need to rotate the enemy to face away from us.
		m_xPuppetOrientationInterpolation.SetFinal(Asura_Maths::IdentityQuat);
	}

	return bSuccess;
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_CounterAlienCrawlStandAttackLeft
// Author       : Anthony Gregson
// Date         : 11/07/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_CounterAlienCrawlStandAttackLeft::AVP_Predator_Move_Melee_CounterAlienCrawlStandAttackLeft(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash()) // Because we use unique parameter names for this, we have to set up the animations ourselves.
{
	m_bNoBranching = true;

	const Asura_Blueprint* pxBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_GRAPPLEPREDATOR, uAVP_BLUEPRINT_NAME_PREDATORCOUNTER_ALIENCRAWLSTANDATTACK);
	if (pxBlueprint)
	{
		Asura_Hash_ID uFirstPersonHash = ASURA_HASH_ID_UNSET;
		Asura_Hash_ID uThirdPersonHash = ASURA_HASH_ID_UNSET;
		Asura_Value xValue;
		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_PREDATORLEFTCLAW_FIRSTPERSON, xValue))
		{
			uFirstPersonHash = xValue.GetHashIDValue();
		}
		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_PREDATORLEFTCLAW_THIRDPERSON, xValue))
		{
			uThirdPersonHash = xValue.GetHashIDValue();
		}
		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_INITIALOFFSET, xValue))
		{
			m_fInitialVictimForwardOffset = xValue.GetFloatValue();
		}

		SetAnimHashes(uFirstPersonHash, uThirdPersonHash);

		if (m_pxAVPAnimationData)
		{
			m_pxAVPAnimationData->SetTweenData(g_fTweenInDuration, g_fTweenOutDuration, true);
			m_pxAVPAnimationData->SetLeaveAnimAtEnd(true);
		}

		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_ALIENLEFTCLAW_FIRSTPERSON, xValue))
		{
			m_uFirstPersonVictimAnimID = xValue.GetHashIDValue();
		}
		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_ALIENLEFTCLAW_THIRDPERSON, xValue))
		{
			m_uThirdPersonVictimAnimID = xValue.GetHashIDValue();
		}
	}
}

bool AVP_Predator_Move_Melee_CounterAlienCrawlStandAttackLeft::Start(const Asura_Msg_Move* pxStartMsg)
{
	// If we successfully start, tweak the puppet settings slightly.
	const bool bSuccess = PARENT::Start(pxStartMsg);

	if (bSuccess)
	{
		AVP_ClientActor_Vertebrate* pxVictim = AVP_ClientActor_Vertebrate::FindEntity(m_uCurrentPuppet);
		if (!pxVictim) { return false; }

		Asura_Movement_System* pxMovementSystem = pxVictim->GetMovementSystem();
		if (!pxMovementSystem) { return false; }

		AVP_Move_Puppet* pxPuppetMove = static_cast<AVP_Move_Puppet*>(pxMovementSystem->GetMove(AVP_Move_Puppet::GetStaticHash()));
		if (!pxPuppetMove) { return false; }

		pxPuppetMove->SetAlwaysCreateRagdollOnDeath(true);
		pxPuppetMove->SetControlDeathInternally(false);
		AVP_MoveData_Animation* pxPuppetAnimData = pxPuppetMove->GetAVPAnimationData();
		if (pxPuppetAnimData)
		{
			pxPuppetAnimData->SetTweenData(pxPuppetAnimData->GetTweenInDuration(), 0.2f, false);
			pxPuppetMove->AddNextMove(AVP_Alien_Move_Melee_CrawlToStandAttackR_Return_Miss::GetStaticHash());
		}
	}

	return bSuccess;
}

////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Predator_Move_Melee_CounterAlienCrawlStandAttackRight
// Author       : Anthony Gregson
// Date         : 11/07/08
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_CounterAlienCrawlStandAttackRight::AVP_Predator_Move_Melee_CounterAlienCrawlStandAttackRight(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash()) // Because we use unique parameter names for this, we have to set up the animations ourselves.
{
	m_bNoBranching = true;
	const Asura_Blueprint* pxBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_GRAPPLEPREDATOR, uAVP_BLUEPRINT_NAME_PREDATORCOUNTER_ALIENCRAWLSTANDATTACK);
	if (pxBlueprint)
	{
		Asura_Hash_ID uFirstPersonHash = ASURA_HASH_ID_UNSET;
		Asura_Hash_ID uThirdPersonHash = ASURA_HASH_ID_UNSET;
		Asura_Value xValue;
		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_PREDATORRIGHTCLAW_FIRSTPERSON, xValue))
		{
			uFirstPersonHash = xValue.GetHashIDValue();
		}
		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_PREDATORRIGHTCLAW_THIRDPERSON, xValue))
		{
			uThirdPersonHash = xValue.GetHashIDValue();
		}
		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_INITIALOFFSET, xValue))
		{
			m_fInitialVictimForwardOffset = xValue.GetFloatValue();
		}

		SetAnimHashes(uFirstPersonHash, uThirdPersonHash);

		if (m_pxAVPAnimationData)
		{
			m_pxAVPAnimationData->SetTweenData(g_fTweenInDuration, g_fTweenOutDuration, true);
			m_pxAVPAnimationData->SetLeaveAnimAtEnd(true);
		}

		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_ALIENRIGHTCLAW_FIRSTPERSON, xValue))
		{
			m_uFirstPersonVictimAnimID = xValue.GetHashIDValue();
		}
		if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_ALIENRIGHTCLAW_THIRDPERSON, xValue))
		{
			m_uThirdPersonVictimAnimID = xValue.GetHashIDValue();
		}
	}
}

bool AVP_Predator_Move_Melee_CounterAlienCrawlStandAttackRight::Start(const Asura_Msg_Move* pxStartMsg)
{
	// If we successfully start, tweak the puppet settings slightly.
	const bool bSuccess = PARENT::Start(pxStartMsg);

	if (bSuccess)
	{
		AVP_ClientActor_Vertebrate* pxVictim = AVP_ClientActor_Vertebrate::FindEntity(m_uCurrentPuppet);
		if (!pxVictim) { return false; }

		Asura_Movement_System* pxMovementSystem = pxVictim->GetMovementSystem();
		if (!pxMovementSystem) { return false; }

		AVP_Move_Puppet* pxPuppetMove = static_cast<AVP_Move_Puppet*>(pxMovementSystem->GetMove(AVP_Move_Puppet::GetStaticHash()));
		if (!pxPuppetMove) { return false; }

		pxPuppetMove->SetAlwaysCreateRagdollOnDeath(true);
		pxPuppetMove->SetControlDeathInternally(false);
		AVP_MoveData_Animation* pxPuppetAnimData = pxPuppetMove->GetAVPAnimationData();
		if (pxPuppetAnimData)
		{
			pxPuppetAnimData->SetTweenData(pxPuppetAnimData->GetTweenInDuration(), 0.2f, false);
			pxPuppetMove->AddNextMove(AVP_Alien_Move_Melee_CrawlToStandAttackL_Return_Miss::GetStaticHash());
		}
	}

	return bSuccess;
}

////////////////////////////////////////////////////////////////////////////////
// Counter Predalien Close Attacks
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_CounterPredalienLeftClawAttack::AVP_Predator_Move_Melee_CounterPredalienLeftClawAttack(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_ALIEN, uAVP_BLUEPRINT_NAME_PREDATORCOUNTER_PREDALIENLEFTCLAW)
{
	m_bClearQueuedMeleeRequests = true;
}

AVP_Predator_Move_Melee_CounterPredalienRightClawAttack::AVP_Predator_Move_Melee_CounterPredalienRightClawAttack(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_ALIEN, uAVP_BLUEPRINT_NAME_PREDATORCOUNTER_PREDALIENRIGHTCLAW)
{
	m_bClearQueuedMeleeRequests = true;
}

AVP_Predator_Move_Melee_CounterPredalienTailSwipe::AVP_Predator_Move_Melee_CounterPredalienTailSwipe(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash())
{
	const Asura_Blueprint* pxFirstPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash);
	const Asura_Blueprint* pxThirdPersonBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uAVP_BLUEPRINT_TYPE_MELEE, uThirdPersonBlueprintHash);
	SetupAnimHashesFromBlueprint(pxFirstPersonBlueprint, pxThirdPersonBlueprint, "CounterPredalienTailSwipe");
	m_bClearQueuedMeleeRequests = true;
	if (m_pxAVPAnimationData)
	{
		m_pxAVPAnimationData->SetTweenData(g_fTweenInDuration, g_fTweenOutDuration, true);
		m_pxAVPAnimationData->SetLeaveAnimAtEnd(false);
	}
}

////////////////////////////////////////////////////////////////////////////////
// Counter Predalien Jump Down Attack
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_CounterPredalienJumpDownAttack::AVP_Predator_Move_Melee_CounterPredalienJumpDownAttack(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_ALIEN, uAVP_BLUEPRINT_NAME_PREDATORCOUNTER_PREDALIENJUMPDOWN)
{
	m_bClearQueuedMeleeRequests = true;
}

bool AVP_Predator_Move_Melee_CounterPredalienJumpDownAttack::Start(const Asura_Msg_Move* pxStartMsg)
{
	const bool bSuccess = PARENT::Start(pxStartMsg);

	if (bSuccess)
	{
		AVP_ClientActor_Vertebrate* pxVictim = AVP_ClientActor_Vertebrate::FindEntity(m_uCurrentPuppet);
		if (!pxVictim) { return false; }

		Asura_Movement_System* pxMovementSystem = pxVictim->GetMovementSystem();
		if (!pxMovementSystem) { return false; }

		AVP_Move_Puppet* pxPuppetMove = static_cast<AVP_Move_Puppet*>(pxMovementSystem->GetMove(AVP_Move_Puppet::GetStaticHash()));
		if (!pxPuppetMove) { return false; }

		pxPuppetMove->SetAlwaysCreateRagdollOnDeath(true);
		pxPuppetMove->SetControlDeathInternally(false);
		AVP_MoveData_Animation* pxPuppetAnimData = pxPuppetMove->GetAVPAnimationData();
		if (pxPuppetAnimData)
		{
			pxPuppetAnimData->SetTweenData(pxPuppetAnimData->GetTweenInDuration(), 0.2f, false);
			pxPuppetMove->AddNextMove(AVP_Predalien_Move_KnockedDown_Middle::GetStaticHash());
		}
	}

	return bSuccess;
}


////////////////////////////////////////////////////////////////////////////////
// Knocked down Predalien attacks
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_Move_Melee_PredalienPounceAttack_StartBase::AVP_Predator_Move_Melee_PredalienPounceAttack_StartBase(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash, Asura_Hash_ID uMoveHash)
: PARENT(xParentSystem, uMoveHash,
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "PredalienPounceAttackStart",
		 AVP_Predator_Move_Melee_PredalienPounceAttack_Return_Hit::GetStaticHash(), AVP_Predator_Move_Melee_PredalienPounceAttack_Return_Countered::GetStaticHash(), AVP_Predator_Move_Melee_PredalienPounceAttack_Return_Miss::GetStaticHash())
{
	m_bClearQueuedMeleeRequests = true;
}

AVP_Predator_Move_Melee_PredalienPounceAttack_Start1::AVP_Predator_Move_Melee_PredalienPounceAttack_Start1(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, GetStaticHash())
{
	AddNextMove(AVP_Predator_Move_Melee_PredalienPounceAttack_Grapple1::GetStaticHash());
}

AVP_Predator_Move_Melee_PredalienPounceAttack_Start2::AVP_Predator_Move_Melee_PredalienPounceAttack_Start2(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, GetStaticHash())
{
	AddNextMove(AVP_Predator_Move_Melee_PredalienPounceAttack_Grapple2::GetStaticHash());
}


AVP_Predator_Move_Melee_PredalienPounceAttack_StartKill::AVP_Predator_Move_Melee_PredalienPounceAttack_StartKill(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, GetStaticHash())
{
	AddNextMove(AVP_Predator_Move_Melee_PredalienPounceAttack_GrappleKill::GetStaticHash());
}

AVP_Predator_Move_Melee_PredalienPounceAttack_Return_Hit::AVP_Predator_Move_Melee_PredalienPounceAttack_Return_Hit(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "PredalienPounceAttackHit")
{
	m_bClearQueuedMeleeRequests = true;
}

bool AVP_Predator_Move_Melee_PredalienPounceAttack_Return_Hit::ShouldStart() const
{
	// If the parent says we can start, check that the entity is of a type that we don't attach on to.
	if (!PARENT::ShouldStart()) { return false; }

	// There's only one move we can have come from.
	const AVP_Predator_Move_Melee_PredalienPounceAttack_StartBase* pxCurrentMove = static_cast<const AVP_Predator_Move_Melee_PredalienPounceAttack_StartBase*>(GetParentSystem().GetCurrentMove());
	if (!pxCurrentMove) { return false; }

	const AVP_ClientEntity_Actor* pxVictim = AVP_ClientEntity_Actor::FindEntity(pxCurrentMove->GetHitEntity());
	// TODO - These next two checks take the safe option of using this move if our victim has gone missing or died, but we should possibly be going into miss in that case.
	if (!pxVictim) { return true; }
	if (pxVictim->IsDead()) { return true; }

	switch (pxVictim->GetClassification())
	{
	default:
		return true;

		// Predalien is attached to, so don't start this move.
	case AVP_ENTITYCLASS_PREDALIEN:
		// However, we can only grab them if they aren't invulnerable.
		return pxVictim->IsInvulnerable();
	}
}

AVP_Predator_Move_Melee_PredalienPounceAttack_Return_Countered::AVP_Predator_Move_Melee_PredalienPounceAttack_Return_Countered(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "PredalienPounceAttackCountered")
{
}

AVP_Predator_Move_Melee_PredalienPounceAttack_Return_Miss::AVP_Predator_Move_Melee_PredalienPounceAttack_Return_Miss(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "PredalienPounceAttackMiss")
{
}

AVP_Predator_Move_Melee_PredalienPounceAttack_Grapple1::AVP_Predator_Move_Melee_PredalienPounceAttack_Grapple1(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_ALIEN, uAVP_BLUEPRINT_NAME_PREDATOR_GRAPPLEPREDALIEN1)
{
	m_bAlwaysFatal = false;
}

void AVP_Predator_Move_Melee_PredalienPounceAttack_Grapple1::UpdateStates(const float fTimeStep)
{
	if (m_uLastStatesUpdateFrameStamp != Asura_Timers::GetFrameNumber()) // Make sure we don't do this twice because of the external update.
	{
		const u_int uAnimFlags = GetAnimFlagsForLastFrame();
		if (uAnimFlags & AVP_ANIMFLAG_GRAPPLE_APPLY_DAMAGE)
		{
			AVP_ClientActor_Predator* pxPred = AVP_ClientActor_Predator::FindEntity( GetParentSystem().GetOwnerGuid() );
			if ( pxPred )
			{
				pxPred->RegainEnergyFromTrophyKill( AVP_ENTITYCLASS_PREDALIEN );
			}
		}
	}

	PARENT::UpdateStates(fTimeStep);
}

bool AVP_Predator_Move_Melee_PredalienPounceAttack_Grapple1::Start(const Asura_Msg_Move* pxStartMsg)
{
	bool bSuccess = PARENT::Start(pxStartMsg);

	if (bSuccess)
	{
		// Unusually, we need to rotate the enemy to face away from us.
		m_xPuppetOrientationInterpolation.SetFinal(Asura_Maths::IdentityQuat);
	}

	return bSuccess;
}



AVP_Predator_Move_Melee_PredalienPounceAttack_Grapple2::AVP_Predator_Move_Melee_PredalienPounceAttack_Grapple2(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_ALIEN, uAVP_BLUEPRINT_NAME_PREDATOR_GRAPPLEPREDALIEN2)
{
	m_bAlwaysFatal = false;
}

void AVP_Predator_Move_Melee_PredalienPounceAttack_Grapple2::UpdateStates(const float fTimeStep)
{
	if (m_uLastStatesUpdateFrameStamp != Asura_Timers::GetFrameNumber()) // Make sure we don't do this twice because of the external update.
	{
		const u_int uAnimFlags = GetAnimFlagsForLastFrame();
		if (uAnimFlags & AVP_ANIMFLAG_GRAPPLE_APPLY_DAMAGE)
		{
			AVP_ClientActor_Predator* pxPred = AVP_ClientActor_Predator::FindEntity( GetParentSystem().GetOwnerGuid() );
			if ( pxPred )
			{
				pxPred->RegainEnergyFromTrophyKill( AVP_ENTITYCLASS_PREDALIEN );
			}
		}
	}

	PARENT::UpdateStates(fTimeStep);
}

bool AVP_Predator_Move_Melee_PredalienPounceAttack_Grapple2::Start(const Asura_Msg_Move* pxStartMsg)
{
	bool bSuccess = PARENT::Start(pxStartMsg);

	if (bSuccess)
	{
		// Unusually, we need to rotate the enemy to face away from us.
		m_xPuppetOrientationInterpolation.SetFinal(Asura_Maths::IdentityQuat);
	}

	return bSuccess;
}


AVP_Predator_Move_Melee_PredalienPounceAttack_GrappleKill::AVP_Predator_Move_Melee_PredalienPounceAttack_GrappleKill(Asura_Movement_System& xParentSystem)
: PARENT(xParentSystem, GetStaticHash(),
		 AVP_Settings::AVP_SPECIES_PREDATOR, AVP_Settings::AVP_SPECIES_ALIEN, uAVP_BLUEPRINT_NAME_PREDATOR_GRAPPLEPREDALIENKILL)
{
	m_bAlwaysFatal = true;
}

void AVP_Predator_Move_Melee_PredalienPounceAttack_GrappleKill::UpdateStates(const float fTimeStep)
{
	if (m_uLastStatesUpdateFrameStamp != Asura_Timers::GetFrameNumber()) // Make sure we don't do this twice because of the external update.
	{
		const u_int uAnimFlags = GetAnimFlagsForLastFrame();
		if (uAnimFlags & AVP_ANIMFLAG_GRAPPLE_APPLY_DAMAGE)
		{
			AVP_ClientActor_Predator* pxPred = AVP_ClientActor_Predator::FindEntity( GetParentSystem().GetOwnerGuid() );
			if ( pxPred )
			{
				pxPred->RegainEnergyFromTrophyKill( AVP_ENTITYCLASS_PREDALIEN );
			}
		}
	}

	PARENT::UpdateStates(fTimeStep);
}

bool AVP_Predator_Move_Melee_PredalienPounceAttack_GrappleKill::Start(const Asura_Msg_Move* pxStartMsg)
{
	bool bSuccess = PARENT::Start(pxStartMsg);

	if (bSuccess)
	{
		// Unusually, we need to rotate the enemy to face away from us.
		m_xPuppetOrientationInterpolation.SetFinal(Asura_Maths::IdentityQuat);
	}

	return bSuccess;
}

/// End of file. ///
