//////////////////////////////////////////////////////////////////////////////
//
// AVP_Behaviour_AVP3Alien_StalkThreat.cpp
//
// Copyright (C) 2007 Rebellion. All Rights Reserved.
//
//////////////////////////////////////////////////////////////////////////////

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

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

// header
#include "Behaviour\BehaviourTypes\AVP3Alien\AVP_Behaviour_AVP3Alien_StalkThreat.h"

// asura
#include "AI/Asura_AI_Navigation.h"
#ifndef ASURA_NO_DEBUG_OUTPUT
#include "Debugging/Asura_DebugLineRender.h"
#include "Network/Asura_Message.h"
#include "Rendering/Asura_Font_System.h"
#endif

// axon
#include "Behaviour/BehaviourTypes/AVP_Behaviour_Types.h"
#include "Behaviour/BehaviourTypes/AVP3Alien/AVP_Behaviour_AVP3Alien_GetToMovingTarget.h"
#include "Behaviour/BehaviourTypes/AVP3Alien/AVP_Behaviour_AVP3Alien_KeepDistance.h"
#include "Behaviour/BehaviourTypes/AVP3Alien/AVP_Behaviour_AVP3Alien_Wander.h"
#include "Core/BrainTypes/AVP_Brain_Team_Alien.h"
#include "Core/BrainTypes/Axon_Project_Brain.h"

// avp
#include "Actor/AVP_Actor_PhysicsObjectHandler.h"
#include "Actor/Vertebrates/Alien/AVP_Alien_Description.h"
#include "Entity/AVP_Messages.h"
#include "Entity/Controller/AVP_ServerEntity_AlienTeam.h"
#include "Entity/PhysicalObject/Actor/AVP_ServerEntity_Actor.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/AVP_ServerActor_Vertebrate.h"
#include "Knowledge/AVP_Knowledge_System.h"
#include "Moves/AVP_Movement_System.h"
#include "Moves/Grapple/AVP_Grapple_Messages.h"

//////////////////////////////////////////////////////////////////////////////
//
// AVP_Behaviour_AVP3Alien_StalkThreat
//
//////////////////////////////////////////////////////////////////////////////

AVP_Behaviour_AVP3Alien_StalkThreat::AVP_Behaviour_AVP3Alien_StalkThreat( Axon_Project_Brain* pxBrain )
: PARENT( pxBrain, AXON_BEHAVIOUR_TYPE_AVP3ALIEN_STALK_THREAT )
{
}


bool AVP_Behaviour_AVP3Alien_StalkThreat::Activate()
{
	return PARENT::Activate();
}


void AVP_Behaviour_AVP3Alien_StalkThreat::Deactivate()
{
	// Destroy any children
	Axon_Behaviour* pxChildBehaviour = GetChild();
	while( pxChildBehaviour )
	{
		UnlinkChild( pxChildBehaviour );
		GetProjectBrain()->DestroyBehaviour( pxChildBehaviour );
		pxChildBehaviour = GetChild();
	}

	PARENT::Deactivate();
}


