///////////////////////////////////////////////////////////////////////////////
//
// File   : AVP_ServerActor_Human.h
// Author : Andy Tate
// Date   : 3-Oct-2006
//
// Copyright (C) 2006 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
	#pragma once
#endif   // ifdef ASURA_USE_PRAGMA_ONCE
#ifndef __AVP_SERVERACTOR_HUMAN_H__
#define __AVP_SERVERACTOR_HUMAN_H__

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

#include "Core/Asura_HashedList.h"

#include "Actor/Vertebrates/Human/AVP_Human_AIAnimStateMachine.h"
#include "Actor/Vertebrates/Human/AVP_Human_Description.h"
#include "Entity/AVP_Entity_EventIDs.h"
#include "Entity/Locations/Objective/Marine/AVP_ServerEntity_Objective_Marine.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/AVP_ServerActor_Vertebrate.h"
#include "GUIMenu/Asura_GUIMenu_Element_Text.h"


////////////////////////////////////////////////////////////////////////////////
// Forward class declarations...
////////////////////////////////////////////////////////////////////////////////

class AVP_Message_HumanPlayerCommands;
class AVP_Human_MoraleHandler;
class AVP_InventoryItem_Torch;

////////////////////////////////////////////////////////////////////////////////
// Class declaration...
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_ServerActor_Human
// Author       : Andy Tate
// Date         : 3-Oct-2006
//
// Description  : This class handles the operation of the Human actor, the
//				  Human can be either player controlled or AI controlled.
////////////////////////////////////////////////////////////////////////////////
class AVP_ServerActor_Human : public AVP_ServerActor_Vertebrate
{
#if defined(ASURA_TOOLS)
	// Friend classes...
	friend class ToolsAVP_Entity_Human;
#endif//defined(ASURA_TOOLS)

public:

	enum { CURRENT_CLIENTCREATE_VERSION = 2 };

	enum DialogueType
	{
		AVP_DLG_HUMAN_NO_TYPE,
		
		// Passive State Dialogue
		AVP_DLG_HUMAN_ALERT_TO_PASSIVE,
		AVP_DLG_HUMAN_ALERT_TO_PASSIVE_FROM_AGGRESSIVE,
		AVP_DLG_HUMAN_IDLE_CHATTER,
		AVP_DLG_HUMAN_ENTERING_COVER,
		AVP_DLG_HUMAN_PASSIVE_TO_ALERT,
		AVP_DLG_HUMAN_AGGRESSIVE_TO_ALERT,
		AVP_DLG_HUMAN_ENTERING_AGGRESSIVE,
		AVP_DLG_HUMAN_ATTACKING,
		AVP_DLG_HUMAN_RELOADING,
		AVP_DLG_HUMAN_FLEEING,
		AVP_DLG_HUMAN_TAUNTING,
		AVP_DLG_HUMAN_KILLED_THREAT,
		AVP_DLG_HUMAN_KILLED_THREAT_RESPONSE,
		AVP_DLG_HUMAN_TEAMMATE_KILLED,
		AVP_DLG_HUMAN_SCARED_REACTION,
		AVP_DLG_HUMAN_FALLING_BACK,
		AVP_DLG_HUMAN_FRIENDLY_FIRE,
		AVP_DLG_HUMAN_HURRY_UP,
		AVP_DLG_HUMAN_KEEP_FORMATION,
		AVP_DLG_HUMAN_PROVIDING_COEVRING_FIRE,
	};

	enum FormationRole
	{
		FORMATION_ROLE_NONE,
		FORMATION_ROLE_SUPPORT,
		FORMATION_ROLE_ASSAULT,
		FORMATION_ROLE_FALLBACK,
		FORMATION_ROLE_STANDGROUND,
		FORMATION_ROLE_SMARTGUN,
		FORMATION_ROLE_TRAVELLING,
		MAX_FORMATION_ROLES,
	};

	enum ExpressionType
	{
		FACE_EXPRESSION_PASSIVE,
		FACE_EXPRESSION_ACTIVE,
		FACE_EXPRESSION_AGGRESSIVE,
		FACE_EXPRESSION_SCARED,
		MAX_FACE_EXPRESSION,
	};

	// Overridden chunk-handling functions...
	virtual	void ReadFromChunkStream(Asura_Chunk_Stream& xStream);
	virtual	void WriteToChunkStream(Asura_Chunk_Stream& xStream) const;

	virtual void WriteToClientCreateStream(Asura_Chunk_Memory_Stream& xStream) const;

