//////////////////////////////////////////////////////////////////////////////////////////
//
// FILE : Asura_ApplyForce_Messages.cpp
//
// AUTHORS : Emil Popovic - 22.04.2009
//
// Copyright (C) 2009 Rebellion, All Rights Reserved.
//
//////////////////////////////////////////////////////////////////////////////////////////


//////////////
// INCLUDES //
//////////////

// core
#include "Core/Asura.h"

// This file's header.
#include "Entity/PhysicalObject/Asura_ApplyForce_Messages.h"

// Engine independent.
#include "Blueprint/Asura_Blueprint.h"
#include "Blueprint/Asura_Blueprint_System.h"
#include "Blueprint/Asura_Blueprint_HashIDs.h"
#include "ChunkSystem/Asura_Chunk_Stream.h"
#include "Entity/Asura_Entity_Classification.h"
#include "Network/Asura_Guid.h"



void Asura_Msg_ApplyForce_Linear::SetDefaults()
{
	m_uVersion = CURRENT_VERSION;
	m_xOffsetFromCentreOfMass.Zero();
	m_uSourcePosObjectGuid = ASURA_GUID_UNREGISTERED;
	m_uExtraInfoBPHash = ASURA_HASH_ID_UNSET;
}

void Asura_Msg_ApplyForce_Linear::WriteToChunkStream(Asura_Chunk_Stream& xStream) const
{
	xStream << m_uVersion;
	xStream << m_xOffsetFromCentreOfMass.x;
	xStream << m_xOffsetFromCentreOfMass.y;
	xStream << m_xOffsetFromCentreOfMass.z;
	xStream << m_uSourcePosObjectGuid;
	xStream << m_uExtraInfoBPHash;
}



void Asura_Msg_ApplyForce_Radial::SetDefaults ()
{
	m_uVersion = CURRENT_VERSION;
	m_uSourcePosObjectGuid = ASURA_GUID_UNREGISTERED;
	m_uExtraInfoBPHash = ASURA_HASH_ID_UNSET;
}

void Asura_Msg_ApplyForce_Radial::WriteToChunkStream(Asura_Chunk_Stream& xStream) const
{
	xStream << m_uVersion;
	xStream << m_uSourcePosObjectGuid;
	xStream << m_uExtraInfoBPHash;
}


bool ApplyForceMsg_ImpulseData::FillFromBlueprint( const Asura_Hash_ID uExtraInfoBPHash )
{
	const Asura_Blueprint* pxBlueprint = Asura_Blueprint_System::GetBlueprintByHashID(uASURA_BLUEPRINT_TYPE_FORCES, uExtraInfoBPHash );
	if (pxBlueprint)
	{
		Asura_Value xValue;

		if (pxBlueprint->GetParameterValueByHashID( 0x2E590A59, xValue))	// "Damage.Type"
		{
			m_iDamageType = xValue.GetIntValue();
		}

		if (pxBlueprint->GetParameterValueByHashID( 0x9623B018, xValue))	// "Damage.Far"
		{
			m_fFarDamage = xValue.GetFloatValue();
		}

		if (pxBlueprint->GetParameterValueByHashID( 0x2E560347, xValue))	// "Damage.Near"
		{
			m_fNearDamage = xValue.GetFloatValue();
		}

		if (pxBlueprint->GetParameterValueByHashID( 0x87F0969E, xValue))	// "Impulse.Far"
		{
			m_fFarImpulse = xValue.GetFloatValue();
		}

		if (pxBlueprint->GetParameterValueByHashID( 0x7625ED81, xValue))	// "Impulse.Near"
		{
			m_fNearImpulse = xValue.GetFloatValue();
		}

		if (pxBlueprint->GetParameterValueByHashID( 0xD321C6E6, xValue))	// "Range.Far"
		{
			m_fFarRange = xValue.GetFloatValue();
		}

		if (pxBlueprint->GetParameterValueByHashID( 0x911AC639, xValue))	// "Range.Near"
		{
			m_fNearRange = xValue.GetFloatValue();
		}

		if (pxBlueprint->GetParameterValueByHashID( 0xE294E98E, xValue))	// "PlayPFX"
		{
			m_uPlayPFXHash = xValue.GetHashIDValue();
		}

		if (pxBlueprint->GetParameterValueByHashID( 0x912F1E5B, xValue))	// "PlaySound"
		{
			m_uPlaySoundHash = xValue.GetHashIDValue();
		}
		return true;
	}

	Asura_Assertf( false, ("Failed to extract data from FORCES blueprint %d", uExtraInfoBPHash ) );
	return false;	// Blueprint was not found.
}


float ApplyForceMsg_ImpulseData::CalculateImplusePower( float fLength )
{
	if( fLength<=m_fNearRange )
	{
		return m_fNearImpulse;
	}
	
	if( fLength>=m_fFarRange )
	{
		return m_fFarImpulse;
	}

	const float fStrength = (fLength-m_fNearRange) / (m_fFarRange-m_fNearRange);

	const float fImpulsePower = Asura_Maths::Lerp( m_fNearImpulse, m_fFarImpulse, fStrength );
	
	return fImpulsePower;
}