
///////////////////////////////////////////////////////////////////////////////
//
// File   : AVP_Predator_JumpHandler.cpp
// Author : Andy Tate
// Date   : 26-Sep-2007
//
// Copyright (C) 2007 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

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

#include "Core/Asura.h"

// This file's header...
#include "Actor/Vertebrates/Predator/AVP_Predator_JumpHandler.h"

// Asura independent header-files...
#include "Attractors/Asura_Attractor_System.h"
#include "Blueprint/Asura_Blueprint_System.h"
#include "Camera/Asura_Camera.h"
#if !defined(ASURA_NO_DEBUG_OUTPUT)
#include "Debugging/Asura_DebugLineRender.h"
#endif	// !defined(ASURA_NO_DEBUG_OUTPUT)
#include "Network/Asura_Message.h"
#include "Network/Asura_Network.h"
#include "ProjectSettings/Asura_PhysicsConfiguration.h"
#include "Rendering/Asura_Font_System.h"
#include "SpecialFX/PFX/Asura_PFX_Entity_Effect.h"
#include "SpecialFX/PFX/Asura_PFX_System.h"

// Game independent header-files...
#include "Actor/AVP_Actor_AnimationHandler.h"
#include "Actor/Vertebrates/AVP_Vertebrate_CameraHandler.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_Description.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_Focus.h"
#include "Actor/Vertebrates/Predator/AVP_Predator_InputHandler.h"
#include "Blueprint/AVP_Blueprint_HashIDs.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Predator/AVP_ClientActor_Predator.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Predator/AVP_Messages_Predator.h"
#include "Moves/Vertebrates/Predator/AVP_Predator_MovesJump.h"


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

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Predator_JumpHandler::AVP_Predator_JumpHandler
// Author       : Andy Tate
// Date         : 26-Sep-2007
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_JumpHandler::AVP_Predator_JumpHandler(AVP_ClientActor_Vertebrate& m_xOwner)
: PARENT(m_xOwner)
{
}

/// End of function 'AVP_Predator_JumpHandler::AVP_Predator_JumpHandler'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Predator_JumpHandler::~AVP_Predator_JumpHandler
// Author       : Andy Tate
// Date         : 26-Sep-2007
////////////////////////////////////////////////////////////////////////////////

AVP_Predator_JumpHandler::~AVP_Predator_JumpHandler()
{
}

/// End of function 'AVP_Predator_JumpHandler::~AVP_Predator_JumpHandler'. ///


////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_Predator_JumpHandler::HandleJump
// Author       : Anthony Gregson
// Date         : 08/10/07
////////////////////////////////////////////////////////////////////////////////

bool AVP_Predator_JumpHandler::HandleJump( const float fJumpValue )
{
	const AVP_Predator_Focus* pxFocus = static_cast<const AVP_Predator_Focus*>(m_xOwner.GetFocus());
	if (!pxFocus) { return PARENT::HandleJump(fJumpValue); }

	if (!pxFocus->GetJumpAvailable())
	{
		// go up to the standard jump if we haven't found a target
		// However, if focus is active we still don't want to jump at all.
		if (pxFocus->GetActive())
		{
			return false;
		}
		else
		{
			return PARENT::HandleJump(fJumpValue);
		}
	}

	if ((fJumpValue <= 0.0f) || ((m_xOwner.GetConstrainedMovementAttractorID() == uASURA_ATTRACTOR_ID_NONE) && (m_xOwner.GetGroundType() == AVP_Actor_PhysicsObjectHandler::OFF_GROUND)))
	{
		return false;
	}

	// See if we already have a movement-controlling move in progress, and disallow jumps if we do.
	const Asura_Movement_System* pxMovementSystem = m_xOwner.GetMovementSystem();
	const AVP_Move* pxCurrentMove = pxMovementSystem ? static_cast<const AVP_Move*>(pxMovementSystem->GetCurrentMove()) : NULL;
	if (pxCurrentMove && (pxCurrentMove->IsDisableMovement() || (pxCurrentMove->GetAVPAnimationData() && !pxCurrentMove->GetAVPAnimationData()->GetDontCalculateVelocity())))
	{
		return false;
	}

	// reset the zoom level
	AVP_Vertebrate_CameraHandler* pxCameraHandler = static_cast<AVP_Vertebrate_CameraHandler*>( m_xOwner.GetCameraHandler() );
	pxCameraHandler->SetZoomLevel( m_xOwner, 0 );

	return SendJumpMoveStartMessage( m_xOwner.GetGuid(), AVP_PREDATOR_JUMPTYPE_TARGETED, pxFocus->GetJumpDestinationPosition(), pxFocus->IsJumpNoisy() ? AVP_ClientActor_Vertebrate::JUMPLAND_NORMAL : AVP_ClientActor_Vertebrate::JUMPLAND_LIGHT, pxFocus->GetJumpVariation() ) != ASURA_HASH_ID_UNSET;
}

DEBUGVAR float dbg_fPlayerJumpTurnTime = 0.75f;

Asura_Hash_ID AVP_Predator_JumpHandler::SendJumpMoveStartMessage( const Asura_Guid uOwnerGuid, const AVP_PREDATOR_JUMPTYPE eJumpType, const Asura_Vector_3& xTargetPosition, const AVP_ClientActor_Vertebrate::JumpLandType eJumpLandType, const int iTargetedJumpVariation/* = 0*/ )
{
	Asura_Hash_ID uMoveHash( ASURA_HASH_ID_UNSET );
	if ( eJumpType == AVP_PREDATOR_JUMPTYPE_TARGETED )
	{
		Asura_Message* pxMessage = Asura_Network::CreateMessage( ASURA_MSG_MOVE_START, sizeof( AVP_Message_Predator_Move_JumpStart ) );

		if ( pxMessage != NULL )
		{
			uMoveHash = AVP_Move_Predator_JumpTarget::GetStaticHash();

			AVP_Message_Predator_Move_JumpStart* pxData = static_cast< AVP_Message_Predator_Move_JumpStart* >( pxMessage->GetData() );

			// Fill-in the message-body...
			pxMessage->SetFromGuid( uOwnerGuid );
			pxMessage->SetToGuid( uOwnerGuid );

			pxData->ClearFlags();
			pxData->SetMoveID( uMoveHash );
			pxData->SetForceAbort( true );
			pxData->SetIgnoredByOwner( false );
			pxData->SetJumpData(xTargetPosition, eJumpLandType, iTargetedJumpVariation, dbg_fPlayerJumpTurnTime);

			// Forward the message directly to the client...
			AVP_ClientEntity_Actor* pxClient = AVP_ClientEntity_Actor::FindEntity( uOwnerGuid );
			if ( pxClient->HandleMessage( pxMessage ) )
			{
				// ...before informing all other client's as well...
				pxData->SetIgnoredByOwner( true );
				Asura_Network::Send( pxMessage );
			}
			else
			{
				Asura_Assert( false, "Client failed to handle message." );
				Asura_Network::DestroyMessage(pxMessage);
				uMoveHash = ASURA_HASH_ID_UNSET;
			}
		}
		else
		{
			Asura_Assert( false, "Unable to create message" );
		}
	}
	else
	{
		Asura_Assert( false, "Unhandled jump type" );
	}
	return uMoveHash;
}

/// End of function 'AVP_Alien_JumpHandler::HandleJump'. ///

/// End of file. ///