void AVP_Behaviour_AVP3Alien_StalkThreat::Update( const float fTimeslice )
{
//	PARENT::Update( fTimeslice );

	if( ( !GetProjectBrain() ) || ( !GetProjectBrain()->GetKnowledgeSystem() ) || ( !GetProjectBrain()->GetActor() ) || ( !AVP_ServerEntity_AlienTeam::GetInstance() ) || ( !AVP_ServerEntity_AlienTeam::GetInstance()->GetBrain() ) )
	{
		Asura_Assert( 0, "Alien AI error" );
		SetInError();
	}

	const Asura_Guid uBestThreatKnowledge = ( GetProjectBrain()->GetKnowledgeSystem()->HaveThreatKnowledge() && GetProjectBrain()->GetKnowledgeSystem()->GetBestThreatKnowledge() ) ?
											GetProjectBrain()->GetKnowledgeSystem()->GetBestThreatKnowledge()->GetGuid() : ASURA_GUID_UNREGISTERED;

	const AVP_ServerEntity_Actor* const pxActor = AVP_ServerEntity_Actor::FindEntity( uBestThreatKnowledge );

	if( ( uBestThreatKnowledge != ASURA_GUID_UNREGISTERED ) && ( !pxActor ) )
	{
		Asura_Assert( 0, "Couldn't find best threat actor" );
		SetInError();
	}

	if ( IsFinished() || IsInError() ) { return; }

//	const Asura_Vector_3& xThreatPosition = GetProjectBrain()->GetKnowledgeSystem()->GetBestThreatKnowledge()->m_xPosition;
//	const Asura_Vector_3& xOurPosition    = GetProjectBrain()->GetActor()->GetPosition();

	// Need an actor to do anything
	if( !GetProjectBrain()->GetActor() )
	{
		SwitchToState( STATE_IDLE );
		return;
	}

	switch( GetCurrentState() )
	{
		case STATE_IDLE:
		{
			// Fired at
			if( GetProjectBrain()->GetKnowledgeSystem()->IsFiredAt() )
			{
				SwitchToState( STATE_CHARGE ); // TODO: Flee
			}
			else
			if( uBestThreatKnowledge != ASURA_GUID_UNREGISTERED )
			{
				// Charge instantly, if in alert state (or no team brain)
				if( AVP_ServerEntity_AlienTeam::GetInstance()->GetBrain()->InAlertState() )
				{
					SwitchToState( STATE_CHARGE );
				}
				else
				{
					SwitchToState( STATE_TRACK_THREAT );
				}
			}
			else
			{
				SwitchToState( STATE_WANDER );
			}
			break;
		}

		case STATE_WANDER:
		{
            if( uBestThreatKnowledge != ASURA_GUID_UNREGISTERED )
            {
				SwitchToState( STATE_TRACK_THREAT );
			}
			else
			{
				AVP_Behaviour_AVP3Alien_Wander* pxChild = static_cast<AVP_Behaviour_AVP3Alien_Wander*>( GetChildWithType( this, AXON_BEHAVIOUR_TYPE_AVP3ALIEN_WANDER ) );
				if( ( !pxChild ) || pxChild->IsInError() || pxChild->IsFinished() )
				{
					SwitchToState( STATE_IDLE );
				}
				else
				// Fired at
				if( GetProjectBrain()->GetKnowledgeSystem()->IsFiredAt() )
				{
					SwitchToState( STATE_CHARGE ); // TODO: Flee
				}
			}
			break;
		}

		case STATE_TRACK_THREAT:
		{
            AVP_Behaviour_AVP3Alien_KeepDistance* pxChild = static_cast<AVP_Behaviour_AVP3Alien_KeepDistance*>( GetChildWithType( this, AXON_BEHAVIOUR_TYPE_AVP3ALIEN_KEEP_DISTANCE ) );
            if( ( !pxChild ) || pxChild->IsInError() || pxChild->IsFinished() )
            {
				// Something went wrong
                SwitchToState( STATE_IDLE );
            }
			else
			if( uBestThreatKnowledge == ASURA_GUID_UNREGISTERED )
			{
				// No threats, idle
                SwitchToState( STATE_IDLE );
			}
			else
			// Charge instantly, if in alert state (or no team brain)
			if( AVP_ServerEntity_AlienTeam::GetInstance()->GetBrain()->InAlertState() )
			{
				SwitchToState( STATE_CHARGE );
			}
			else
			{
				// Update closest (best) threat to follow
				pxChild->SetTargetGuid( uBestThreatKnowledge );

				// Fired at
				if( GetProjectBrain()->GetKnowledgeSystem()->IsFiredAt() )
				{
					SwitchToState( STATE_CHARGE );
				}
				else
				// Spotted
				if( GetProjectBrain()->GetKnowledgeSystem()->IsSpotted() )
				{
					SwitchToState( STATE_CHARGE ); // STATE_SCARE_THREAT ); TEMP
				}
				else
				// Possibly spotted
				if( GetProjectBrain()->GetKnowledgeSystem()->IsPossiblySpotted() )
				{
					SwitchToState( STATE_FREEZE );
				}
			}
			break;
		}

		case STATE_FREEZE:
		{
			if( uBestThreatKnowledge == ASURA_GUID_UNREGISTERED )
			{
				// No threats, idle
                SwitchToState( STATE_IDLE );
			}
			else
			{
				// Fired at
				if( GetProjectBrain()->GetKnowledgeSystem()->IsFiredAt() )
				{
					SwitchToState( STATE_CHARGE );
				}
				else
				// Charge instantly, if in alert state (or no team brain)
				if( AVP_ServerEntity_AlienTeam::GetInstance()->GetBrain()->InAlertState() )
				{
					SwitchToState( STATE_CHARGE );
				}
				else
				// Spotted
				if( GetProjectBrain()->GetKnowledgeSystem()->IsSpotted() )
				{
					SwitchToState( STATE_CHARGE ); // STATE_SCARE_THREAT ); TEMP
				}
				else
				// Not spotted
				if( !GetProjectBrain()->GetKnowledgeSystem()->IsPossiblySpotted() )
				{
					SwitchToState( STATE_TRACK_THREAT );
				}
			}
			break;
		}

		case STATE_SCARE_THREAT:
		{
			if( uBestThreatKnowledge == ASURA_GUID_UNREGISTERED )
			{
				SwitchToState( STATE_IDLE );
			}
			else
			// Fired at or anim finished
			if( GetProjectBrain()->GetKnowledgeSystem()->IsFiredAt() || GetProjectBrain()->RequestedAnimationHasFinished() )
			{
				SwitchToState( STATE_CHARGE );
			}
			break;
		}

		case STATE_CHARGE:
		{
			// Trigger alert state in team brain
			if( AVP_ServerEntity_AlienTeam::GetInstance() )
			{
				AVP_ServerEntity_AlienTeam::GetInstance()->GetBrain()->TriggerAlertState();
			}

			if( uBestThreatKnowledge == ASURA_GUID_UNREGISTERED )
			{
				SwitchToState( STATE_IDLE );
			}
			else
			{
                AVP_Behaviour_AVP3Alien_GetToMovingTarget* pxChild = static_cast<AVP_Behaviour_AVP3Alien_GetToMovingTarget*>( GetChildWithType( this, AXON_BEHAVIOUR_TYPE_AVP3ALIEN_GET_TO_MOVING_TARGET ) );
				if( ( !pxChild ) || pxChild->IsInError() )
				{
					SwitchToState( STATE_IDLE );
				}
				else
				if( pxChild->IsFinished() )
				{
					if( AVP_ServerEntity_AlienTeam::GetInstance() )
					{
						if( AVP_ServerEntity_AlienTeam::GetInstance()->GetAttackToken( GetProjectBrain()->GetActor()->GetGuid(), uBestThreatKnowledge ) )
						{
							if( AVP_ServerEntity_AlienTeam::GetInstance()->GetBrain()->GrappleAllowed( pxActor->IsPlayer() ) &&
								CheckGrappleAngles( pxActor ) )
							{
								SwitchToState( STATE_GRAPPLE );
							}
							else
							{
								SetFinished();
							}
						}
						else
						{
							SwitchToState( STATE_CIRCLE );
						}
					}
					else
					{
						Asura_Assert( 0, "No alien team entity on level" );
						SetInError();
					}
				}
			}
			break;
		}

		case STATE_GRAPPLE:
		{
			SwitchToState( STATE_IDLE );
			break;
		}

		case STATE_CIRCLE:
		{
            AVP_Behaviour_AVP3Alien_KeepDistance* pxChild = static_cast<AVP_Behaviour_AVP3Alien_KeepDistance*>( GetChildWithType( this, AXON_BEHAVIOUR_TYPE_AVP3ALIEN_KEEP_DISTANCE ) );
            if( ( !pxChild ) || pxChild->IsInError() || pxChild->IsFinished() )
            {
				// Something went wrong
                SwitchToState( STATE_IDLE );
            }
			else
			if( uBestThreatKnowledge == ASURA_GUID_UNREGISTERED )
			{
				// No threats, idle
                SwitchToState( STATE_IDLE );
			}
			else
			if( GetStateTimer() > 3.0f )
			{
				// Timer up
				SwitchToState( STATE_CHARGE );
			}
			break;
		}

		default:
		{
			Asura_Assert( 0, "AVP_Behaviour_AVP3Alien_StalkThreat::Update - invalid state" );
			SwitchToState( STATE_IDLE );
			break;
		}
	}
}

