//------------------------------------------------------------------------------
// File   : AVP_ServerActor_Human.cpp
// Author : Gareth Thomas
// Date   : 3-Oct-2006
// Copyright (C) 2007 Rebellion, All Rights Reserved.
//------------------------------------------------------------------------------

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

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

// Asura files...
#include "Blueprint/Asura_Blueprint.h"
#include "Blueprint/Asura_Blueprint_System.h"

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

// AVP axon
#include "Core/BrainTypes/AVP_Brain_Actor_Marine.h"

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

Asura_Hashed_List<AVP_ServerActor_Android>	AVP_ServerActor_Android::s_xList;

//------------------------------------------------------------------------------
// AVP_ServerActor_Android:: Constructor
//------------------------------------------------------------------------------
AVP_ServerActor_Android::AVP_ServerActor_Android(const Asura_Guid uGUID)
: Asura_Entity_Server(uGUID)
, PARENT(uGUID)
, m_bDialogueHashIdsInitialised(false)
{
	// Update the data...
	Classification	= AVP_ENTITYCLASS_ANDROID;

	for (int i = 0; i < ANDROID_DLG_MAX_DIALOGUE_HASH_IDS; ++i)
	{
		m_uAndroidDialogueHashIDs[i] = ASURA_HASH_ID_UNSET;
	}

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

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

void AVP_ServerActor_Android::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 == CURRENT_CHUNK_VERSION )
		{
		}
		else
		{
			Asura_Assertf( false, ( "AVP_ServerActor_Android::ReadFromChunkStream - unhandled chunk version (%u)", uVersion ) );
		}
	}
}

void AVP_ServerActor_Android::WriteToChunkStream(Asura_Chunk_Stream& xStream) const
{
	xStream << CURRENT_CHUNK_VERSION;

	PARENT::WriteToChunkStream( xStream );

	// No data yet.
}

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

//------------------------------------------------------------------------------
// AVP_ServerActor_Android:: CreateAndReturn
//------------------------------------------------------------------------------
AVP_ServerActor_Android* AVP_ServerActor_Android::CreateAndReturn(Asura_Guid uGUID)
{
	AVP_ServerActor_Android* pxAndroid = new AVP_ServerActor_Android(uGUID);

	return pxAndroid;
}

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

	AVP_ServerEntity_Actor* pxKillingActor = AVP_ServerEntity_Actor::FindEntity(xDamage.GetFromGuid());

	if (pxKillingActor)
	{
		if ((pxKillingActor->GetClassification() == AVP_ENTITYCLASS_MARINE) && (!pxKillingActor->IsPlayer()))
		{
			EffectMorale(xDamage.GetFromGuid());
		}
	}
}

//-----------------------------------------------------------------
// AVP_ServerActor_Android :: InitialiseDialogueFromBlueprint
//-----------------------------------------------------------------
void AVP_ServerActor_Android::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 Android Actor With GUID Of %d", GetGuid() ) );

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

				if (pxBlueprint->GetParameterValueByHashID(0xe81e6559, xValue)) //0xe81e6559; //"ENTERING_AGGRESSIVE"
				{
					m_uAndroidDialogueHashIDs[ANDROID_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_uAndroidDialogueHashIDs[ANDROID_DLG_HUMAN_AGGRESSIVE_TO_ALERT] = xValue.GetHashIDValue();
				}
				else
				{
					Asura_Assert( false,  "Dialogue Paramater Not Found In Blueprint." );
				}

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

				if (pxBlueprint->GetParameterValueByHashID(0xff738942, xValue)) //0xff738942; //"ENTERING_COVER"
				{
					m_uAndroidDialogueHashIDs[ANDROID_DLG_HUMAN_ENTERING_COVER] = xValue.GetHashIDValue();
				}
				else
				{
					Asura_Assert( false,  "Dialogue Paramater Not Found In Blueprint." );
				}

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

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

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

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

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

				m_bDialogueHashIdsInitialised = true;
			}
		}
	}
}

