//////////////////////////////////////////////////////////////////////////////
//
// AVP_Movement_System.h
//
// Copyright (c) 2007 Rebellion. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////////

// B E G I N   F I L E   W R A P P E R ///////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef ___AVP_MOVEMENT_SYSTEM_H___
#define ___AVP_MOVEMENT_SYSTEM_H___ 1

// E N D   F I L E   W R A P P E R ///////////////////////////////////////////

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

#include "Entity/PhysicalObject/Moves/Asura_Movement_System.h"

// F O R W A R D   D E C L A R A T I O N S ///////////////////////////////////

class AVP_ClientEntity_Actor;

// C L A S S E S /////////////////////////////////////////////////////////////

class AVP_Msg_Move : public Asura_Msg_Move
{
public:
	// Intentionally no Set functions in the base class, these can only be set from subclasses where they're valid.
	bool GetHasTargetEntity() const { return (m_usProjectFlags & AVP_MSG_MOVE_FLAG_HASTARGETENTITY) != 0; }
	bool GetTargetEntityIsPuppet() const { return (m_usProjectFlags & AVP_MSG_MOVE_FLAG_TARGETENTITYISPUPPET) != 0; }

protected:

	enum
	{
		AVP_MSG_MOVE_FLAG_HASTARGETENTITY		= 0x0001,
		AVP_MSG_MOVE_FLAG_TARGETENTITYISPUPPET	= 0x0002, // If this flag is set, we'll also tell the target entity about the move starting.
	};
};

// Message subclass for puppeteer moves, although other moves can use it too (such as melee moves).
class AVP_Msg_MoveWithTargetEntity : public AVP_Msg_Move
{
public:
 	Asura_Guid GetTargetGuid() const { return m_uTargetGuid; }
 	void SetTargetGuid(Asura_Guid uTargetGuid);

	void SetTargetEntityIsPuppet(bool bIsPuppet);

protected:
	Asura_Guid m_uTargetGuid;
};

class AVP_Msg_Melee_Move : public AVP_Msg_MoveWithTargetEntity
{
public:
	u_int GetVariation() const					{ return m_uVariation; }
	void SetVariation(u_int uVariation)			{ m_uVariation = uVariation; }

	u_int GetPendingAttackType() const					{ return m_uPendingAttackType; }
	void SetPendingAttackType(u_int uPendingAttackType)	{ m_uPendingAttackType = uPendingAttackType; }

	bool GetSuckPermitted() const { return (m_usProjectFlags & AVP_MSG_MELEE_MOVE_FLAG_SUCKPERMITTED) != 0; }
	void SetSuckPermitted(bool bPermitted);

private:
	u_int m_uVariation;
	u_int m_uPendingAttackType;

	enum
	{
		AVP_MSG_MELEE_MOVE_FLAG_SUCKPERMITTED	= 0x0010,	// Allows the server to pick whether target suck is within range
	};
};

class AVP_Msg_Grapple_Move : public AVP_Msg_MoveWithTargetEntity
{
public:
	Asura_Hash_ID GetGrappleDescriptionBlueprint() const	{ return m_uGrappleDescriptionBlueprint; }
	void SetGrappleDescriptionBlueprint(u_int uBlueprint)	{ m_uGrappleDescriptionBlueprint = uBlueprint; }

private:
	Asura_Hash_ID m_uGrappleDescriptionBlueprint;
};

class AVP_Msg_MeleeWithTargetPosition_Move : public AVP_Msg_Melee_Move
{
public:
 	const Asura_Vector_3& GetTargetPosition() const					{ return m_xTargetPosition; }
 	void SetTargetPosition(const Asura_Vector_3& xTargetPosition)	{ m_xTargetPosition = xTargetPosition; }

private:
	Asura_Vector_3 m_xTargetPosition;
};


// Movement system itself
class AVP_Movement_System : public Asura_Movement_System
{
	typedef Asura_Movement_System PARENT;

public:
    AVP_Movement_System( AVP_ClientEntity_Actor& xOwner );

	virtual bool HandleMessage( const Asura_Message* pxMessage );

	AVP_ClientEntity_Actor& GetActorOwner( void ) { return m_xOwner; }
    const AVP_ClientEntity_Actor& GetActorOwner( void ) const { return m_xOwner; }
    virtual bool IsControlledByAnyPlayer( const Asura_Guid uGUID ) const;
    virtual bool IsControlledByLocalPlayer( const Asura_Guid uGUID ) const;

	void ExternalUpdateCurrentMove(const float fTimeStep);

protected:
    virtual void SendChainCompleteMessage(Asura_Hash_ID uFinalMoveID) const;

private:
    AVP_ClientEntity_Actor& m_xOwner;
};

#endif // #ifndef ___AVP_MOVEMENT_SYSTEM_H___