void AVP_Behaviour_AVP3Alien_StalkThreat::PerFrameUpdate( const float fTimeslice )
{
	UpdateStateTimer( fTimeslice );

	// Orient to target in scare state
	if( ( GetCurrentState() == STATE_SCARE_THREAT ) && GetProjectBrain() && GetProjectBrain()->GetKnowledgeSystem() && GetProjectBrain()->GetKnowledgeSystem()->GetBestThreatKnowledge() )
	{
		const AVP_ServerEntity_PhysicalObject* const pxPhysicalObjectTarget = AVP_ServerEntity_PhysicalObject::FindEntity( GetProjectBrain()->GetKnowledgeSystem()->GetBestThreatKnowledge()->GetGuid() );
		if ( !pxPhysicalObjectTarget )
		{
			Asura_Assertf( 0, ( "Can't find physical object with Guid:%u", GetProjectBrain()->GetKnowledgeSystem()->GetBestThreatKnowledge()->GetGuid() ) );
			SetInError();
			return;
		}

		// Turn to face the threat.
		OrientToPosition( &pxPhysicalObjectTarget->GetPosition(), fTimeslice );
	}
}

#ifndef ASURA_NO_DEBUG_OUTPUT
void AVP_Behaviour_AVP3Alien_StalkThreat::RenderDebugInfo()
{
	PARENT::RenderDebugInfo();

	static const char* s_aszStateStrings[NUM_STATES] =
	{
		"IDLE",
		"WANDER",
		"TRACK_THREAT",
		"FREEZE",
		"SCARE_THREAT",
		"CHARGE",
		"GRAPPLE",
		"CIRCLE"
	};

	static const u_int auStateDebugColour[NUM_STATES] =
	{
		0xFFD8D8D8, // STATE_IDLE			- Gray
		0xFFFFFFFF, // STATE_WANDER			- White
		0xFF08FF08, // STATE_TRACK_THREAT	- Green
		0xFF00D8FF, // STATE_FREEZE			- Light Blue
		0xFFFFFF08,	// STATE_SCARE_THREAT	- Yellow
		0xFFFF2828,	// STATE_CHARGE			- Bright Red
		0xFFFF2828,	// STATE_GRAPPLE		- Bright Red
		0xFFFFFF08	// STATE_CIRCLE			- Yellow
	};

	static const char* s_aszAwarenessStrings[5] =
	{
		"POSSIBLY SPOTTED",
		"POSSIBLY AIMED AT",
		"SPOTTED",
		"AIMED AT",
		"FIRING"
	};

	static const u_int auAwarenessColour[5] =
	{
		0xFF08FF08, // POSSIBLY SPOTTED		- Green
		0xFF08FF08, // POSSIBLY AIMED AT	- Green
		0xFFFFFF08, // SPOTTED				- Yellow
		0xFFFFFF08, // AIMED AT				- Yellow
		0xFFFF2828, // FIRING				- Bright Red
	};

	Asura_Font_System::Print( GetProjectBrain()->GetDebugOutputPos().x, GetProjectBrain()->GetDebugOutputPos().y, 0.5f, auStateDebugColour[ GetCurrentState() ],
		ASURA_TEXTFORMAT_CENTREJUSTIFIED | ASURA_TEXTFORMAT_FORMATSTRING, "%s", s_aszStateStrings[ GetCurrentState() ] );

	GetProjectBrain()->GetDebugOutputPos().y += 10.0f;

	const int iBestAwarenessTypeMinus1 = GetProjectBrain()->GetKnowledgeSystem()->GetBestAwarenessKnowledge()->m_uTypeInformation - 1;
	if( iBestAwarenessTypeMinus1 >= 0 )
	{
		Asura_Font_System::Print( GetProjectBrain()->GetDebugOutputPos().x, GetProjectBrain()->GetDebugOutputPos().y, 0.5f, auAwarenessColour[iBestAwarenessTypeMinus1],
			ASURA_TEXTFORMAT_CENTREJUSTIFIED, s_aszAwarenessStrings[iBestAwarenessTypeMinus1] );

		GetProjectBrain()->GetDebugOutputPos().y += 10.0f;
	}
}
#endif


