
///////////////////////////////////////////////////////////////////////////////
//
// File   : AVP_Predator_AIAnimStateMachine.cpp
// Author : Andy Tate
// Date   : 14-Dec-2006
//
// Copyright (C) 2006 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

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

#include "Core/Asura.h"

// This file's header...
#include "Actor/Vertebrates/Predator/AVP_Predator_AIAnimStateMachine.h"

#include "Rendering/Asura_Font_System.h"
#include "Network/Asura_Message.h"

#include "Actor/Vertebrates/Predator/AVP_Predator_AIAnimStateConnections.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_AIAnimStateData.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_JumpHandler.h"
#include "Core/AVP_Settings.h"
#include "Entity/PhysicalObject/Actor/AVP_ServerEntity_Actor.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Predator/AVP_Messages_Predator.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Predator/AVP_ServerActor_Predator.h"
#include "Inventory/AVP_Inventory_Group.h"
#include "Inventory/AVP_Inventory_HashIDs.h"
#include "Inventory/AVP_Inventory_Item.h"
#include "Inventory/AVP_Inventory_System.h"
#include "Moves/Vertebrates/Predator/AVP_Predator_MovesJump.h"

static const char* g_aszStateString[ AVP_Predator_AIAnimStateMachine::PREDATOR_STATE_END - AVP_Predator_AIAnimStateMachine::PREDATOR_STATE_BEGIN ] = 
{
	"Crouch.Idle",			// PREDATOR_STATE_CROUCH_IDLE
	"Crouch.Move",			// PREDATOR_STATE_CROUCH_MOVE
	"Idle->Crouch.Idle",	// IDLE_TO_CROUCH_IDLE
	"Crouch.Idle->Idle"		// CROUCH_IDLE_TO_IDLE
};

static bool g_abDirectionalState[ AVP_Predator_AIAnimStateMachine::PREDATOR_STATE_END - AVP_Predator_AIAnimStateMachine::PREDATOR_STATE_BEGIN ] = 
{
	false,	// PREDATOR_STATE_CROUCH_IDLE
	true,	// PREDATOR_STATE_CROUCH_MOVE
	false,	// IDLE_TO_CROUCH_IDLE
	false	// CROUCH_IDLE_TO_IDLE
};

static bool g_abLoopedState[ AVP_Predator_AIAnimStateMachine::PREDATOR_STATE_END - AVP_Predator_AIAnimStateMachine::PREDATOR_STATE_BEGIN ] = 
{
	true,	// PREDATOR_STATE_CROUCH_IDLE
	true,	// PREDATOR_STATE_CROUCH_MOVE
	false,	// IDLE_TO_CROUCH_IDLE
	false	// CROUCH_IDLE_TO_IDLE
};

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

void AVP_Predator_AIAnimStateMachine::Initialise()
{
	// We load the anim data for all our weapons here to avoid long loading sequences in game.
	const AVP_Inventory_System* pxInvSys = m_xServerActor.GetInventorySystem();
	const AVP_Inventory_Group* pxWeaponGroup = pxInvSys != NULL ? pxInvSys->GetGroup( uAVP_INVENTORY_GROUPHASH_WEAPON ) : NULL;
	if ( pxWeaponGroup != NULL )
	{
		Asura_Hash_ID uWeaponItr( pxWeaponGroup->FindLowestPriorityItem() );
		for ( ; uWeaponItr != ASURA_HASH_ID_UNSET; uWeaponItr = pxWeaponGroup->FindNextHighestPriorityItem( uWeaponItr ) )
		{
			const AVP_Inventory_Item* pxItem = pxWeaponGroup->GetItem( uWeaponItr );
			if ( pxItem )
			{
				AVP_Predator_AIAnimStateData::InitialiseWeaponData( m_xServerActor.GetAnimStateBlueprintType(), pxItem->GetBlueprintHash() );
			}
		}
	}

	PARENT::Initialise();
}

const AVP_Actor_AnimStateData* AVP_Predator_AIAnimStateMachine::GetStateAnimData( const u_int uState ) const
{
	const AVP_Inventory_System* pxInvSys = m_xServerActor.GetInventorySystem();
	const AVP_Inventory_Group* pxWeaponGroup = pxInvSys != NULL ? pxInvSys->GetGroup( uAVP_INVENTORY_GROUPHASH_WEAPON ) : NULL;
	Asura_Assert( pxWeaponGroup != NULL, "Unable to get wepaon group" );
	if ( pxWeaponGroup != NULL )
	{
		const AVP_Inventory_Item* pxItem = pxWeaponGroup->GetCurrentInventoryItem();
		if ( pxItem )
		{
			return AVP_Predator_AIAnimStateData::GetAnimStateData( m_xServerActor.GetAnimStateBlueprintType(), pxItem->GetBlueprintHash(), uState );
		}
		else
		{
			return NULL;
		}
	}
	else
	{
		return NULL;
	}
}

