
///////////////////////////////////////////////////////////////////////////////
//
// File   : AVP_ClientActor_AlienQueen.cpp
// Author : Andy McCabe
// Date   : 07-Nov-2008
//
// Copyright (C) 2008 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

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

#include "Core/Asura.h"

// This file's header...
#include "Entity/PhysicalObject/Actor/Vertebrates/AlienQueen/AVP_ClientActor_AlienQueen.h"

// Asura independent header-files...
#include "Blueprint/Asura_Blueprint_System.h"
#include "Core/Asura_Timers.h"
#include "Network/Asura_Message.h"
#include "Physics/Asura_Physics_Object.h"
#include "Rendering/Asura_Font_System.h"
#include "Rendering/Asura_Viewport.h"
#include "SpecialFX/PFX/Asura_PFX_System.h"
#include "SpecialFX/PFX/Asura_PFX_Entity_Effect.h"

// Game independent header-files...
#include "Actor/Vertebrates/AlienQueen/AVP_AlienQueen_AIAnimStateData.h"
#include "Actor/Vertebrates/AlienQueen/AVP_AlienQueen_AnimationHandler.h"
#include "Actor/Vertebrates/AlienQueen/AVP_AlienQueen_Description.h"
#include "Animation/AVP_AnimFlags.h"
#include "Blueprint/AVP_Blueprint_HashIDs.h"
#include "Core/AVP_Game_Core.h"
#include "Entity/AVP_Entity_Classification.h"
#include "Entity/Damage/AVP_EntityDamage_Apply.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/AVP_Vertebrate_Messages.h"
#include "Inventory/AVP_Inventory_System.h"
#include "Mesh/AVP_PolygonFlags.h"
#include "Moves/AVP_Movement_System.h"
#include "Moves/Vertebrates/AlienQueen/AVP_AlienQueen_MovesMelee.h"

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

//////////////////////////////////////////////////////////////////////////////
//
// AVP_ClientActor_AlienQueen
//
//////////////////////////////////////////////////////////////////////////////

Asura_Hashed_List<AVP_ClientActor_AlienQueen>	AVP_ClientActor_AlienQueen::s_xList;

AVP_ClientActor_AlienQueen::AVP_ClientActor_AlienQueen(void)
: AVP_ClientActor_Vertebrate(AVP_PolygonFlag_IgnoreForAlienCollision)
, m_uDroolPFXEffect(ASURA_PFX_INVALID_EFFECT_ID)
, m_uAlienQueenFlags(0)
{
	Classification = AVP_ENTITYCLASS_ALIENQUEEN;

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

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

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


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

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

void AVP_ClientActor_AlienQueen::PostCreateInitialise()
{
	// If there is no animation handler yet, create it.
	if( !m_pxAnimationHandler && GetBlueprintHashID() != ASURA_HASH_ID_UNSET )
	{
		CreateAnimationHandler();
	}

	PARENT::PostCreateInitialise();
}


void AVP_ClientActor_AlienQueen::GetCurrentBlockBlueprintHashes(Asura_Hash_ID& uBlueprintTypeHash, Asura_Hash_ID& uFirstPersonBlueprintHash, Asura_Hash_ID& uThirdPersonBlueprintHash) const
{
	// The alien doesn't have weapon variations, so the blueprint ids come from the main actor blueprint.
	uBlueprintTypeHash = uAVP_BLUEPRINT_TYPE_MOVESALIENQUEEN;
	uFirstPersonBlueprintHash = uThirdPersonBlueprintHash = ASURA_HASH_ID_UNSET;

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

	Asura_Value xValue;
	if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_BLOCK_FIRSTPERSON, xValue))
	{
		uFirstPersonBlueprintHash = xValue.GetHashIDValue();
	}

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