	// Overridden functions...
	virtual	void Update(void);
	virtual	bool HandleMessage(const Asura_Message* pxMessage);
	virtual void MakePlayer(Asura_Guid uPlayerGuid);
	virtual void MakeAI(void);
	virtual void PostLoadInitialise(void);
	virtual	void TakeDamageExtended(const AVP_EntityDamage_RequestVictim& xDamage, const bool bForceFatal, const bool bSendMessageToClient=true );

	virtual void AddPermenantlyActiveItems(AVP_Inventory_Group* pxGroup);

	virtual Axon_Brain* CreateBrain();

	// Public Dialogue Functions
	void PlayDialogue(DialogueType uDialogType);

	// Legacy chunk handling, to be removed as soon as possible...
	virtual	bool IsFilledFromChunkBuffer(void) const	{return false;}

	// Accessor functions...
	void		SetUseTestBehaviour(u_int bVal)				{m_bUseTestBehaviour = bVal;}
	u_int		GetUseTestBehaviour(void)					{return m_bUseTestBehaviour;}

	void		SetCrouching( bool bSet );
	bool		IsCrouching() const			{ return m_bCrouching; }

	void		SetAiming( bool bSet );
	bool		IsAiming() const		{ return m_bAiming; }

	bool		IsIdle() const { return ( !IsPlayer() && GetAIAnimStateMachine()->IsIdle() && !IsAiming() && !IsCrouching() ); }

	void									SetCoverType(AVP_Human_AIAnimStateMachine::CoverType eVal)	{m_eCoverType = eVal;}
	AVP_Human_AIAnimStateMachine::CoverType	GetCoverType(void) const {return static_cast< AVP_Human_AIAnimStateMachine::CoverType >( m_eCoverType );}

	void		SetGuardzoneGuid(Asura_Guid uGuid)		{m_uGuardZoneGuid = uGuid;}
	Asura_Guid	GetGuardZoneGuid(void)					{return m_uGuardZoneGuid;}
	AVP_Human_MoraleHandler*	GetMoraleHandler(void)	{return m_pxMoraleHandler;}	
	AVP_InventoryItem_Torch*	GetTorchItem(void) const;

	void		SetActionGamesceneGuid( Asura_Guid uGuid )	{ m_uActionGamesceneGuid = uGuid; }
	Asura_Guid	GetActionGamesceneGuid( void )				{ return m_uActionGamesceneGuid; }

	virtual bool IsHuman() const { return true; }
	// Objective Functions
	Objective* 	GetCurrentObjective( void )														{ return m_pxCurrentObjective; }
	Asura_Guid 	GetCurrentObjectiveGuid( void )													{ return m_pxCurrentObjective->uObjectiveGuid; }
	u_int 		GetCurrentObjectiveState( void )												{ return m_pxCurrentObjective->uObjectiveState; }
	
	u_int 		GetCurrentObjectiveType( void )													{ return m_uCurrentObjectiveType; }
	u_int 		GetCurrentObjectiveThreatAction( void )											{ return m_uCurrentObjectiveThreatAction; }
	u_int		GetCurrentObjectiveMovementMode( void )											{ return m_uCurrentObjectiveMovementMode; }


	Asura_Hash_ID GetFacialAnimation( ExpressionType eType, u_int iIndex);

	void		RequestAction( Asura_Guid uIgnoreActionGuid = ASURA_GUID_UNREGISTERED );
	void		GetNumOptionalAndRequiredActionGuids( u_int* uNumRequired, u_int* uNumOptional, bool bConsiderActiveState = true);
	void		GetOptionalAndRequiredGuids( Asura_Guid* pxRequired, Asura_Guid* pxOptional );
	Asura_Guid	GetActionGuidToAssign(Asura_Guid* pxActions, u_int uNumActions, Asura_Guid uIgnoreActionGuid, bool bIsRequiredAction );
	void		SendPerformActionMessage( Asura_Guid uActionGuid );
	void		AssignAction( Asura_Guid uGuidToAssign, bool bIsRequiredAction, u_int uNumActions );
	bool		BuildRandomisedOptionalArray( u_int uNumOptional, Asura_Guid* pxOptionalActions, Asura_Guid* pxRandomOptionals );
	void		ProcessCurrentObjective( void );

	void		PlayerMeleedFriendly( Asura_Guid uGuid );

	u_int		GetFormationRole( void )						{ return m_uFormationRole; }
	void		SetFormationRole( u_int uFormationRole )		{ m_uFormationRole = uFormationRole; }

	Asura_GUIMenu_Element_Text&       GetNameText() { return m_xNameText;}
	const Asura_GUIMenu_Element_Text& GetNameText() const { return m_xNameText;}

	Asura_Guid    GetHackingToolGuid() const { return m_uHackingToolGuid; }
	void          SetHackingToolGuid(Asura_Guid uGuid) { m_uHackingToolGuid = uGuid; }

