
///////////////////////////////////////////////////////////////////////////////
//
// File   : AVP_Messages_Predator.cpp
// Author : Andy Tate
// Date   : 6-Oct-2006
//
// Copyright (C) 2006 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

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

#include "Core/Asura.h"

// This file's header...
#include "Entity/PhysicalObject/Actor/Vertebrates/Predator/AVP_Messages_Predator.h"

// Asura independent header-files...
#include "Core/Asura_BitPacker.h"
#include "Network/Asura_NetMsg.h"

// Asura platform header-files...

// Game independent header-files...
#include "Actor/Vertebrates/AVP_Vertebrate_Focus.h"
#include "Actor/Vertebrates/AVP_Vertebrate_InputHandler.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_MeleeCounter_System.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_Recon.h"
#include "Entity/AVP_Entity_Classification.h"
#include "Entity/AVP_Messages.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Predator/AVP_ClientActor_Predator.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Predator/AVP_ServerActor_Predator.h"
#include "Inventory/AVP_Inventory_System.h"
#include "Inventory/Items/AVP_InventoryItem_Weapon.h"

#include "Core/BrainTypes/AVP_Brain_Actor_Predator.h"
#include "Knowledge/AVP_Knowledge_System_Predator.h"
#include "Knowledge/AVP_Knowledge_System_Actor.h"

// Game platform header-files...

// Tools header-files...


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


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


////////////////////////////////////////////////////////////////////////////////
// Private functions...
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Protected functions...
////////////////////////////////////////////////////////////////////////////////


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

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Message_PredatorClientUpdate::FillPredator
// Author       : Andy Tate
// Date         : 6-Oct-2006
////////////////////////////////////////////////////////////////////////////////

void AVP_Message_PredatorClientUpdate::FillPredator( const AVP_ServerActor_Predator& xPredator )
{
	// Fill-in the base-class...
    FillVertebrate(xPredator);

	//AVP_Brain_Actor_Predator* pxPredBrain = (AVP_Brain_Actor_Predator*)xPredator.GetActorBrain();

//	if ((pxPredBrain) && (pxPredBrain->GetKnowledgeSystem()))
	{
		//FIXME!!
		m_uAlertLevel = AVP_Knowledge_System_Actor::AGGRESSIVE_ALERTNESS;//pxPredBrain->GetKnowledgeSystem()->GetAlertLevel();
	}


	// Fill-in our own data...
	m_uDiscGuid					= xPredator.GetDiscGuid();
	m_uHeldProjectileGuid		= xPredator.GetHeldProjectileGuid();
	m_uTargetGuid				= xPredator.GetTargetGuid(); 

	m_bCrouching = xPredator.IsCrouching();
	m_bInsidePounceRange = static_cast<const AVP_Predator_MeleeCounter_System* >( xPredator.GetMeleeSystem() )->InsidePounceRange();
	m_bLockOn = xPredator.IsLockOn(); 
}

/// End of function 'AVP_Message_PredatorClientUpdate::FillPredator'. ///


#ifdef ASURA_SUPPORT_NETMSG_SYSTEM
void AVP_Message_PredatorClientUpdate::RegisterFields(u_short usMsgID, u_short usEntityClassification)
{
	Asura_Assert(usMsgID == ASURA_MSG_CLIENTUPDATE, "invalid msg ID");
	Asura_Assert(!Asura_NetMsg::FindNetMsgObject(usMsgID, usEntityClassification), "already exists");
	Asura_Assert(usEntityClassification == AVP_ENTITYCLASS_PREDATOR, "Unexpected entity classification.");
	
	u_char ucNumFields = GetNumFields();

	Asura_NetMsg* pxNetMsg = new Asura_NetMsg(usMsgID, usEntityClassification, ucNumFields, sizeof(AVP_Message_PredatorClientUpdate));
	RegisterFields(pxNetMsg);
	pxNetMsg->EndRegistration();
}


void AVP_Message_PredatorClientUpdate::RegisterFields(Asura_NetMsg* pxNetMsg)
{
	const AVP_Message_PredatorClientUpdate xDummy;
	AVP_Message_Vertebrate_ClientUpdate::RegisterFields(pxNetMsg);

	Asura_NetMsg_RegisterField(pxNetMsg, xDummy, Asura_FieldType_Guid, m_uDiscGuid, 1, Asura_Threshold_AnyChange, 0.0f);
	Asura_NetMsg_RegisterField(pxNetMsg, xDummy, Asura_FieldType_Guid, m_uHeldProjectileGuid, 1, Asura_Threshold_AnyChange, 0.0f);
	Asura_NetMsg_RegisterField(pxNetMsg, xDummy, Asura_FieldType_Guid, m_uTargetGuid, 1, Asura_Threshold_AnyChange, 0.0f);
	Asura_NetMsg_RegisterField(pxNetMsg, xDummy, Asura_FieldType_uchar, m_bCrouching, 1, Asura_Threshold_AnyChange, 0.0f);
	Asura_NetMsg_RegisterField(pxNetMsg, xDummy, Asura_FieldType_uchar, m_bLockOn, 1, Asura_Threshold_AnyChange, 0.0f);
	Asura_NetMsg_RegisterIntFieldBits(pxNetMsg, xDummy, Asura_FieldType_uint_bits, 2, m_uAlertLevel, 1, Asura_Threshold_AnyChange);
}
#endif//#ifdef ASURA_SUPPORT_NETMSG_SYSTEM

