
///////////////////////////////////////////////////////////////////////////////
//
// File   : AVP_Alien_MovesTail.cpp
// Author : Chris Wallace
// Date   : 29-Oct-2007
//
// Copyright (C) 2007 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

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

#include "Core/Asura.h"

// This file's header...
#include "Moves/Vertebrates/Alien/AVP_Alien_MovesTail.h"

// Asura independent header-files...
#include "Animation/Asura_AnimationController_Animation.h"
#include "Blueprint/Asura_Blueprint_System.h"

// Asura platform header-files...

// Game independent header-files...
#include "Actor/AVP_Actor_InteractionHandler.h"
#include "Actor/Vertebrates/AVP_Vertebrate_Description.h"
#include "Actor/Vertebrates/AVP_Vertebrate_Focus.h"
#include "Actor/Vertebrates/Alien/AVP_Alien_AnimationHandler.h"
#include "Actor/Vertebrates/Alien/AVP_Alien_Description.h"
#include "Actor/Vertebrates/Alien/AVP_Alien_InputHandler.h"
#include "Actor/Vertebrates/Alien/AVP_Alien_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/Damage/AVP_EntityDamage_Messages.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Alien/AVP_ClientActor_Alien.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/AVP_Vertebrate_Messages.h"
#include "Inventory/AVP_Inventory_System.h"
#include "Moves/AVP_Movement_System.h"

// Game platform header-files...

// Tools header-files...


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

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

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

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


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


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


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Alien_Move_Melee_TailAttack_Start
// Author       : Anthony Gregson
// Date         : 12/01/09
////////////////////////////////////////////////////////////////////////////////

AVP_Alien_Move_Melee_TailAttack_Start::AVP_Alien_Move_Melee_TailAttack_Start(Asura_Movement_System& xParentSystem, const Asura_Hash_ID uHash,
																			 const Asura_Hash_ID uFirstPersonBlueprintHash, const Asura_Hash_ID uThirdPersonBlueprintHash, const char* szBaseParameterName,
																			 const Asura_Hash_ID uHitReturnMove, const Asura_Hash_ID uCounteredReturnMove, const Asura_Hash_ID uMissReturnMove)
: PARENT(xParentSystem, uHash,
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, szBaseParameterName,
		 uHitReturnMove, uCounteredReturnMove, uMissReturnMove)
{
	m_bAllowSuckToEnemy = false;
}

bool AVP_Alien_Move_Melee_TailAttack_Start::Start( const Asura_Msg_Move* pxStartMsg )
{
	Asura_Assert(pxStartMsg, "Tail attacks should only be started by message.");

	AVP_Alien_AnimationHandler* pxAnimHandler = static_cast< AVP_Alien_AnimationHandler* >( GetAVPParentSystem().GetActorOwner().GetAnimationHandler() );
	if ( pxAnimHandler && pxStartMsg )
	{
		const AVP_Msg_MeleeWithTargetPosition_Move* pxFullData = static_cast<const AVP_Msg_MeleeWithTargetPosition_Move*>(pxStartMsg);
		const Asura_Guid uTargetGuid = pxFullData->GetTargetGuid();
		const AVP_ClientEntity_Actor* pxActorTarget = AVP_ClientEntity_Actor::FindEntity(uTargetGuid);
		if (pxActorTarget)
		{
			// Actor targets aim at the melee marker point.
			pxAnimHandler->StartTailStab_EntityTarget(uTargetGuid, AVP_Vertebrate_Description::GetMarkerPointHashID(AVP_Vertebrate_Description::MPID_TARGET_1));
		}
		else
		{
			const AVP_ClientEntity_PhysicalObject* pxPhysicalTarget = AVP_ClientEntity_PhysicalObject::FindEntity(uTargetGuid);
			if (pxPhysicalTarget)
			{
				// Physical object targets aim at the compass.
				pxAnimHandler->StartTailStab_EntityTarget(uTargetGuid, ASURA_HASH_ID_UNSET);
			}
			else
			{
				// Everything else aims at a worldspace target.
				pxAnimHandler->StartTailStab_WorldSpaceTarget(pxFullData->GetTargetPosition());
			}
		}
	}
	return PARENT::Start( pxStartMsg );
}

void AVP_Alien_Move_Melee_TailAttack_Start::Finish()
{
	AVP_Alien_AnimationHandler* pxAnimHandler = static_cast< AVP_Alien_AnimationHandler* >( GetAVPParentSystem().GetActorOwner().GetAnimationHandler() );
	if ( pxAnimHandler )
	{
		pxAnimHandler->FinishTailStab();
	}

	PARENT::Finish();
}