	virtual bool GetHasCreateMessage() const { return !IsDead() || IsADeadBody(); }
	virtual void InitialiseDialogueFromBlueprint(Asura_Hash_ID uBlueprintHashID) {}
	virtual Asura_Hash_ID GetDialogueHashID(u_int uIndex)	{return ASURA_HASH_ID_UNSET;}

	virtual u_int	GetElementFromBoneID(int iBoneID) const { return AVP_Human_Description::GetElementFromBoneID(iBoneID); }
	virtual int		GetAnyBoneIDFromElement(u_int uElement) const { return AVP_Human_Description::GetAnyBoneIDFromElement(uElement); } // Since bones->elements is a many->one mapping, this function will return one of the bones associated with the given element, but not necessarily the only one.

	virtual void    OnPickup(AVP_ServerEntity_Pickup* pxPickup, float fQuantity, float fSecondaryQuantity, bool bSetAsCurrent = true);

	// Head ripping static messages
	void			OnHeadRipped() const;

	Asura_Guid GetGuidToLastDamageUs() { return m_uLastGuidToDamageUs; }

	u_int GetGS2MoveSpeed()		{ return m_uGS2MoveSpeed; }

	bool  GetHasHackingTool () const { return m_bHasHackingTool; }

	bool	GetHasDamagedLegs() const { return m_bLegsDamaged; }
	bool	GetStartsInjured() const { return m_bStartAsInjured; }

	// functions for the player's server actor for picking up/dropping an actor up from the ground
	void DropBuddy();
	void PickUpBuddy( const Asura_Guid uBuddyGuid );

	// functions for when the player picks up/drops this actor
	bool IsPickupAble() const { return m_bPickUpAble; }
	bool IsDroppable() const { return m_bDroppable; }

	Asura_Guid GetPickedUpBuddyGuid() const { return m_uPickedUpBuddyGuid; }
	bool IsCarryingBudddy() const { return m_uPickedUpBuddyGuid != ASURA_GUID_UNREGISTERED; }
	bool GetHasMotionTracker() const { return m_bHasMotionTracker; }

#ifdef ASURA_TOOLS
	virtual bool			SupportsCustomEvents() const { return true; }
	virtual int			    GetNumCustomEvents() const { return NUM_MESSAGE_BLOCKS; }
	virtual unsigned short* GetCustomEvent(int iIndex);
	virtual void			GetCustomEventName(int iEventIndex, Asura_String& xEventName);
	virtual void			ApplyChangesForTemplateInstance( Tools_EntityTemplateInstance* pxInstance );
#endif

	// Static list accessors...
	static AVP_ServerActor_Human*							FindEntity(const Asura_Guid uGuid)	{return s_xList.FindEntity(uGuid);}
	static const Asura_Hashed_List<AVP_ServerActor_Human>*	GetList(void)						{return &s_xList;}

	void	GetFacialAnimationValuesFromBlueprint( const Asura_Blueprint& xBlueprint );
	u_int	GetNumFaceAnimsForExpression( ExpressionType uFaceType );

	void SendOnAlertMessage() { SendMessagesForEvent( AVP_ENTITY_EVENT_MARINE_ALERTED ); }
	void SendOnThreatMessage() { SendMessagesForEvent( AVP_ENTITY_EVENT_MARINE_THREAT_SPOTTED ); }

	virtual bool ExplodesOnFatalPlasmaDamage() const { return true ;}

protected:
	virtual void UpdateMovement();

	void CheckForAlliesinLOF();

	// force alian legs loss if any limb is damaged.
	virtual float CalculateAndUpdateLocationSpecificDamage(const AVP_EntityDamage_RequestVictim& xDamage, u_int& uDestroyedSkinElements, u_int& uGibbedSkinElements, bool bForceFatal);

	enum
	{
		MESSAGE_BLOCK_HEAD_RIPPED,
		NUM_MESSAGE_BLOCKS
	};

	// Protected variables...
	u_int						m_uType;
	u_int						m_bUseTestBehaviour;
	Asura_Guid					m_uGuardZoneGuid;
	Asura_Guid					m_uActionGamesceneGuid;
	bool						m_bHasObjective;
	Objective*					m_pxCurrentObjective;
	u_int						m_uFormationRole;
	u_int						m_uNumTimesMeleedFriendly;
	float						m_fFriendlyMeleeTimer;
	bool						m_bFriendlyMeleeTriggered;
	Asura_Guid					m_uLastMeleedFriendlyGuid;
	float						m_fLastFriendlyMeleeTimer;
	bool						m_fLastFriendlyMeleeTrigger;
	Asura_Hash_ID               m_uHackingToolGuid;