//-----------------------------------------------------------------
// AVP_ServerActor_Android :: GetDialogueHashIDFromDialoguetype
//-----------------------------------------------------------------
Asura_Hash_ID AVP_ServerActor_Android::GetDialogueHashIDFromDialoguetype(DialogueType uDialogType)
{
	switch (uDialogType)
	{
		case AVP_DLG_HUMAN_ALERT_TO_PASSIVE:					return (m_uAndroidDialogueHashIDs[ANDROID_DLG_HUMAN_ALERT_TO_PASSIVE]);
		case AVP_DLG_HUMAN_IDLE_CHATTER:						return (m_uAndroidDialogueHashIDs[ANDROID_DLG_HUMAN_IDLE_CHATTER]);
		case AVP_DLG_HUMAN_ENTERING_COVER:						return (m_uAndroidDialogueHashIDs[ANDROID_DLG_HUMAN_ENTERING_COVER]);
		case AVP_DLG_HUMAN_PASSIVE_TO_ALERT:					return (m_uAndroidDialogueHashIDs[ANDROID_DLG_HUMAN_PASSIVE_TO_ALERT]);
		case AVP_DLG_HUMAN_AGGRESSIVE_TO_ALERT:					return (m_uAndroidDialogueHashIDs[ANDROID_DLG_HUMAN_AGGRESSIVE_TO_ALERT]);
		case AVP_DLG_HUMAN_ENTERING_AGGRESSIVE:					return (m_uAndroidDialogueHashIDs[ANDROID_DLG_HUMAN_ENTERING_AGGRESSIVE]);
		case AVP_DLG_HUMAN_ATTACKING:							return (m_uAndroidDialogueHashIDs[ANDROID_DLG_HUMAN_ATTACKING]);
		case AVP_DLG_HUMAN_RELOADING:							return (m_uAndroidDialogueHashIDs[ANDROID_DLG_HUMAN_RELOADING]);
		case AVP_DLG_HUMAN_KILLED_THREAT:						return (m_uAndroidDialogueHashIDs[ANDROID_DLG_HUMAN_KILLED_THREAT]);
		case AVP_DLG_HUMAN_SCARED_REACTION:						return (m_uAndroidDialogueHashIDs[ANDROID_DLG_HUMAN_SNEAK_ATTACK_RESPONSE]);
		default:												return ASURA_HASH_ID_UNSET;
	}
}

//-----------------------------------------------------------------
// AVP_ServerActor_Android :: EffectMorale
//-----------------------------------------------------------------
void AVP_ServerActor_Android::EffectMorale(Asura_Guid uGuidToEffect)
{
	AVP_ServerActor_Human* pxHuman = AVP_ServerActor_Human::FindEntity(uGuidToEffect);

	if (pxHuman)
	{
		if (pxHuman->GetInitialSquadGuid() != ASURA_GUID_UNREGISTERED)
		{
			AVP_ServerEntity_Squad_Marine* pxMarineSquad = AVP_ServerEntity_Squad_Marine::FindEntity(pxHuman->GetInitialSquadGuid());

			if (pxMarineSquad)
			{
				if (!pxMarineSquad->IsPlayersSquad())
				{
					if (pxHuman->GetMoraleHandler())
					{
						pxHuman->GetMoraleHandler()->EffectMorale(AVP_Human_MoraleHandler::AVP_MORALE_EFFECTOR_KILLED_ANDROID);
						pxMarineSquad->EffectSquadMorale(AVP_Human_MoraleHandler::AVP_MORALE_EFFECTOR_SQUAD_MEMBER_KILLED_ANDROID, pxHuman->GetGuid());
					}
				}
			}
		}
		else
		{
			if (!pxHuman->IsPlayer())
			{
				if (pxHuman->GetMoraleHandler())
				{
					pxHuman->GetMoraleHandler()->EffectMorale(AVP_Human_MoraleHandler::AVP_MORALE_EFFECTOR_KILLED_ANDROID);
				}
			}
		}
	}
}


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

	PARENT::PostLoadInitialise();
}

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

void AVP_ServerActor_Android::OnEntityActivate()
{
	PARENT::OnEntityActivate();

	AVP_Brain_Actor_Marine* pxMarineBrain = (AVP_Brain_Actor_Marine*)GetActorBrain();

	if (pxMarineBrain)
	{
		pxMarineBrain->RequestRegisterWithTeam();
	}
}

void AVP_ServerActor_Android::OnEntityDeactivate()
{
	PARENT::OnEntityDeactivate();

	AVP_Brain_Actor_Marine* pxMarineBrain = (AVP_Brain_Actor_Marine*)GetActorBrain();

	if (pxMarineBrain)
	{
		pxMarineBrain->RequestUnregisterWithTeam();
	}
}