//////////////////////////////////////////////////////////////////////////////
//
// Private
//
//////////////////////////////////////////////////////////////////////////////

void AVP_Behaviour_AVP3Alien_StalkThreat::SwitchToState( const State eNextState )
{
	if( GetCurrentState() == eNextState )
	{
		return;
	}

	bool bGotoIdleState = false;

	if( ( !GetProjectBrain() ) || ( !GetProjectBrain()->GetKnowledgeSystem() ) )
	{
		Asura_Assert( 0, "No brain or knowledge system" );
		bGotoIdleState = true;
	}

	// Do any work we need to exit our current state.
	switch ( GetCurrentState() )
	{
		case STATE_IDLE:
		{
			break;
		}

		case STATE_WANDER:
		{
			DestroyChildWithType( AXON_BEHAVIOUR_TYPE_AVP3ALIEN_WANDER );
			break;
		}

		case STATE_TRACK_THREAT:
		{
			DestroyChildWithType( AXON_BEHAVIOUR_TYPE_AVP3ALIEN_KEEP_DISTANCE );
			break;
		}

		case STATE_FREEZE:
		{
			break;
		}

		case STATE_SCARE_THREAT:
		{
			break;
		}

		case STATE_CHARGE:
		{
			DestroyChildWithType( AXON_BEHAVIOUR_TYPE_AVP3ALIEN_GET_TO_MOVING_TARGET );
			break;
		}

		case STATE_GRAPPLE:
		{
			AVP_ServerEntity_AlienTeam::GetInstance()->GetBrain()->SetGrappleVictim( ASURA_GUID_UNREGISTERED );
			AVP_ServerEntity_AlienTeam::GetInstance()->ReturnAttackToken( GetProjectBrain()->GetActor()->GetGuid() );
			break;
		}

		case STATE_CIRCLE:
		{
			DestroyChildWithType( AXON_BEHAVIOUR_TYPE_AVP3ALIEN_KEEP_DISTANCE );
			break;
		}

		default:
		{
			Asura_Assert( 0, "AVP_Behaviour_AVP3Alien_StalkThreat::SwitchToState - invalid prev state" );
			break;
		}
	}

	// Do any work we need to change into our next state.
	SetCurrentState( eNextState );

	switch ( GetCurrentState() )
	{
		case STATE_IDLE:
		{
			GetProjectBrain()->RequestAnimation( AVP_Alien_Description::ALIEN_ANIM_IDLE );
			break;
		}

		case STATE_WANDER:
		{
			CreateChildWithType( AXON_BEHAVIOUR_TYPE_AVP3ALIEN_WANDER );
			break;
		}

		case STATE_TRACK_THREAT:
		{
			if( !GetProjectBrain()->GetKnowledgeSystem()->GetBestThreatKnowledge() )
			{
				// No threat knowledge
				bGotoIdleState = true;
			}
			else
			{
				AVP_Behaviour_AVP3Alien_KeepDistance* pxChild = static_cast<AVP_Behaviour_AVP3Alien_KeepDistance*>( CreateChildWithType( AXON_BEHAVIOUR_TYPE_AVP3ALIEN_KEEP_DISTANCE ) );
				if ( !pxChild )
				{
					Asura_Assert( 0, "Unable to create AXON_BEHAVIOUR_TYPE_AVP3ALIEN_KEEP_DISTANCE child behaviour" );
					bGotoIdleState = true;
				}
				else
				{
					// Set follow info
					GetProjectBrain()->GetNavData().m_eMovementMode = AVP_Navigation::MM_SLOWEST;
					pxChild->SetTargetGuid( GetProjectBrain()->GetKnowledgeSystem()->GetBestThreatKnowledge()->GetGuid() );

					if ( GetProjectBrain() && GetProjectBrain()->GetTeam() )
					{
						pxChild->SetFollowDist( GetProjectBrain()->GetTeam()->GetStalkDistance() );
					}
					else
					{
						pxChild->SetFollowDist( 12.0f );
					}
				}
			}
			break;
		}

		case STATE_FREEZE:
		{
			break;
		}

		case STATE_SCARE_THREAT:
		{
			GetProjectBrain()->RequestAnimation( AVP_Alien_Description::ALIEN_ANIM_TAUNT );
			break;
		}

		case STATE_CHARGE:
		{
			if( !GetProjectBrain()->GetKnowledgeSystem()->GetBestThreatKnowledge() )
			{
				// No threat knowledge
				bGotoIdleState = true;
			}
			else
			{
				AVP_Behaviour_AVP3Alien_GetToMovingTarget* pxChild = static_cast<AVP_Behaviour_AVP3Alien_GetToMovingTarget*>( CreateChildWithType( AXON_BEHAVIOUR_TYPE_AVP3ALIEN_GET_TO_MOVING_TARGET ) );
				if ( !pxChild )
				{
					Asura_Assert( 0, "Unable to create AXON_BEHAVIOUR_TYPE_AVP3ALIEN_GET_TO_MOVING_TARGET child behaviour" );
					bGotoIdleState = true;
				}
				else
				{
					// Set follow info
					GetProjectBrain()->GetNavData().m_eMovementMode = AVP_Navigation::MM_FASTEST;
					pxChild->SetTargetGuid( GetProjectBrain()->GetKnowledgeSystem()->GetBestThreatKnowledge()->GetGuid() );

					const float fMinRange = 2.0f; // TODO: From blueprint
					const float fMaxRange = 6.0f;
					pxChild->SetArrivalRange( Asura_Random::GetFloat() * ( fMaxRange - fMinRange ) + fMinRange );
				}
			}
			break;
		}

		case STATE_GRAPPLE:
		{
			if( !DoGrapple( GetProjectBrain()->GetKnowledgeSystem()->GetBestThreatKnowledge()->GetGuid() ) )
			{
				bGotoIdleState = true;
			}
			break;
		}

		case STATE_CIRCLE:
		{
			if( !GetProjectBrain()->GetKnowledgeSystem()->GetBestThreatKnowledge() )
			{
				// No threat knowledge
				bGotoIdleState = true;
			}
			else
			{
				AVP_Behaviour_AVP3Alien_KeepDistance* pxChild = static_cast<AVP_Behaviour_AVP3Alien_KeepDistance*>( CreateChildWithType( AXON_BEHAVIOUR_TYPE_AVP3ALIEN_KEEP_DISTANCE ) );
				if ( !pxChild )
				{
					Asura_Assert( 0, "Unable to create AXON_BEHAVIOUR_TYPE_AVP3ALIEN_KEEP_DISTANCE child behaviour" );
					bGotoIdleState = true;
				}
				else
				{
					// Set follow info
					GetProjectBrain()->GetNavData().m_eMovementMode = AVP_Navigation::MM_FAST;
					pxChild->SetTargetGuid( GetProjectBrain()->GetKnowledgeSystem()->GetBestThreatKnowledge()->GetGuid() );

					static const float fCIRCLE_DIST = 6.0f;
					pxChild->SetFollowDist( fCIRCLE_DIST + Asura_Random::GetFloat() * 2 );
				}
			}
			break;
		}

		default:
		{
			Asura_Assert( 0, "AVP_Behaviour_AVP3Alien_StalkThreat::SwitchToState - invalid next state" );
			bGotoIdleState = true;
			break;
		}
	}

	if( bGotoIdleState )
	{
		SwitchToState( STATE_IDLE );
	}
}

