//////////////////////////////////////////////////////////////////////////////
//
// Asura_ServerNode_GS2Spline.cpp
//
// Copyright (C) 2008 Rebellion. All Rights Reserved.
//
//////////////////////////////////////////////////////////////////////////////

// I N C L U D E S ///////////////////////////////////////////////////////////

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

#ifdef ASURA_USE_AXON

// header
#include "Entity/Locations/Spline/GamesceneSpline/Asura_ServerNode_GS2Spline.h"

// asura
#include "Core/Asura_Graph.h"
#include "Entity/Asura_Entity_Classification.h"
#include "Entity/Locations/OrientedNode/GamesceneNode/Asura_ServerNode_GS2Node.h"
#include "Network/Asura_Message.h"
#ifndef ASURA_NO_DEBUG_OUTPUT
#include "Debugging/Asura_DebugLineRender.h"
#include "Rendering/Asura_Font_System.h"
#endif
#ifdef ASURA_USE_STREAMING
#include "Streaming/Asura_Streaming_System.h"
#endif

// axon
#include "Behaviour/Axon_BehaviourParams.h"
#include "Behaviour/BehaviourTypes/Axon_Behaviour_Types.h"
#ifdef ASURA_TOOLS
#include "Behaviour/BehaviourTypes/Axon_Behaviour_GS2Actor.h"
#endif

//////////////////////////////////////////////////////////////////////////////
//
// Asura_ServerNode_GS2Spline
//
//////////////////////////////////////////////////////////////////////////////

Asura_Hashed_List< Asura_ServerNode_GS2Spline > Asura_ServerNode_GS2Spline::s_xList;

Asura_ServerNode_GS2Spline::Asura_ServerNode_GS2Spline( Asura_Guid uGuid )
: PARENT( uGuid )
, m_uFlags( 0 )
, m_pxSpeedOverTimeGraph( NULL )
, m_fTotalTimeRequired( 0.0f )
, m_fDurationOverride( 0.0f )
, m_iBehaviourSet( AXON_BEHAVIOUR_TYPE_UNSET )
, m_pxBehaviourParams( NULL )
, m_xOccupierGuids()
{
	Classification = AsuraEntityClass_GS2Spline;

	Asura_ResourcePushType(ASURA_RESOURCE_GAMESCENE);
	m_pxSpeedOverTimeGraph = new Asura_Graph<float>(32, 1.75f, 1.75f);
	m_pxSpeedOverTimeGraph->SetClampingValues(true, false, 0.0f, Asura_Maths::LargeFloat);
	Asura_ResourcePopType();

	m_bTestForCollisions = true;

	s_xList.AddToList( this );
}

Asura_ServerNode_GS2Spline::~Asura_ServerNode_GS2Spline()
{
	Asura_ResourcePushType(ASURA_RESOURCE_GAMESCENE);
	delete m_pxSpeedOverTimeGraph;
	m_pxSpeedOverTimeGraph = NULL;
	Asura_ResourcePopType();

	delete m_pxBehaviourParams;
	m_pxBehaviourParams = NULL;

	m_xOccupierGuids.Clear();

	s_xList.RemoveFromList( this );
}