bool AVP_ClientActor_AlienQueen::InitialiseMoves( void )
{
	if(PARENT::InitialiseMoves())
	{
		Asura_Movement_System& xMovementSystem = *m_pxMovementSystem;
		Asura_Hash_ID uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash;
		GetCurrentMeleeBlueprintIDs(uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);

		// NOTE, creating a tree here so any move that is added to another must be listed here before the one that links to it. 

		new AVP_AlienQueen_Move_Melee_Stationary_Roar( xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash );

		new AVP_AlienQueen_Move_Melee_Charge_Collide(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
		new AVP_AlienQueen_Move_Melee_Charge_Collide_Injured(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
		new AVP_AlienQueen_Move_Melee_Charge_Into_Idle(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
		new AVP_AlienQueen_Move_Melee_Charge_Loop(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
		new AVP_AlienQueen_Move_Melee_Charge_BuildUp(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
		
		new AVP_AlienQueen_Move_Melee_ClawSwipe_Left_Return(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
		new AVP_AlienQueen_Move_Melee_ClawSwipe_Left_Start(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
		new AVP_AlienQueen_Move_Melee_ClawSwipe_Left_Loop_Start(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
		new AVP_AlienQueen_Move_Melee_ClawSwipe_Right_Return(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
		new AVP_AlienQueen_Move_Melee_ClawSwipe_Right_Start(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
		new AVP_AlienQueen_Move_Melee_ClawSwipe_Right_Loop_Start(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);

		new AVP_AlienQueen_Move_Melee_ClawSwipeKill_Return_Hit(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
		new AVP_AlienQueen_Move_Melee_ClawSwipeKill_Return_Countered(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
		new AVP_AlienQueen_Move_Melee_ClawSwipeKill_Return_Miss(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);
		new AVP_AlienQueen_Move_Melee_ClawSwipeKill_Grapple(xMovementSystem);
		new AVP_AlienQueen_Move_Melee_ClawSwipeKill_Start(xMovementSystem, uFirstPersonMeleeBlueprintHash, uThirdPersonMeleeBlueprintHash);

		// Spit Acid Attack - Not a melee move as such
		new AVP_AlienQueen_Move_Spit_Acid(xMovementSystem);

		new AVP_AlienQueen_Move_Stunned_Stumble( xMovementSystem );

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

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

bool AVP_ClientActor_AlienQueen::IsBoneInTorso( const int iBoneID )
{
//TBA	return AVP_AlienQueen_Description::GetElementFromBoneID( iBoneID ) == AVP_SET_BODY;
	return true;
}

Asura_Hash_ID AVP_ClientActor_AlienQueen::GetDeathAnimation(const AVP_EntityDamage_ApplyToEntity& xDamage) const
{
	// Always ragdoll from explosions
	bool bAlwaysRagdoll = false;
	Asura_Blueprint* pxBP = Asura_Blueprint_System::GetBlueprintByHashID( uAVP_BLUEPRINT_TYPE_DAMAGE, xDamage.GetTypeHash() );
	if ( pxBP )
	{
		Asura_Value xVal;
		if ( pxBP->GetParameterValueByHashID( uAVP_BLUEPRINT_PARAM_ALWAYSRAGDOLL, xVal ) )
		{
			bAlwaysRagdoll = xVal.GetBoolValue();
		}
	}
	if ( bAlwaysRagdoll ) { return ASURA_HASH_ID_UNSET; }


	const Asura_Blueprint* pxWeaponBlueprint = GetBlueprint();

	Asura_Value xValue;
	if (!pxWeaponBlueprint->GetParameterValueByHashID( uAVP_BLUEPRINT_PARAM_THIRDPERSONDEATH, xValue))
	{ 
		return ASURA_HASH_ID_UNSET; 
	}

	return xValue.GetHashIDValue();
}

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


void AVP_ClientActor_AlienQueen::GetCurrentMeleeBlueprintIDs(Asura_Hash_ID& uFirstPersonID, Asura_Hash_ID& uThirdPersonID) const
{
	uFirstPersonID = uThirdPersonID = ASURA_HASH_ID_UNSET;

	// As the alien, we just get them from our actor blueprint.
	const Asura_Blueprint* pxBlueprint = GetBlueprint();
	if (!pxBlueprint) { return; }

	Asura_Value xValue;
	if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_MELEE_FIRSTPERSON, xValue))
	{
		uFirstPersonID = xValue.GetHashIDValue();
	}

	if (pxBlueprint->GetParameterValueByHashID(uAVP_BLUEPRINT_PARAM_MELEE_THIRDPERSON, xValue))
	{
		uThirdPersonID = xValue.GetHashIDValue();
	}
}

bool AVP_ClientActor_AlienQueen::HandleMessage( const Asura_Message* pxMessage )
{
	if ( pxMessage->GetMsgID() == ASURA_MSG_CLIENTUPDATE )
	{
		const AVP_Message_Vertebrate_ClientUpdate* pxData = static_cast<const AVP_Message_Vertebrate_ClientUpdate*>(pxMessage->GetData());
		if ( pxData )
		{
			const bool	bIsLocalPlayer	= IsPlayer() && AVP_Game_Core::IsLocalPlayer(GetPlayerInfoGuid());
			ProcessClientUpdate( pxData, pxMessage->GetSentTime(), !bIsLocalPlayer );
		}
		return true;
	}
	else
	{
		return PARENT::HandleMessage( pxMessage );
	}
}

void AVP_ClientActor_AlienQueen::ProcessClientUpdate( const AVP_Message_Vertebrate_ClientUpdate* pxData, const float fServerTime, const bool bProcessPosAndOri /*= true*/ )
{
	PARENT::ProcessClientUpdate( pxData, fServerTime, bProcessPosAndOri );
}

const AVP_Actor_AnimStateData* AVP_ClientActor_AlienQueen::GetStateDataFromMesssageData( const u_int uState, const AVP_Message_Actor_ClientUpdate* pxActorData )
{
	return AVP_AlienQueen_AIAnimStateData::GetAnimStateData( GetAnimStateBlueprintType(), uState );
}

const AVP_Actor_AnimStateData* AVP_ClientActor_AlienQueen::GetStateData( const u_int uState, const u_int uGroundType, const u_int uLimbDamage, const bool bIsAiming, const u_int uCoverType)
{
	return AVP_AlienQueen_AIAnimStateData::GetAnimStateData( GetAnimStateBlueprintType(), uState );
}

/// End of file. ///
