
///////////////////////////////////////////////////////////////////////////////
//
// File   : AVP_Alien_InputHandler.h
// Author : Chris Wallace
// Date   : 5-Feb-2007
//
// Copyright (C) 2007 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
	#pragma once
#endif   // ifdef ASURA_USE_PRAGMA_ONCE

#ifndef __AVP_ALIEN_INPUTHANDLER_H__
#define __AVP_ALIEN_INPUTHANDLER_H__

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

#include "Actor/Vertebrates/AVP_Vertebrate_InputHandler.h"

#include "Attractors/Asura_Attractor_Data.h"

#include "Core/AVP_LOS.h"

////////////////////////////////////////////////////////////////////////////////
// Forward class declarations...
////////////////////////////////////////////////////////////////////////////////

class Asura_Attractor_Compiled;
class AVP_ClientActor_Alien;

////////////////////////////////////////////////////////////////////////////////
// Class declaration...
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Alien_InputHandler
// Author       : Andy Tate
// Date         : 3-Oct-2006
//
// Description  : Class to handle the input for a predator client-entity and
//				  create the appropriate message data for the server-entity.
////////////////////////////////////////////////////////////////////////////////

class AVP_Alien_InputHandler : public AVP_Vertebrate_InputHandler
{
public:
	// Public functions...
	AVP_Alien_InputHandler(const Asura_Guid uOwnerGuid);
	virtual ~AVP_Alien_InputHandler() {}

	virtual	void Reset(void);

	virtual void MapTailAttack(Asura_ControlMap& xMap, const u_int uKeyTail);
	virtual void MapPetFacehuggerControl(Asura_ControlMap& xMap, const u_int uKeySpawn);
	virtual void MapInteractAndPetFacehuggerControlToSameKey(Asura_ControlMap& xMap, const u_int uKeyInteractOrSpawn);
	virtual void MapCreateDistraction(Asura_ControlMap& xMap, const u_int uKeyDistract);
	virtual void MapTransition(Asura_ControlMap& xMap, const u_int uKeyTransition );

	// Overridden functions...
	virtual void RefreshBlueprintData(void);

	virtual	Asura_Message* Update(AVP_ClientEntity_Actor& xClient);

	virtual void SetNewLookDirection( AVP_ClientEntity_Actor& xClient, const Asura_AVector3& xDir, const bool bImmediate );

//#ifdef ASURA_SUPPORT_COMMAND_CONSOLE
	static void CreateConsoleVars();
//#endif //#ifdef ASURA_SUPPORT_COMMAND_CONSOLE

protected:
	// Protected variables...

	// Protected functions...	
	virtual void UpdateMovementInput(AVP_ClientEntity_Actor& xClient);
	virtual void UpdateWeapons( AVP_ClientEntity_Actor& xClient ) {}
	virtual void UpdateZoom( AVP_ClientActor_Vertebrate& xClient ) {}
	virtual void UpdateVisionModes( AVP_ClientEntity_Actor& xClient ) {}
	virtual void UpdateMeleeRequests( AVP_ClientActor_Vertebrate& xClient );

	void UpdateAimDirection( AVP_ClientEntity_Actor& xClient );
	void UpdateAimDirectionPrediction( AVP_ClientEntity_Actor& xClient, Asura_Vector_3& xAim );

	virtual	Asura_Message*	CreatePlayerCommandMessageToServer( const AVP_ClientEntity_Actor& xClient ) const;

	float m_fBranchDismountInputTimer;

private:
	// Private typedefs...
	typedef AVP_Vertebrate_InputHandler PARENT;

	struct BranchCallbackData
	{
		AVP_Alien_InputHandler& m_xInputHandler;
		const AVP_ClientActor_Alien& m_xAlien;
		const Asura_Vector_3& m_xTestDirection;
		const Asura_Vector_3& m_xGravityDirection;
		const Asura_Vector_3& m_xCharacterForward;
		const Asura_Vector_3& m_xCurrentAttractorNormal;
		const bool m_bEasyTraversalOnly; // If true, we're much stricter on the required similarity of attractor normals
		const bool m_bApproachingAttractorEnd; // If true, we allow transitions to attractors that normally aren't close enough to our test direction, unless there're several viable alternatives.
		const bool m_bAllowJunctionTransition; // Based on whether we're pushing roughly along the current attractor, decides whether anything other than the current is allowed.
		u_int m_uBestAttractor;
		float m_fBestDirectionDPResult;
		float m_fBestNormalDPResult;
		Asura_Vector_3 m_xBestPosOnAttractor; // Cached so we don't need to calculate it after returning from the search.
		Asura_Quat m_xTargetOrientation; // Ditto.