void AVP_Alien_Move_Melee_TailAttack_Start::Abort()
{
	AVP_Alien_AnimationHandler* pxAnimHandler = static_cast< AVP_Alien_AnimationHandler* >( GetAVPParentSystem().GetActorOwner().GetAnimationHandler() );
	if ( pxAnimHandler )
	{
		pxAnimHandler->FinishTailStab();
	}

	PARENT::Abort();
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Alien_Move_Melee_TailLash_Start
// Author       : Anthony Gregson
// Date         : 02/12/08
////////////////////////////////////////////////////////////////////////////////

AVP_Alien_Move_Melee_TailLash_Start::AVP_Alien_Move_Melee_TailLash_Start(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "TailLashAttack",
		 AVP_Alien_Move_Melee_TailLash_Return_Hit::GetStaticHash(), AVP_Alien_Move_Melee_TailLash_Return_Countered::GetStaticHash(), AVP_Alien_Move_Melee_TailLash_Return_Miss::GetStaticHash())
{
	m_bClearQueuedMeleeRequests = true;
	m_bForceCrouching = true;

	if (m_pxAVPAnimationData)
	{
		m_pxAVPAnimationData->SetDontCalculateVelocity(true);
		m_pxAVPAnimationData->SetDontCalculateAngularVelocity(true);
	}
}

////////////////////////////////////////////////////////////////////////////////
// Class	    : AVP_Alien_Move_Melee_TailLash_Return_Hit
// Author       : Anthony Gregson
// Date         : 02/12/08
////////////////////////////////////////////////////////////////////////////////

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

AVP_Alien_Move_Melee_TailLash_Return_Hit::AVP_Alien_Move_Melee_TailLash_Return_Hit(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szTailLashReturnParameterName)
{
	m_bClearQueuedMeleeRequests = true;
	m_bForceCrouching = true;

	if (m_pxAVPAnimationData)
	{
		m_pxAVPAnimationData->SetDontCalculateVelocity(true);
		m_pxAVPAnimationData->SetDontCalculateAngularVelocity(true);
	}
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Alien_Move_Melee_TailLash_Return_Countered
// Author       : Anthony Gregson
// Date         : 02/12/08
////////////////////////////////////////////////////////////////////////////////

AVP_Alien_Move_Melee_TailLash_Return_Countered::AVP_Alien_Move_Melee_TailLash_Return_Countered(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szTailLashReturnParameterName)
{
	m_bForceCrouching = true;

	if (m_pxAVPAnimationData)
	{
		m_pxAVPAnimationData->SetDontCalculateVelocity(true);
		m_pxAVPAnimationData->SetDontCalculateAngularVelocity(true);
	}
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Alien_Move_Melee_TailLash_Return_Miss
// Author       : Anthony Gregson
// Date         : 02/12/08
////////////////////////////////////////////////////////////////////////////////

AVP_Alien_Move_Melee_TailLash_Return_Miss::AVP_Alien_Move_Melee_TailLash_Return_Miss(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szTailLashReturnParameterName)
{
	m_bForceCrouching = true;

	if (m_pxAVPAnimationData)
	{
		m_pxAVPAnimationData->SetDontCalculateVelocity(true);
		m_pxAVPAnimationData->SetDontCalculateAngularVelocity(true);
	}
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Alien_Move_Melee_TailStab_Start
// Author       : Anthony Gregson
// Date         : 12/01/09
////////////////////////////////////////////////////////////////////////////////

AVP_Alien_Move_Melee_TailStab_Start::AVP_Alien_Move_Melee_TailStab_Start(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, "TailStabAttack",
		 AVP_Alien_Move_Melee_TailStab_Return_Hit::GetStaticHash(), AVP_Alien_Move_Melee_TailStab_Return_Countered::GetStaticHash(), AVP_Alien_Move_Melee_TailStab_Return_Miss::GetStaticHash())
{
	m_bClearQueuedMeleeRequests = true;
	m_bForceCrouching = true;
}

////////////////////////////////////////////////////////////////////////////////
// Class	    : AVP_Alien_Move_Melee_TailStab_Return_Hit
// Author       : Anthony Gregson
// Date         : 12/01/09
////////////////////////////////////////////////////////////////////////////////

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

AVP_Alien_Move_Melee_TailStab_Return_Hit::AVP_Alien_Move_Melee_TailStab_Return_Hit(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szTailStabReturnParameterName)
{
	m_bClearQueuedMeleeRequests = true;
	m_bForceCrouching = true;
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Alien_Move_Melee_TailStab_Return_Countered
// Author       : Anthony Gregson
// Date         : 12/01/09
////////////////////////////////////////////////////////////////////////////////

AVP_Alien_Move_Melee_TailStab_Return_Countered::AVP_Alien_Move_Melee_TailStab_Return_Countered(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szTailStabReturnParameterName)
{
	m_bForceCrouching = true;
}


////////////////////////////////////////////////////////////////////////////////
// Class		: AVP_Alien_Move_Melee_TailStab_Return_Miss
// Author       : Anthony Gregson
// Date         : 12/01/09
////////////////////////////////////////////////////////////////////////////////

AVP_Alien_Move_Melee_TailStab_Return_Miss::AVP_Alien_Move_Melee_TailStab_Return_Miss(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash(),
		 uAVP_BLUEPRINT_TYPE_MELEE, uFirstPersonBlueprintHash, uThirdPersonBlueprintHash, g_szTailStabReturnParameterName)
{
	m_bForceCrouching = true;
}


////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Alien_Move_Melee_TailCharge_Start
// Author       : Anthony Gregson
// Date         : 12/01/09
////////////////////////////////////////////////////////////////////////////////

AVP_Alien_Move_Melee_TailCharge_Start::AVP_Alien_Move_Melee_TailCharge_Start(Asura_Movement_System& xParentSystem, Asura_Hash_ID uFirstPersonBlueprintHash, Asura_Hash_ID uThirdPersonBlueprintHash)
: PARENT(xParentSystem, GetStaticHash())
{
	AddNextMove(AVP_Alien_Move_Melee_TailCharge_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, "TailChargeStart");
	}

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



////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Alien_Move_Melee_TailCharge_Loop
// Author       : Anthony Gregson
// Date         : 12/01/09
////////////////////////////////////////////////////////////////////////////////

AVP_Alien_Move_Melee_TailCharge_Loop::AVP_Alien_Move_Melee_TailCharge_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, "TailChargeLoop");
	}

	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_Alien_Move_Melee_TailCharge_End
// Author       : Anthony Gregson
// Date         : 12/01/09
////////////////////////////////////////////////////////////////////////////////

AVP_Alien_Move_Melee_TailCharge_End::AVP_Alien_Move_Melee_TailCharge_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, "TailChargeStart");
	}

	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);
	}
}


/// End of file. ///