void AVP_Predator_AIAnimStateMachine::BeginState( const u_int uState )
{
	AVP_ServerActor_Predator& xPred = static_cast< AVP_ServerActor_Predator& >( m_xServerActor );

	if ( uState == PREDATOR_STATE_CROUCH_MOVE )
	{
		xPred.SetMoving( true );
		xPred.SetCrouching( true );
	}
	else if ( uState == PREDATOR_STATE_CROUCH_IDLE )
	{
		xPred.SetCrouching( true );
	}

	PARENT::BeginState( uState );
}

bool AVP_Predator_AIAnimStateMachine::EndState( const u_int uState )
{
	AVP_ServerActor_Predator& xPred = static_cast< AVP_ServerActor_Predator& >( m_xServerActor );

	if ( uState == PREDATOR_STATE_CROUCH_MOVE )
	{
		xPred.SetMoving( false );
		xPred.SetCrouching( false );
	}
	else if ( uState == PREDATOR_STATE_CROUCH_IDLE )
	{
		xPred.SetCrouching( false );
	}

	return PARENT::EndState( uState );
}

#ifndef ASURA_NO_DEBUG_OUTPUT
void AVP_Predator_AIAnimStateMachine::RenderDebugInfo()
{
	PARENT::RenderDebugInfo();

	Asura_Vector_3 xDebugPos( m_xServerActor.GetPosition() );
	if ( Asura_Camera::ProjectWorldCoordsToScreenSpace( xDebugPos, true ) && xDebugPos.z > 0.0f)
	{
		xDebugPos.y -= 20.0f;

		const AVP_Inventory_System* pxInvSys = m_xServerActor.GetInventorySystem();
		const AVP_Inventory_Group* pxWeaponGroup = pxInvSys != NULL ? pxInvSys->GetGroup( uAVP_INVENTORY_GROUPHASH_WEAPON ) : NULL;
		Asura_Assert( pxWeaponGroup != NULL, "Unable to get wepaon group" );
		if ( pxWeaponGroup != NULL )
		{
			xDebugPos.y -= 10.0f;

			Asura_Font_System::Print
			(
				xDebugPos.GetX(),
				xDebugPos.GetY(),
				0.6f,
				0xffffffff,
				ASURA_TEXTFORMAT_CENTREJUSTIFIED | ASURA_TEXTFORMAT_FORMATSTRING, 
				"Weapon: 0x%08x", pxWeaponGroup->GetCurrentItem()
			);
		}
	}
}
#endif

const AVP_Actor_AIAnimStateConnectionData* AVP_Predator_AIAnimStateMachine::GetConnectionData( const u_int uFromState, const u_int uToState ) const
{
	return AVP_Predator_AIAnimStateConnections::GetConnectionData( uFromState, uToState );
}

const char* AVP_Predator_AIAnimStateMachine::GetStateDescriptionStatic( const u_int uState )
{
	if ( uState < PREDATOR_STATE_BEGIN )
	{
		return PARENT::GetStateDescriptionStatic( uState );
	}

	Asura_Assert( uState < PREDATOR_STATE_END, "Invalid state" );
	return g_aszStateString[ uState - PREDATOR_STATE_BEGIN ];
}

bool AVP_Predator_AIAnimStateMachine::IsDirectionalState( const u_int uState )
{
	if ( uState < PREDATOR_STATE_BEGIN )
	{
		return PARENT::IsDirectionalState( uState );
	}

	Asura_Assert( uState < PREDATOR_STATE_END, "Invalid state" );
	return g_abDirectionalState[ uState - PREDATOR_STATE_BEGIN ];
}

bool AVP_Predator_AIAnimStateMachine::IsLoopedStateStatic( const u_int uState )
{
	if ( uState < PREDATOR_STATE_BEGIN )
	{
		return PARENT::IsLoopedStateStatic( uState );
	}

	Asura_Assert( uState < PREDATOR_STATE_END, "Invalid state" );
	return g_abLoopedState[ uState - PREDATOR_STATE_BEGIN ];
}

/// End of file. ///
