//------------------------------------------------------------------------------
// File   : AVP_ServerActor_Human.cpp
// Author : Gareth Thomas
// Date   : 12 / 02 / 2008
// Copyright (C) 2007 Rebellion, All Rights Reserved.
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Include files...
//------------------------------------------------------------------------------
// Core
#include "Core/Asura.h"

// This file's header...
#include "Entity/PhysicalObject/Actor/Vertebrates/Human/Civilian/AVP_ServerActor_Civilian.h"

// Asura files...
#include "Blueprint/Asura_Blueprint.h"
#include "Blueprint/Asura_Blueprint_System.h"
#include "Entity/Asura_Entity.h"
#include "Network/Asura_Message.h"

// Game independent header-files...
#include "Actor/Vertebrates/Human/AVP_Human_AIAnimStateMachine.h"
#include "Actor/Vertebrates/Human/AVP_Human_MoraleHandler.h"
#include "Entity/AVP_Entity_Classification.h"
#include "Entity/AVP_Entity_EventIDs.h"
#include "Entity/Controller/AVP_ServerEntity_Squad_Marine.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Human/AVP_Messages_Human.h"


// AVP axon
#include "Core/BrainTypes/AVP_Brain_Actor_Civilian.h"
#include "Knowledge/AVP_Knowledge_System_Actor.h"

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

Asura_Hashed_List<AVP_ServerActor_Civilian>	AVP_ServerActor_Civilian::s_xList;