// Constructor

AVP_Message_PredatorPlayerCommands::AVP_Message_PredatorPlayerCommands( const AVP_ClientActor_Predator& xPredator )
{
	FillPredator( xPredator ); 
}

AVP_Message_PredatorPlayerCommands::AVP_Message_PredatorPlayerCommands( Asura_BitUnpacker& xUnpacker )
{
	Unpack( xUnpacker ); 
}

void AVP_Message_PredatorPlayerCommands::FillPredator( const AVP_ClientActor_Predator& xPred )
{
	PARENT::FillVertebrate( xPred );
	
	m_bCrouching = xPred.IsCrouching();

	m_bRequestingChargeUp = false;
	// Only request charge attack with the melee weapon (i.e. wristblades).
	const AVP_Inventory_System* pxInventory = xPred.GetInventorySystem();
	if (pxInventory)
	{
		const AVP_InventoryItem_Weapon* pxWeapon = static_cast<const AVP_InventoryItem_Weapon*>(pxInventory->GetCurrentItem(uAVP_INVENTORY_GROUPHASH_WEAPON));
		if (pxWeapon && (pxWeapon->GetItemType() == AVP_INVENTORYITEMTYPE_WEAPON_MELEE))
		{
			const AVP_Actor_InputHandler* pxInputHandler = xPred.GetInputHandler();
			if (pxInputHandler)
			{
				// Only send the additional request if we're not in focus mode.
				m_bRequestingChargeUp = (pxInputHandler->GetControlMapValue(AVP_Vertebrate_InputHandler::PRIMARY_ATTACK_HELD) >= 0.5f) && (!xPred.GetFocus() || !xPred.GetFocus()->GetActive() || (xPred.GetFocus()->GetMeleeTarget() == ASURA_GUID_UNREGISTERED));
			}
		}
	}

	m_bDistract = false;

	// Predator laser lock on and target
	const AVP_Vertebrate_Focus* pxPredFocus = xPred.GetFocus(); 
	if (pxPredFocus)
	{
		m_bLockOn = pxPredFocus->HasValidLockOnTarget(); 
		m_uTargetGuid = pxPredFocus->GetLockOnTarget();
	}
	else
	{
		Asura_Assert( false, "Unexpected predator player without focus handler" ); 
		m_bLockOn = false; 
		m_uTargetGuid = ASURA_GUID_UNREGISTERED; 
	}
}

void AVP_Message_PredatorPlayerCommands::Pack( Asura_BitPacker &xPacker ) const
{
	PARENT::Pack( xPacker ); 

	xPacker.PackBool( m_bCrouching ); 
	xPacker.PackBool( m_bRequestingChargeUp ); 
	xPacker.PackBool( m_bDistract ); 
	xPacker.PackBool( m_bLockOn ); 
	if ( m_bLockOn )
	{
		xPacker.Pack( m_uTargetGuid, sizeof(Asura_Guid) * 8 ); 
	}
}

void AVP_Message_PredatorPlayerCommands::Unpack( Asura_BitUnpacker &xUnpacker )
{
	PARENT::Unpack( xUnpacker ); 

	m_bCrouching = xUnpacker.UnpackBool(); 
	m_bRequestingChargeUp = xUnpacker.UnpackBool(); 
	m_bDistract = xUnpacker.UnpackBool(); 
	m_bLockOn = xUnpacker.UnpackBool(); 
	if ( m_bLockOn )
	{
		m_uTargetGuid = xUnpacker.Unpack( sizeof(Asura_Guid) * 8 ); 
	}
}

////////////////////////////////////////////////////////////////////////////////
// Class     : AVP_PredatorBehaviourData
////////////////////////////////////////////////////////////////////////////////

void AVP_PredatorBehaviourData::SetParamsFromBehaviour()
{
	// nothing yet
}

void AVP_PredatorBehaviourData::ReadFromChunkStream( Asura_Chunk_Stream& xStream )
{
	u_int uVersion;
	xStream >> uVersion;

	if ( uVersion == 1 )
	{
		xStream >> m_iBehaviour;
		SetParamsFromBehaviour();
	}
	else
	{
		Asura_Assertf( false, ( "AVP_PredatorBehaviourData::ReadFromChunkStream - unhandled chunk version (%u)", uVersion ) );
	}
}
void AVP_PredatorBehaviourData::WriteToChunkStream( Asura_Chunk_Stream& xStream ) const
{
	xStream << uCURRENT_CHUNK_VERSION;
	xStream << m_iBehaviour;
}

#ifdef ASURA_TOOLS
const char* AVP_PredatorBehaviourData::s_apszBehaviourStrings[ NUM_BEHAVIOURS ] =
{
	"Stalk",
	"Melee"
};

#endif