bool AVP_Behaviour_AVP3Alien_StalkThreat::CheckGrappleAngles( const AVP_ServerEntity_Actor* const pxTargetActor )
{
	const AVP_ServerEntity_Actor* const pxActor = GetProjectBrain() ? GetProjectBrain()->GetActor() : NULL;
	if( !pxActor )
	{
		return false;
	}

	const Asura_Matrix_3x3 xTargetOrientation = pxTargetActor->GetOrientation();

	const Asura_Vector_3 xDirection = pxActor->GetPosition() - pxTargetActor->GetPosition();
	const Asura_Vector_3 xTargetDirection( xTargetOrientation.e13, xTargetOrientation.e23, xTargetOrientation.e33 );

	const float fAngle = Asura_Maths::ArcCosine( ( xDirection * xTargetDirection ) / ( xDirection.Magnitude() * xTargetDirection.Magnitude() ) );

	static const float fMIN_ANGLE = -Asura_Maths::Pi / 7;
	static const float fMAX_ANGLE = Asura_Maths::Pi / 7;

	return ( fAngle >= fMIN_ANGLE ) && ( fAngle <= fMAX_ANGLE );
}

bool AVP_Behaviour_AVP3Alien_StalkThreat::DoGrapple( Asura_Guid uTargetGuid )
{
	// Ask team brain first
	if( !AVP_ServerEntity_AlienTeam::GetInstance()->GetBrain()->SetGrappleVictim( uTargetGuid ) )
	{
		return false;
	}

	// Send the panic mechanic message trigger and switch state.
	Asura_Message* pxMessage = Asura_Network::CreateMessage( ASURA_MSG_MOVE_START, sizeof( AVP_Msg_Grapple_JumpMove_Start ) );
	if ( pxMessage )
	{
		AVP_Msg_Grapple_JumpMove_Start* pxData = static_cast< AVP_Msg_Grapple_JumpMove_Start* >( pxMessage->GetData() );
		pxData->SetMoveID(Asura_GetHashID( "AVP_Attacker_MovesGrapple_Jump" ));
		pxData->SetAttackerGuid( GetProjectBrain()->GetOwnerGuid() );
		pxData->SetVictimGuid( uTargetGuid );
		pxData->SetCanDodge(false);

		pxMessage->SetToGuid( GetProjectBrain()->GetOwnerGuid() );
		pxMessage->SetFromGuid( GetProjectBrain()->GetOwnerGuid() );
		pxMessage->UseGuaranteedDelivery();

		Asura_Network::Send( pxMessage );

		return true;
	}

	return false;
}

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