void Asura_ServerNode_GS2Spline::ReadFromChunkStream( Asura_Chunk_Stream& xStream )
{
	int iVersion;
	xStream >> iVersion;

	PARENT::ReadFromChunkStream( xStream );

	if ( iVersion == CURRENT_CHUNK_VERSION )
	{
		Asura_ReadFromStream_Bitfield_Wrapper< u_int > xFlagsBitfield( m_uFlags );
		xStream >> xFlagsBitfield;

		delete m_pxSpeedOverTimeGraph;
		m_pxSpeedOverTimeGraph = new Asura_Graph< float >( xStream );
#ifdef ASURA_TOOLS
		if ( m_bDistanceVsTimeGraph )
		{
			m_pxSpeedOverTimeGraph->SetClampingValues( true, true, 0.0f, 1.0f );
		}
		else
		{
			m_pxSpeedOverTimeGraph->SetClampingValues( true, false, 0.0f, Asura_Maths::LargeFloat );
		}
#endif //ASURA_TOOLS
		xStream >> m_fTotalTimeRequired;
		xStream >> m_fDurationOverride;

		u_int uNumOccupiers;
		xStream >> uNumOccupiers;
		for ( u_int u = 0; u < uNumOccupiers; ++u )
		{
			Asura_Guid uOccupierGuid;
			xStream >> uOccupierGuid;
#if defined( ASURA_USE_STREAMING ) && !defined( ASURA_TOOLS )
			uOccupierGuid = Asura_Streaming_System::MakeCurrentMasterZoneGuid( uOccupierGuid );
#endif
			m_xOccupierGuids.Push_Back( uOccupierGuid );
		}

		xStream >> m_iBehaviourSet;
		Axon_BehaviourParams::CreateTreeFromChunkStream( xStream, m_pxBehaviourParams );
	}
	else if ( iVersion == 0 )
	{
		Asura_ReadFromStream_Bitfield_Wrapper< u_int > xFlagsBitfield( m_uFlags );
		xStream >> xFlagsBitfield;

		delete m_pxSpeedOverTimeGraph;
		m_pxSpeedOverTimeGraph = new Asura_Graph< float >( xStream );
#ifdef ASURA_TOOLS
		if ( m_bDistanceVsTimeGraph )
		{
			m_pxSpeedOverTimeGraph->SetClampingValues( true, true, 0.0f, 1.0f );
		}
		else
		{
			m_pxSpeedOverTimeGraph->SetClampingValues( true, false, 0.0f, Asura_Maths::LargeFloat );
		}
#endif //ASURA_TOOLS
		xStream >> m_fTotalTimeRequired;
		xStream >> m_fDurationOverride;

		// Chuck away the distance time graph entries.
		u_int uNumDistanceTimeGraphEntries;
		xStream >> uNumDistanceTimeGraphEntries;
		Asura_DistanceTime_GraphPoint xGraphPoint;
		for ( u_int i = 0; i < uNumDistanceTimeGraphEntries; ++i )
		{
			xStream >> xGraphPoint.m_fDistance;
			xStream >> xGraphPoint.m_fCumulativeTime;
		}

		u_int uNumOccupiers;
		xStream >> uNumOccupiers;
		for ( u_int u = 0; u < uNumOccupiers; ++u )
		{
			Asura_Guid uOccupierGuid;
			xStream >> uOccupierGuid;
#if defined( ASURA_USE_STREAMING ) && !defined( ASURA_TOOLS )
			uOccupierGuid = Asura_Streaming_System::MakeCurrentMasterZoneGuid( uOccupierGuid );
#endif
			m_xOccupierGuids.Push_Back( uOccupierGuid );
		}

		xStream >> m_iBehaviourSet;
		Axon_BehaviourParams::CreateTreeFromChunkStream( xStream, m_pxBehaviourParams );
	}
	else
	{
		Asura_Assertf( false, ( "Asura_ServerNode_GS2Spline::ReadFromChunkStream - unhandled chunk version (%d)", iVersion ) );
	}
}

void Asura_ServerNode_GS2Spline::WriteToChunkStream( Asura_Chunk_Stream& xStream ) const
{
	// DON'T FORGET TO UPDATE ApplyChangesForTemplateInstance IF YOU CHANGE STUFF.

	xStream << CURRENT_CHUNK_VERSION;

	PARENT::WriteToChunkStream( xStream );

	bool bSamplesOnly = true;
	bool bIntegrate = false;
#ifdef ASURA_TOOLS
	bSamplesOnly = Tools_Level_Export::IsExport();
	bIntegrate = Tools_Level_Export::IsExport() && !m_bDistanceVsTimeGraph;
	if ( bIntegrate )
	{
		m_bIntegratedGraph = true;
	}
#endif

	Asura_WriteToStream_Bitfield_Wrapper< u_int > xFlagsBitfield( m_uFlags );
	xFlagsBitfield.Add( m_bUsePointOrientation,		1 );
	xFlagsBitfield.Add( m_bIgnoreCollisions,		1 );
	xFlagsBitfield.Add( m_bUNUSED_1,				1 );
	xFlagsBitfield.Add( m_bDistanceVsTimeGraph,		1 );
	xFlagsBitfield.Add( m_bOverrideDuration,		1 );
	xFlagsBitfield.Add( m_bTestForCollisions,		1 );
	xFlagsBitfield.Add( m_bFollowSurface,			1 );
	xFlagsBitfield.Add( m_bFollowSurfaceTools,		1 );
	xFlagsBitfield.Add( m_bIntegratedGraph,			1 );
	xStream << xFlagsBitfield;

#ifdef ASURA_TOOLS
	m_bIntegratedGraph = false;
#endif

	m_pxSpeedOverTimeGraph->WriteToChunkStream( xStream, bSamplesOnly, bIntegrate );

	xStream << m_fTotalTimeRequired;
	xStream << m_fDurationOverride;

	const u_int uNumOccupiers = m_xOccupierGuids.Size();
	xStream << uNumOccupiers;
	for ( Asura_LinkList_ConstIt< Asura_Guid > xIt( m_xOccupierGuids ); !xIt.Done(); xIt.Next() )
	{
		xStream << *xIt.GetCurrent();
	}

	xStream << m_iBehaviourSet;
	Axon_BehaviourParams::WriteTreeToChunkStream( m_pxBehaviourParams, xStream );

	// DON'T FORGET TO UPDATE ApplyChangesForTemplateInstance IF YOU CHANGE STUFF.
}