//------------------------------------------------------------------------------
// AVP_ServerActor_Civilian:: Constructor
//------------------------------------------------------------------------------
AVP_ServerActor_Civilian::AVP_ServerActor_Civilian(const Asura_Guid uGUID)
: Asura_Entity_Server(uGUID)
, PARENT(uGUID)
, m_bDialogueHashIdsInitialised(false)
, m_eCivilianType(CIVILIANTYPE_CONSTRUCTION_WORKER)
, m_bAlertEventSent( false )
{
	// Update the data...
	Classification	= AVP_ENTITYCLASS_CIVILIAN;

	for (int i = 0; i < CIVILIAN_DLG_MAX_DIALOGUE_HASH_IDS; ++i)
	{
		m_uCivilianDialogueHashIDs[i] = ASURA_HASH_ID_UNSET;
	}

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

//------------------------------------------------------------------------------
// AVP_ServerActor_Civilian:: Destructor
//------------------------------------------------------------------------------
AVP_ServerActor_Civilian::~AVP_ServerActor_Civilian()
{
	s_xList.RemoveFromList(this);
}

//------------------------------------------------------------------------------
// AVP_ServerActor_Civilian:: ReadFromChunkStream
//------------------------------------------------------------------------------
void AVP_ServerActor_Civilian::ReadFromChunkStream(Asura_Chunk_Stream& xStream)
{
	// We were created without a chunk initially, so we must check if this is our chunk or our parent's.
	u_int uVersion = xStream.PeekUInt();

	if ( uVersion < 1000 )
	{
		PARENT::ReadFromChunkStream( xStream );
	}
	else
	{
		xStream >> uVersion;

		PARENT::ReadFromChunkStream( xStream );

		if ( uVersion == 1000)
		{
			m_uGuardZoneGuid = ASURA_GUID_UNREGISTERED;
			m_bAlertEventSent = false;
		}
		else if ( uVersion == 1001 )
		{
			xStream >> m_uGuardZoneGuid;
			m_bAlertEventSent = false;
		}
		else if ( uVersion == CURRENT_CHUNK_VERSION )
		{
			xStream >> m_uGuardZoneGuid;
			
			u_int uBoolVal = false;

			xStream >> uBoolVal;

			if ( uBoolVal == 0 )
			{
				m_bAlertEventSent = false;
			}
			else
			{
				m_bAlertEventSent = true;
			}
		}
		else
		{
			Asura_Assertf( false, ( "AVP_ServerActor_Civilian::ReadFromChunkStream - unhandled chunk version (%u)", uVersion ) );
		}
	}
}

//------------------------------------------------------------------------------
// AVP_ServerActor_Civilian:: WriteToChunkStream
//------------------------------------------------------------------------------
void AVP_ServerActor_Civilian::WriteToChunkStream(Asura_Chunk_Stream& xStream) const
{
	xStream << CURRENT_CHUNK_VERSION;

	PARENT::WriteToChunkStream( xStream );

	xStream << m_uGuardZoneGuid;

	if ( m_bAlertEventSent )
	{
		xStream << 1;
	}
	else
	{
		xStream << 0;
	}

	// No data yet.
}

//------------------------------------------------------------------------------
// AVP_ServerActor_Civilian:: WriteToClientCreateStream
//------------------------------------------------------------------------------
void AVP_ServerActor_Civilian::WriteToClientCreateStream(Asura_Chunk_Memory_Stream& xStream) const
{
 	// Call the base-function...
 	PARENT::WriteToClientCreateStream( xStream );
 
 	xStream << static_cast<u_int>(m_eCivilianType);
}

//------------------------------------------------------------------------------
// AVP_ServerActor_Civilian:: InitialiseFromBlueprint
//------------------------------------------------------------------------------
void AVP_ServerActor_Civilian::InitialiseFromBlueprint( const Asura_Blueprint& xBlueprint )
{
	PARENT::InitialiseFromBlueprint( xBlueprint );

	switch (GetBlueprintHashID())
	{
		//"CONSTRUCTIONWORKER"
		case (0x0814c38f):			m_eCivilianType = CIVILIANTYPE_CONSTRUCTION_WORKER; break;
		default:					m_eCivilianType = CIVILIANTYPE_CONSTRUCTION_WORKER; break;
	}
}

//------------------------------------------------------------------------------
// AVP_ServerActor_Civilian:: Create
//------------------------------------------------------------------------------
void AVP_ServerActor_Civilian::Create(Asura_Guid uGUID)
{
	new AVP_ServerActor_Civilian(uGUID);
}

//-----------------------------------------------------------------
// AVP_ServerActor_Civilian :: CreateAndReturn
//-----------------------------------------------------------------
AVP_ServerActor_Civilian* AVP_ServerActor_Civilian::CreateAndReturn(Asura_Guid uGUID)
{
	AVP_ServerActor_Civilian* pxAlien = new AVP_ServerActor_Civilian(uGUID);
	
	return pxAlien;
}

//-----------------------------------------------------------------
// AVP_ServerActor_Civilian :: OnDeath
//-----------------------------------------------------------------
void	AVP_ServerActor_Civilian::OnDeath(const AVP_EntityDamage_ApplyToEntity& xDamage)
{
	PARENT::OnDeath(xDamage);

	SendMessagesForEvent(AVP_ENTITY_EVENT_CIVILIAN_KILLED);
}

//-----------------------------------------------------------------
// AVP_ServerActor_Civilian :: InitialiseDialogueFromBlueprint
//-----------------------------------------------------------------
void AVP_ServerActor_Civilian::InitialiseDialogueFromBlueprint(Asura_Hash_ID uBlueprintHashID)
{
	if ( GetBlueprint() )
	{
		Asura_Value xValue;

		if ( GetBlueprint()->GetParameterValueByHashID( 0x661d3a4b , xValue ) ) // 0x661d3a4b; //"Dialogue Blueprint"
		{
			Asura_Hash_ID		uBlueprintTypeHashID		= 0xf20fd9d8; //Asura_GetHashID("Dialogue");
			Asura_Hash_ID		uDialogueBlueprintHashID	= xValue.GetHashIDValue();
			Asura_Blueprint*	pxBlueprint					= Asura_Blueprint_System::GetBlueprintByHashID(uBlueprintTypeHashID, uDialogueBlueprintHashID);

			Asura_Assertf( pxBlueprint, ( "Dialogue Blueprint Not Found For Civilian Actor With GUID Of %d", GetGuid() ) );

			if (pxBlueprint)
			{
				if (pxBlueprint->GetParameterValueByHashID(0x3099d0b0, xValue))		//0x3099d0b0; //"PASSIVE_TO_ALERT"
				{
					m_uCivilianDialogueHashIDs[CIVILIAN_DLG_HUMAN_PASSIVE_TO_ALERT] = xValue.GetHashIDValue();
				}
				else
				{
					Asura_Assert( false,  "Dialogue Paramater Not Found In Blueprint." );
				}

				if (pxBlueprint->GetParameterValueByHashID(0xe81e6559, xValue))		//0xe81e6559; //"ENTERING_AGGRESSIVE"
				{
					m_uCivilianDialogueHashIDs[CIVILIAN_DLG_HUMAN_ENTERING_AGGRESSIVE] = xValue.GetHashIDValue();
				}
				else
				{
					Asura_Assert( false,  "Dialogue Paramater Not Found In Blueprint." );
				}

				if (pxBlueprint->GetParameterValueByHashID(0xd3c48c73, xValue))		//0xd3c48c73; //"AGGRESSIVE_TO_ALERT"
				{
					m_uCivilianDialogueHashIDs[CIVILIAN_DLG_HUMAN_AGGRESSIVE_TO_ALERT] = xValue.GetHashIDValue();
				}
				else
				{
					Asura_Assert( false,  "Dialogue Paramater Not Found In Blueprint." );
				}

				if (pxBlueprint->GetParameterValueByHashID(0xc95a1426, xValue))		//0xc95a1426; //"ALERT_TO_PASSIVE"
				{
					m_uCivilianDialogueHashIDs[CIVILIAN_DLG_HUMAN_ALERT_TO_PASSIVE] = xValue.GetHashIDValue();
				}
				else
				{
					Asura_Assert( false,  "Dialogue Paramater Not Found In Blueprint." );
				}

				if (pxBlueprint->GetParameterValueByHashID(0x3e71ad2d, xValue))		//0x3e71ad2d; //"SNEAK_ATTACK_RESPONSE"
				{
					m_uCivilianDialogueHashIDs[CIVILIAN_DLG_HUMAN_SNEAK_ATTACK_RESPONSE] = xValue.GetHashIDValue();
				}
				else
				{
					Asura_Assert( false,  "Dialogue Paramater Not Found In Blueprint." );
				}

				if (pxBlueprint->GetParameterValueByHashID(0x2576dc15, xValue))		//0x2576dc15; //"TEAM_MATE_KILLED"
				{
					m_uCivilianDialogueHashIDs[CIVILIAN_DLG_HUMAN_TEAM_MATE_KILLED] = xValue.GetHashIDValue();
				}
				else
				{
					Asura_Assert( false,  "Dialogue Paramater Not Found In Blueprint." );
				}

				if (pxBlueprint->GetParameterValueByHashID(0xeb3035b4, xValue))		//0xeb3035b4; //"TAUNTING"
				{
					m_uCivilianDialogueHashIDs[CIVILIAN_DLG_HUMAN_TAUNTING] = xValue.GetHashIDValue();
				}
				else
				{
					Asura_Assert( false,  "Dialogue Paramater Not Found In Blueprint." );
				}

				if (pxBlueprint->GetParameterValueByHashID(0xe374a49a, xValue))		//0xe374a49a; //"ATTACKING"
				{
					m_uCivilianDialogueHashIDs[CIVILIAN_DLG_HUMAN_ATTACKING] = xValue.GetHashIDValue();
				}
				else
				{
					Asura_Assert( false,  "Dialogue Paramater Not Found In Blueprint." );
				}

				if (pxBlueprint->GetParameterValueByHashID(0x385e0c1c, xValue))		//0x385e0c1c; //"KILLED_THREAT"
				{
					m_uCivilianDialogueHashIDs[CIVILIAN_DLG_HUMAN_KILLED_THREAT] = xValue.GetHashIDValue();
				}
				else
				{
					Asura_Assert( false,  "Dialogue Paramater Not Found In Blueprint." );
				}

				if (pxBlueprint->GetParameterValueByHashID(0x6bd41904, xValue))		//0x6bd41904; //"KILLED_THREAT_RESPONSE"
				{
					m_uCivilianDialogueHashIDs[CIVILIAN_DLG_HUMAN_KILLED_THREAT_RESPONSE] = xValue.GetHashIDValue();
				}
				else
				{
					Asura_Assert( false,  "Dialogue Paramater Not Found In Blueprint." );
				}

				if (pxBlueprint->GetParameterValueByHashID(0x166103a9, xValue))		//0x166103a9; //"RELOADING"
				{
					m_uCivilianDialogueHashIDs[CIVILIAN_DLG_HUMAN_RELOADING] = xValue.GetHashIDValue();
				}
				else
				{
					Asura_Assert( false,  "Dialogue Paramater Not Found In Blueprint." );
				}

				if (pxBlueprint->GetParameterValueByHashID(0xd1c5c63c, xValue))		//0xd1c5c63c; //"FLEEING"
				{
					m_uCivilianDialogueHashIDs[CIVILIAN_DLG_HUMAN_FLEEING] = xValue.GetHashIDValue();
				}
				else
				{
					Asura_Assert( false,  "Dialogue Paramater Not Found In Blueprint." );
				}

				if (pxBlueprint->GetParameterValueByHashID(0x97cc205e, xValue))		//0x97cc205e; //"IDLE_CHATTER"
				{
					m_uCivilianDialogueHashIDs[CIVILIAN_DLG_HUMAN_IDLE_CHATTER] = xValue.GetHashIDValue();
				}
				else
				{
					Asura_Assert( false,  "Dialogue Paramater Not Found In Blueprint." );
				}

				m_bDialogueHashIdsInitialised = true;
			}
		}
	}
}

//-----------------------------------------------------------------
// AVP_ServerActor_Civilian :: GetDialogueHashIDFromDialoguetype
//-----------------------------------------------------------------
Asura_Hash_ID AVP_ServerActor_Civilian::GetDialogueHashIDFromDialoguetype(DialogueType uDialogType)
{
	switch (uDialogType)
	{
		case AVP_DLG_HUMAN_ALERT_TO_PASSIVE:						return ( m_uCivilianDialogueHashIDs[ CIVILIAN_DLG_HUMAN_ALERT_TO_PASSIVE ] );

		case AVP_DLG_HUMAN_IDLE_CHATTER:							return ( m_uCivilianDialogueHashIDs[ CIVILIAN_DLG_HUMAN_IDLE_CHATTER ] );

		case AVP_DLG_HUMAN_PASSIVE_TO_ALERT:						return ( m_uCivilianDialogueHashIDs[ CIVILIAN_DLG_HUMAN_PASSIVE_TO_ALERT ] );

		case AVP_DLG_HUMAN_AGGRESSIVE_TO_ALERT:						return ( m_uCivilianDialogueHashIDs[ CIVILIAN_DLG_HUMAN_AGGRESSIVE_TO_ALERT ] );

		case AVP_DLG_HUMAN_ENTERING_AGGRESSIVE:						return ( m_uCivilianDialogueHashIDs[ CIVILIAN_DLG_HUMAN_ENTERING_AGGRESSIVE] );

		case AVP_DLG_HUMAN_SCARED_REACTION:							return ( m_uCivilianDialogueHashIDs[ CIVILIAN_DLG_HUMAN_SNEAK_ATTACK_RESPONSE ] );

		case AVP_DLG_HUMAN_TEAMMATE_KILLED:							return ( m_uCivilianDialogueHashIDs[ CIVILIAN_DLG_HUMAN_TEAM_MATE_KILLED ] );

		case AVP_DLG_HUMAN_KILLED_THREAT:							return ( m_uCivilianDialogueHashIDs[ CIVILIAN_DLG_HUMAN_KILLED_THREAT ] );

		case AVP_DLG_HUMAN_TAUNTING:								return ( m_uCivilianDialogueHashIDs[ CIVILIAN_DLG_HUMAN_TAUNTING ] );

		case AVP_DLG_HUMAN_ATTACKING:								return ( m_uCivilianDialogueHashIDs[ CIVILIAN_DLG_HUMAN_ATTACKING ] );

		case AVP_DLG_HUMAN_KILLED_THREAT_RESPONSE:					return ( m_uCivilianDialogueHashIDs[ CIVILIAN_DLG_HUMAN_KILLED_THREAT_RESPONSE ] );

		case AVP_DLG_HUMAN_RELOADING:								return ( m_uCivilianDialogueHashIDs[ CIVILIAN_DLG_HUMAN_RELOADING ] );

		case AVP_DLG_HUMAN_FLEEING:									return ( m_uCivilianDialogueHashIDs[ CIVILIAN_DLG_HUMAN_FLEEING ] );

		default:													return ASURA_HASH_ID_UNSET;
	}
}

//------------------------------------------------------------------------------
// AVP_ServerActor_Civilian:: CreateBrain
//------------------------------------------------------------------------------
Axon_Brain* AVP_ServerActor_Civilian::CreateBrain()
{
	return new AVP_Brain_Actor_Civilian( this );
}

void AVP_ServerActor_Civilian::PostLoadInitialise()
{
	if ( !IsPlayer() && !IsADeadBody() && !IsDead() )
	{
		if ( m_pxAIAnimStateMachine == NULL )
		{
			m_pxAIAnimStateMachine = new AVP_Human_AIAnimStateMachine( *this );
		}
		m_pxAIAnimStateMachine->Initialise();
	}

	PARENT::PostLoadInitialise();
}

void AVP_ServerActor_Civilian::MakeAI()
{
	PARENT::MakeAI();
	if ( m_pxAIAnimStateMachine == NULL )
	{
		m_pxAIAnimStateMachine = new AVP_Human_AIAnimStateMachine( *this );
	}
}

void AVP_ServerActor_Civilian::Update()
{
	PARENT::Update();

	AVP_Brain_Actor_Civilian* pxCivBrain = ( AVP_Brain_Actor_Civilian* )GetActorBrain();

	if ( pxCivBrain && pxCivBrain->IsActive() && pxCivBrain->GetKnowledgeSystem() )
	{
		AVP_Knowledge_System_Actor* pxCivKS = pxCivBrain->GetKnowledgeSystem();

		if ( pxCivKS->GetBestAlertKnowledge().GetGuid() != ASURA_GUID_UNREGISTERED )
		{
			if ( !m_bAlertEventSent )
			{
				m_bAlertEventSent = true;
				SendMessagesForEvent( AVP_ENTITY_EVENT_CIVILIAN_ALERTED );
			}
		}
	}
}