	u_int						m_uCurrentObjectiveType;
	u_int						m_uCurrentObjectiveThreatAction;
	u_int						m_uCurrentObjectiveMovementMode;
	unsigned short			    m_usHeadRippedMessageBlock;

	Asura_Guid					m_uLastGuidToDamageUs;

	u_int						m_uGS2MoveSpeed;

	Asura_Hash_ID				m_uHackingToolBPHash;
	bool                        m_bHasHackingTool;
	float						m_fLOSUpdateTimer;

	Asura_Guid					m_uPickedUpBuddyGuid;

	union
	{
		u_int		m_uFlags;
		struct
		{
			u_int	m_bCrouching	    : 1,
					m_bAiming		    : 1,
					m_eCoverType	    : 2,
					m_bLegsDamaged	    : 1,
					m_bStartAsInjured   : 1,
					m_bPickUpAble	    : 1,
					m_bDroppable	    : 1,
					m_bPickedUp		    : 1,
					m_bHasMotionTracker : 1,
									    : 0;
		};
	};

	AVP_Human_MoraleHandler*	m_pxMoraleHandler;

	Asura_Hash_ID m_uFaceExpression_Passive01;
	Asura_Hash_ID m_uFaceExpression_Passive02;
	Asura_Hash_ID m_uFaceExpression_Passive03;
	Asura_Hash_ID m_uFaceExpression_Passive04;

	Asura_Hash_ID m_uFaceExpression_Active01;
	Asura_Hash_ID m_uFaceExpression_Active02;
	Asura_Hash_ID m_uFaceExpression_Active03;
	Asura_Hash_ID m_uFaceExpression_Active04;

	Asura_Hash_ID m_uFaceExpression_Aggressive01;
	Asura_Hash_ID m_uFaceExpression_Aggressive02;
	Asura_Hash_ID m_uFaceExpression_Aggressive03;
	Asura_Hash_ID m_uFaceExpression_Aggressive04;

	Asura_Hash_ID m_uFaceExpression_Scared01;
	Asura_Hash_ID m_uFaceExpression_Scared02;
	Asura_Hash_ID m_uFaceExpression_Scared03;
	Asura_Hash_ID m_uFaceExpression_Scared04;

	Asura_GUIMenu_Element_Text  m_xNameText;

	// Protected functions...
	AVP_ServerActor_Human(const Asura_Guid uGUID);
	virtual ~AVP_ServerActor_Human(void);

	void	ProcessHumanPlayerCommands( const AVP_Message_HumanPlayerCommands* pxData, float fMessageSentTime );

	// Protected Virtual Overridden Functions...
	virtual	void	MakeClientUpdateMessage(void);
	virtual void	InitialiseFromBlueprint(const Asura_Blueprint& xBlueprint);
	virtual bool	InitialiseInventory(void);

	// Protected Dialogue Functions
	virtual Asura_Hash_ID GetDialogueHashIDFromDialoguetype(DialogueType eDialogType) {return ASURA_HASH_ID_UNSET;}

	// Overridden event functions...
	virtual void OnApplyDamage(const AVP_EntityDamage_ApplyToEntity& xDamage);
	virtual void OnDeath(const AVP_EntityDamage_ApplyToEntity& xDamage);

	virtual bool GetIsInLowStance() const { return IsCrouching(); }

	virtual const Asura_Blueprint* GetCurrentFlinchBlueprint() const;

	virtual float GetHeadPositionYOffset() const { return -2.0f; }
	virtual float GetChestPositionYOffset() const { return -1.5f; }

	virtual Asura_Hash_ID GetMovesBlueprintType() const;
	virtual void		  HandleInteractions( );

	void ProcessFreindlyMelee();

	void OnDroppedByPlayer();
	void OnPickedUpByPlayer();

private:
	// Private typedefs...
	typedef AVP_ServerActor_Vertebrate PARENT;

	// Static Private variables...
	static	Asura_Hashed_List<AVP_ServerActor_Human>	s_xList;

	// Private functions...
	AVP_ServerActor_Human(void);
	AVP_ServerActor_Human(const AVP_ServerActor_Human& xOther);
	AVP_ServerActor_Human& operator=(const AVP_ServerActor_Human& xOther);

	// Interaction functions
	void PlugBattery();
	void RemoveBattery();
	void PlugHackingTool();
	void RemoveHackingTool();
	void HideHackingTool();
	void SetBatteryAsWeapon();

	static const u_int uCURRENT_CHUNK_VERSION = 18;
};

#endif   // ifndef __AVP_SERVERACTOR_HUMAN_H__

/// End of file. ///