bool Asura_ServerNode_GS2Spline::HandleMessage( const Asura_Message* pxMessage )
{
	bool bHandled = false;

	if ( m_pxBehaviourParams )
	{
		bHandled = m_pxBehaviourParams->DoHandleMessage( pxMessage );
	}

	switch ( pxMessage->GetMsgID() )
	{
		case ASURA_MSG_AXON_GS2_TAKE_LINK:
		case ASURA_MSG_AXON_GS2_ANIM_CHANGE:
		case ASURA_MSG_AXON_GS2_DONT_STOP_AT_NODE:
		case ASURA_MSG_AXON_GS2_TELEPORT_TO_NODE:
		case ASURA_MSG_AXON_GS2_PATHFIND_TO_NODE:
		{
			// Forward these messages on to our current users.
			for ( Asura_LinkList_ConstIt< Asura_Guid > xIt( m_xOccupierGuids ); !xIt.Done(); xIt.Next() )
			{
				Asura_Network::Forward( pxMessage, *xIt.GetCurrent(), GetGuid() );
			}

			bHandled = true;
			break;
		}

		case ASURA_MSG_AXON_GS2_EXIT_GAMESCENE:
		{
			// Special case. Take a copy of the list before forwarding the message on, because it may cause occupiers to be removed.
			Asura_LinkList< Asura_Guid > xOccupierCopy( m_xOccupierGuids );
			for ( Asura_LinkList_ConstIt< Asura_Guid > xIt( xOccupierCopy ); !xIt.Done(); xIt.Next() )
			{
				Asura_Network::Forward( pxMessage, *xIt.GetCurrent(), GetGuid() );
			}

			bHandled = true;
			break;
		}

		default:
		{
			break;
		}
	}

	if ( bHandled )
	{
		return true;
	}
	else
	{
		return PARENT::HandleMessage( pxMessage );
	}
}

bool Asura_ServerNode_GS2Spline::IsBaseOrDerivativeOf( u_short usClassification ) const
{
	if ( usClassification == AsuraEntityClass_GS2Spline )
	{
		return true;
	}
	return PARENT::IsBaseOrDerivativeOf( usClassification );
}

void Asura_ServerNode_GS2Spline::EnterSpline( const Asura_Guid uActorGuid )
{
	// Check we're not already here.
	Asura_Assert( !m_xOccupierGuids.Find( uActorGuid ), "Asura_ServerNode_GS2Spline::EnterSpline - guid already registered" );

	SetIsOccupied( true );
	m_xOccupierGuids.Push_Front( uActorGuid );
}

void Asura_ServerNode_GS2Spline::ExitSpline( const Asura_Guid uActorGuid )
{
	// Check we're here.
	Asura_Assert( m_xOccupierGuids.Find( uActorGuid ), "Asura_ServerNode_GS2Spline::ExitSpline - guid not registered" );

	m_xOccupierGuids.Remove( uActorGuid );
	SetIsOccupied( m_xOccupierGuids.Size() > 0 );
}

float Asura_ServerNode_GS2Spline::GetAverageLinkSpeed() const
{
	return ( GetTotalLinkTime() > 0.001f ) ? ( GetTotalLength() / GetTotalLinkTime() ) : Asura_Maths::LargeFloat;
}

float Asura_ServerNode_GS2Spline::GetPositionFromTime( const float fTimeElapsed, Asura_Vector_3& xOutput, Asura_Quat *pxOutputOrientation ) const
{
	const float fProportion = GetProportionFromTime( fTimeElapsed );
	GetPositionFromProportion( fProportion, xOutput, pxOutputOrientation );
	return ( fTimeElapsed > GetTotalLinkTime() ) ? ( fTimeElapsed - GetTotalLinkTime() ) : 0.0f;
}