		BranchCallbackData(AVP_Alien_InputHandler& xInputHandler, const AVP_ClientActor_Alien& xAlien, const Asura_Vector_3& xTestDirection, const Asura_Vector_3& xGravityDirection, const Asura_Vector_3& xCharacterForward, const Asura_Vector_3& xCurrentAttractorNormal, bool bEasyTraversalOnly, bool bApproachingAttractorEnd, bool bAllowJunctionTransition)
			: m_xInputHandler(xInputHandler)
			, m_xAlien(xAlien)
			, m_xTestDirection(xTestDirection)
			, m_xGravityDirection(xGravityDirection)
			, m_xCharacterForward(xCharacterForward)
			, m_xCurrentAttractorNormal(xCurrentAttractorNormal)
			, m_bEasyTraversalOnly(bEasyTraversalOnly)
			, m_bApproachingAttractorEnd(bApproachingAttractorEnd)
			, m_bAllowJunctionTransition(bAllowJunctionTransition)
			, m_uBestAttractor(uASURA_ATTRACTOR_ID_NONE)
			, m_fBestDirectionDPResult(-1.0f)
			, m_fBestNormalDPResult(-1.0f)
			, m_xBestPosOnAttractor(Asura_Maths::ZeroVector3)
			, m_xTargetOrientation(Asura_Maths::IdentityQuat)
		{
		}
	};

	struct LeapCallbackData
	{
		AVP_Alien_InputHandler& m_xInputHandler;
		const AVP_ClientActor_Alien& m_xAlien;
		Asura_Vector_3& m_xLeapPositionOut;
		Asura_Vector_3& m_xLeapNormalOut;
		Asura_Vector_3 m_xTestDir;
		float m_fTestDist;
		float m_fMinDist;
		float m_fClosestTestDist;
		Asura_Guid m_uBestAttractor;

		LeapCallbackData(AVP_Alien_InputHandler& xInputHandler, const AVP_ClientActor_Alien& xAlien, const Asura_Vector_3& xTestDisplacement, const float fMinDistToAttractor, Asura_Vector_3& xLeapPosOut, Asura_Vector_3& xLeapNormOut)
		: m_xInputHandler(xInputHandler)
		, m_xAlien(xAlien)
		, m_xLeapPositionOut(xLeapPosOut)
		, m_xLeapNormalOut(xLeapNormOut)
		, m_xTestDir(xTestDisplacement)
		, m_fMinDist(fMinDistToAttractor)
		, m_fClosestTestDist(Asura_Maths::LargeFloat)
		, m_uBestAttractor(uASURA_ATTRACTOR_ID_NONE)
		{
			m_fTestDist = m_xTestDir.Normalise();
		}
	};


	class PredictionLOSFunctor
	{
	public:
		PredictionLOSFunctor( Asura_LOS_OutputData& xOutputData ) : m_rxOutData( xOutputData ) {}

		bool CheckEntity( Asura_Entity_Renderable* pxEntity, const Asura_LOS_InputData& xInputData );
		float GetInitialMaxDistance() { return m_rxOutData.m_fDistanceToIntersection; }
		float GetMaxDistance() { return m_rxOutData.m_fDistanceToIntersection; }
		bool ShouldStop() { return false; }

	private:
		Asura_LOS_OutputData&	m_rxOutData;
	};

	// Private functions...
	AVP_Alien_InputHandler(const AVP_Alien_InputHandler& xOther);

	AVP_Alien_InputHandler&	operator=(const AVP_Alien_InputHandler& xOther);

	// Platform specific control-map creation...
	void	Platform_InitialiseControlMap(void);

	void TestBranchAttractor(const Asura_Attractor_Compiled& xAttractor, BranchCallbackData& xData);
	static void TestBranchAttractors_Callback(void* pData, const Asura_Attractor_Compiled* const pxAttractor);

	void SendMountBranchMoveMessage(const Asura_Vector_3& xTargetPos, const Asura_Quat& xTargetOrientation, AVP_ClientActor_Alien& xOwner) const;
	void SendDismountBranchMoveMessage(const Asura_Vector_3& xDirection, AVP_ClientActor_Alien& xOwner) const;

	void TestLeapAttractor( const Asura_Attractor_Compiled& xAttractor, LeapCallbackData& xData );
	static void TestLeapAttractors_Callback( void* pData, const Asura_Attractor_Compiled* const pxAttractor );

	// Private variables...
	Asura_Vector_3 m_xLastUpVector;
	float m_fLookSmoothingTimer;

	float m_fMaxDistanceBetweenAlienAndBranchForAttachSquared;
	float m_fMaxDistanceBelowBranchForAttach;
	float m_fAlienBranchLOSDistance;
	float m_fAlienBranchInputTimeForDismount;
	float m_fAlienBranchMaxCosAngleForDismount;

};   // End of class 'AVP_Alien_InputHandler'.


#endif   // ifndef __AVP_ALIEN_INPUTHANDLER_H__


/// End of file. ///