float Asura_ServerNode_GS2Spline::GetTangentFromTime(const float fTimeElapsed, Asura_Vector_3& xOutput) const
{
	const float fProportion = GetProportionFromTime( fTimeElapsed );
	GetTangentFromProportion( fProportion, xOutput );
	return ( fTimeElapsed > GetTotalLinkTime() ) ? ( fTimeElapsed - GetTotalLinkTime() ) : 0.0f;
}

float Asura_ServerNode_GS2Spline::GetSpeedFromTime(const float fTimeElapsed) const
{
	const float fProportion = GetProportionFromTime(fTimeElapsed);
	if (m_bDistanceVsTimeGraph)
	{
		Asura_Assert(0, "Unimplemented!");
		return 1.0f;
	}
	else if (m_bOverrideDuration)
	{
		return m_pxSpeedOverTimeGraph->GetValueAtTime_Discrete(fProportion) * m_fTotalTimeRequired / m_fDurationOverride;
	}
	else
	{
		return m_pxSpeedOverTimeGraph->GetValueAtTime_Discrete(fProportion);
	}
}

float Asura_ServerNode_GS2Spline::GetFinalSpeed() const
{
	return GetSpeedFromTime(1.0f);
}

float Asura_ServerNode_GS2Spline::GetProportionFromTime(float fTimeElapsed) const
{
	if ( m_fTotalTimeRequired <= 0.0f )
	{
		return 0.0f;
	}
	else if ( m_bDistanceVsTimeGraph )
	{
		const float fTime = Asura_Maths::ClampToRange( fTimeElapsed / m_fDurationOverride, 0.0f, 1.0f );
		return m_pxSpeedOverTimeGraph->GetValueAtTime_Discrete( fTime );
	}
	else
	{
		const float fLength	= GetTotalLength();
		const float	fTime	= m_bOverrideDuration
							? Asura_Maths::ClampToRange( fTimeElapsed / m_fDurationOverride, 0.0f, 1.0f )
							: Asura_Maths::ClampToRange( fTimeElapsed / m_fTotalTimeRequired, 0.0f, 1.0f );
		const float	fValue	= m_bIntegratedGraph
							? m_pxSpeedOverTimeGraph->GetValueAtTime_Discrete( fTime )
							: m_pxSpeedOverTimeGraph->GetAreaUnderGraph( fTime );

		return ( fValue * m_fTotalTimeRequired / fLength );
	}
}

#ifndef ASURA_NO_DEBUG_OUTPUT
void Asura_ServerNode_GS2Spline::DoRenderDebugInfo()
{
	Asura_Hashed_List<Asura_ServerNode_GS2Spline>* pxGS2SplineList = Asura_ServerNode_GS2Spline::GetList();
	Asura_Hashed_List_It<Asura_ServerNode_GS2Spline> xIt(pxGS2SplineList);

	while ( !xIt.Done() )
	{
		Asura_ServerNode_GS2Spline* pxGS2Spline = xIt.GetCurrent();
		xIt.Next();

		if ( pxGS2Spline )
		{
			pxGS2Spline->RenderDebugInfo();
		}
	}
}

void Asura_ServerNode_GS2Spline::RenderDebugInfo()
{
	PARENT::RenderDebugInfo();

	// Render the line no matter what, as there's no good way of working out if we should render or not.
	Asura_ServerEntity_Node* pxSourceNode = Asura_ServerEntity_Node::GetList()->FindEntity( GetSourceGuid() );
	Asura_ServerEntity_Node* pxTargetNode = Asura_ServerEntity_Node::GetList()->FindEntity( GetTargetGuid() );
	if ( pxSourceNode && pxTargetNode )
	{
		Asura_DebugLineRender::AddArrow( pxSourceNode->GetPosition(), pxTargetNode->GetPosition(), 0xffffffff, 0.025f );
	}

	if ( !DebugTextPosOnScreen() ) { return; }

	Asura_Font_System::Print( GetDebugTextPos().x, GetDebugTextPos().y, 0.5f, 0xffffffff, ASURA_TEXTFORMAT_CENTREJUSTIFIED | ASURA_TEXTFORMAT_FORMATSTRING, 
		"GS2 Spline: %u", GetGuid() );
}
#endif

void Asura_ServerNode_GS2Spline::Create( const Asura_Guid uGuid, Asura_Chunk_Stream& xStream )
{
	Asura_ServerNode_GS2Spline* pxSpline = new Asura_ServerNode_GS2Spline( uGuid );
	pxSpline->ReadFromChunkStream( xStream );
}

#ifdef ASURA_TOOLS
bool Asura_ServerNode_GS2Spline::CanBeIncludedInTemplate() const
{
	return ( Classification == AsuraEntityClass_GS2Spline );
}

void Asura_ServerNode_GS2Spline::ApplyChangesForTemplateInstance( Tools_EntityTemplateInstance* pxInstance )
{
	PARENT::ApplyChangesForTemplateInstance( pxInstance );

	if ( m_pxBehaviourParams )
	{
		m_pxBehaviourParams->DoApplyChangesForTemplateInstance( pxInstance );
	}
}

void Asura_ServerNode_GS2Spline::CreateBasePoints()
{
	PARENT::CreateBasePoints();

	// Also set the point orientations.
	Asura_ServerNode_GS2Node* pxSource = Asura_ServerNode_GS2Node::FindEntity( GetSourceGuid() );
	Asura_ServerNode_GS2Node* pxTarget = Asura_ServerNode_GS2Node::FindEntity( GetTargetGuid() );
	if (!(pxSource && pxTarget))
	{
		return;
	}
	Asura_Quat xOrientQ;
	pxSource->GetOrientation( xOrientQ );
	SetPointOrientation( 0, xOrientQ );
	pxTarget->GetOrientation( xOrientQ );
	SetPointOrientation( 1, xOrientQ );
}

void Asura_ServerNode_GS2Spline::OnChanged()
{
	PARENT::OnChanged();
	ChangedDistanceTimeGraph();
	UpdateFollowSurface();
}

void Asura_ServerNode_GS2Spline::UpdateFollowSurface()
{
	if ( !m_bFollowSurfaceTools )
	{
		m_bFollowSurface = false;
	}
	else
	{
		float fLinkLength = GetTotalLength();
		for ( float fCurrentDistance = 0.0f; fCurrentDistance < fLinkLength; fCurrentDistance += 0.1f )
		{
			Asura_Vector_3 xPosition;
			Asura_Quat	   xQOrient;
			GetPositionFromDistance( fCurrentDistance, xPosition, &xQOrient );
			Asura_Vector_3 xUp( 0.0f, -1.0f, 0.0f );
			xUp = xQOrient.RotateVector( xUp);
			float fDistanceToIntersection;
			if ( Axon_Behaviour_GS2Actor::FollowSurfaceTest( xPosition, -xUp, fDistanceToIntersection ) )
			{
				if ( Asura_Maths::Abs( fDistanceToIntersection ) > 0.02f )
				{
					// (AW - 12.04.2005) - Follow ground makes a difference, don't disable.
					m_bFollowSurface = true;
					return;
				}
			}
		}
		// (AW - 12.04.2005) - Follow ground makes no difference at all, disable it.
		m_bFollowSurface = false;
	}
}

Asura_Graph<float>* Asura_ServerNode_GS2Spline::GetSpeedOverTimeGraph()
{
	return m_pxSpeedOverTimeGraph;
}

void Asura_ServerNode_GS2Spline::SetDistanceVsTimeGraph( const bool bDistanceTimeGraph ) 
{
	if (bDistanceTimeGraph != (bool)m_bDistanceVsTimeGraph)
	{
		if (bDistanceTimeGraph)
		{
			if (!m_bOverrideDuration || m_fDurationOverride < 0.001f)
			{
				m_fDurationOverride = GetTotalLength() / GetAverageLinkSpeed();
			}
			m_pxSpeedOverTimeGraph->Initialise(16, 0.0f, 1.0f, 0.0f, 1.f);
			m_pxSpeedOverTimeGraph->SetClampingValues(true, true, 0.0f, 1.0f);
		}
		else
		{
			m_pxSpeedOverTimeGraph->Initialise(16, GetAverageLinkSpeed(), GetAverageLinkSpeed(), 0.0f, 1.f);
			m_pxSpeedOverTimeGraph->SetClampingValues(true, false, 0.0f, Asura_Maths::LargeFloat);
		}
		m_bDistanceVsTimeGraph = bDistanceTimeGraph;
	}
}

float Asura_ServerNode_GS2Spline::GetTimeFromProportion( float fProportion ) const
{
	const u_int uNumSamples = m_pxSpeedOverTimeGraph->GetNumDiscreteSamples();
	const float fTimeSlice  = ( m_pxSpeedOverTimeGraph->GetDomainMax() - m_pxSpeedOverTimeGraph->GetDomainMin() ) / ( uNumSamples - 1 );

	float fTimeBefore = m_pxSpeedOverTimeGraph->GetDomainMin();
	float fTimeAfter  = fTimeBefore + fTimeSlice;

	if ( m_bDistanceVsTimeGraph )
	{
		for ( u_int u = 0; u < uNumSamples - 1; ++u )
		{
			const float fValueAfter = m_pxSpeedOverTimeGraph->GetValueAtTime_Discrete( fTimeAfter );
			if ( fValueAfter > fProportion )
			{
				const float fValueBefore = m_pxSpeedOverTimeGraph->GetValueAtTime_Discrete( fTimeBefore );
				const float fSubProp	 = ( fProportion - fValueBefore ) / ( fValueAfter - fValueBefore );

				return Asura_Maths::Lerp( fTimeBefore, fTimeAfter, fSubProp ) * GetTotalLinkTime();
			}

			fTimeBefore = fTimeAfter;
			fTimeAfter += fTimeSlice;
		}
	} 
	else if ( m_bIntegratedGraph )
	{
		for ( u_int u = 0; u < uNumSamples - 1; ++u )
		{
			const float fValueAfter = m_pxSpeedOverTimeGraph->GetValueAtTime_Discrete( fTimeAfter ) * GetTotalLinkTime() / GetTotalLength();
			if ( fValueAfter > fProportion )
			{
				const float fValueBefore = m_pxSpeedOverTimeGraph->GetValueAtTime_Discrete( fTimeBefore ) * GetTotalLinkTime() / GetTotalLength();
                const float fSubProp     = ( fProportion - fValueBefore ) / ( fValueAfter - fValueBefore );

				return Asura_Maths::Lerp( fTimeBefore, fTimeAfter, fSubProp ) * GetTotalLinkTime();
			}

			fTimeBefore = fTimeAfter;
			fTimeAfter += fTimeSlice;
		}
	}
	else
	{
		for ( u_int u = 0; u < uNumSamples - 1; ++u )
		{
			const float fValueAfter = m_pxSpeedOverTimeGraph->GetAreaUnderGraph( fTimeAfter ) * GetTotalLinkTime() / GetTotalLength();
			if ( fValueAfter > fProportion )
			{
				float fValueBefore = m_pxSpeedOverTimeGraph->GetAreaUnderGraph( fTimeBefore ) * GetTotalLinkTime() / GetTotalLength();
				float fSubProp = ( fProportion - fValueBefore ) / ( fValueAfter - fValueBefore );

				return Asura_Maths::Lerp( fTimeBefore, fTimeAfter, fSubProp ) * GetTotalLinkTime();
			}

			fTimeBefore = fTimeAfter;
			fTimeAfter += fTimeSlice;
		}
	}

	return GetTotalLinkTime();
}

void Asura_ServerNode_GS2Spline::ChangedDistanceTimeGraph()
{
	if (!m_bDistanceVsTimeGraph)
	{
		// (AW - 09.07.2004) - Figure out our average speed
		float fAverageSpeed = m_pxSpeedOverTimeGraph->GetAverageValue();
		fAverageSpeed = Asura_Maths::ClampToRange( fAverageSpeed, 0.01f, 1000.0f );

		// Calculate time required.
		m_fTotalTimeRequired = GetTotalLength() / fAverageSpeed;
	}
}

void Asura_ServerNode_GS2Spline::SetBehaviourSet( int iBehaviourSet )
{
	m_iBehaviourSet = iBehaviourSet;

	if ( m_pxBehaviourParams )
	{
		delete m_pxBehaviourParams;
		m_pxBehaviourParams = NULL;
	}

	// Create the correct behaviour parameters for the behaviour set.
	Axon_BehaviourParams::CreateTree( iBehaviourSet, m_pxBehaviourParams );
}

bool Asura_ServerNode_GS2Spline::UpdateBehaviourTree()
{
	Axon_BehaviourParams* pxBehaviourParams = NULL;
	if ( Axon_BehaviourParams::ConvertTree( m_iBehaviourSet, m_pxBehaviourParams, pxBehaviourParams ) )
	{
		delete m_pxBehaviourParams;
		m_pxBehaviourParams = pxBehaviourParams;
		return true;
	}
	return false;
}
#endif

//////////////////////////////////////////////////////////////////////////////
//
// 
//
//////////////////////////////////////////////////////////////////////////////

#endif // ASURA_USE_AXON
