/*!
	@project Rune
	@file RuFusion_Actor.h

	Copyright (c) 2004-2006 All rights reserved

	@author John Tang
	@date 2006/07/28
*/

#ifndef _RUFUSION_ACTOR_H_
#define _RUFUSION_ACTOR_H_

#include "../Scene/Base/RuSceneBase.h"
#include "../Fusion/RuFusion_Mime.h"
#include "../Fusion/RuFusion_Sojourner.h"

#pragma unmanaged

// ************************************************************************************************************************************************************

enum CRuFusion_ActorState
{
	// "Background" States
	ruFUSION_ACTORSTATE_NORMAL				= 0,
	ruFUSION_ACTORSTATE_JUMP				= 1,
	ruFUSION_ACTORSTATE_FALLING				= 2,
	ruFUSION_ACTORSTATE_SWIM_SURFACE		= 3,
	ruFUSION_ACTORSTATE_SWIM_DIVE			= 4,

	ruFUSION_ACTORSTATE_SIT_BEGIN			= 6,
	ruFUSION_ACTORSTATE_SIT_LOOP			= 7,
	ruFUSION_ACTORSTATE_SIT_END				= 8,

	ruFUSION_ACTORSTATE_SLEEP_BEGIN			= 9,
	ruFUSION_ACTORSTATE_SLEEP_LOOP			= 10,
	ruFUSION_ACTORSTATE_SLEEP_END			= 11,

	ruFUSION_ACTORSTATE_DYING				= 12,
	ruFUSION_ACTORSTATE_DEAD				= 13,
	ruFUSION_ACTORSTATE_REVIVING			= 14,

	// "Foreground" States
	ruFUSION_ACTORSTATE_COMBAT_1H			= 21,							//!< Idle 1H combat state
	ruFUSION_ACTORSTATE_COMBAT_2H			= 22,							//!< Idle 2H combat state
	ruFUSION_ACTORSTATE_COMBAT_BOW			= 23,							//!< Idle bow combat state
	ruFUSION_ACTORSTATE_COMBAT_GUN			= 24,							//!< Idle gun combat state
	ruFUSION_ACTORSTATE_COMBAT_POLEARM		= 25,							//!< Idle polearm combat state
	ruFUSION_ACTORSTATE_COMBAT_UNARMED		= 26,							//!< Idle unarmed combat state

	// "Transient" States
	ruFUSION_ACTORSTATE_ATTACK_1H			= 31,							//!< 1-handed strike
	ruFUSION_ACTORSTATE_ATTACK_2H			= 32,							//!< 2-handed strike
	ruFUSION_ACTORSTATE_ATTACK_BOW_BEGIN	= 33,
	ruFUSION_ACTORSTATE_ATTACK_BOW_LOOP		= 34,
	ruFUSION_ACTORSTATE_ATTACK_BOW_END		= 35,
	ruFUSION_ACTORSTATE_ATTACK_GUN_BEGIN	= 36,
	ruFUSION_ACTORSTATE_ATTACK_GUN_LOOP		= 37,
	ruFUSION_ACTORSTATE_ATTACK_GUN_END		= 38,
	ruFUSION_ACTORSTATE_ATTACK_OH			= 39,							//!< Offhand strike
	ruFUSION_ACTORSTATE_ATTACK_OH_PIERCE	= 40,							//!< Offhand piercing strike
	ruFUSION_ACTORSTATE_ATTACK_POLEARM		= 41,							//!< Polearm strike
	ruFUSION_ACTORSTATE_ATTACK_UNARMED		= 42,							//!< Unarmed strike

	ruFUSION_ACTORSTATE_BUFF_BEGIN			= 51,
	ruFUSION_ACTORSTATE_BUFF_LOOP			= 52,
	ruFUSION_ACTORSTATE_BUFF_END			= 53,
	ruFUSION_ACTORSTATE_BUFF_INSTANT		= 54,

	ruFUSION_ACTORSTATE_CAST_BEGIN			= 55,
	ruFUSION_ACTORSTATE_CAST_LOOP			= 56,
	ruFUSION_ACTORSTATE_CAST_END			= 57,
	ruFUSION_ACTORSTATE_CAST_INSTANT		= 58,

	ruFUSION_ACTORSTATE_CHANNEL_BEGIN		= 59,
	ruFUSION_ACTORSTATE_CHANNEL_LOOP		= 60,
	ruFUSION_ACTORSTATE_CHANNEL_END			= 61,
	ruFUSION_ACTORSTATE_CHANNEL_INSTANT		= 62,

	ruFUSION_ACTORSTATE_EMOTE_ANGRY			= 101,
	ruFUSION_ACTORSTATE_EMOTE_APPLAUSE		= 102,
	ruFUSION_ACTORSTATE_EMOTE_APPROVAL		= 103,
	ruFUSION_ACTORSTATE_EMOTE_BEG			= 104,
	ruFUSION_ACTORSTATE_EMOTE_CRY			= 105,
	ruFUSION_ACTORSTATE_EMOTE_HEAD_NOD		= 106,
	ruFUSION_ACTORSTATE_EMOTE_HEAD_SHAKE	= 107,
	ruFUSION_ACTORSTATE_EMOTE_LAUGH			= 108,
	ruFUSION_ACTORSTATE_EMOTE_POINT			= 109,
	ruFUSION_ACTORSTATE_EMOTE_PROVOKE		= 110,
	ruFUSION_ACTORSTATE_EMOTE_SALUTE		= 111,
	ruFUSION_ACTORSTATE_EMOTE_SPEAK			= 112,
	ruFUSION_ACTORSTATE_EMOTE_SURRENDER		= 113,
	ruFUSION_ACTORSTATE_EMOTE_THREATEN		= 114,
	ruFUSION_ACTORSTATE_EMOTE_VICTORY		= 115,
	ruFUSION_ACTORSTATE_EMOTE_WAVE			= 116,

	ruFUSION_ACTORSTATE_HOLSTER				= 121,
	ruFUSION_ACTORSTATE_UNHOLSTER			= 122,

	ruFUSION_ACTORSTATE_HOLSTER_2H			= 123,
	ruFUSION_ACTORSTATE_UNHOLSTER_2H		= 124,

	// "Auxiliary" States
	ruFUSION_ACTORSTATE_HURT				= 151,

	ruFUSION_ACTORSTATE_FORCE_DWORD		= 0x7FFFFFFF
};

// ************************************************************************************************************************************************************

class CRuFusion_Actor : public IRuObject
{
	ruRTTI_DECLARE
	ruHEAP_DECLARE
	ruCLASSGUID_DECLARE

protected:
	REAL								m_latentPeriod;

	CRuEntity*							m_targetEntity;					//!< Target entity
	CRuFusion_Mime*						m_targetMime;					//!< Target mime object

	CRuFusion_Sojourner*				m_sojourner;

	CRuMatrix4x4						m_refFrameBasis;

	// Current actor state
	CRuFusion_ActorState				m_actorState;					//!< Current state of the actor
	CRuFusion_ActorState				m_foregroundState;
	CRuFusion_ActorState				m_transientState;
	CRuVector3							m_currentForwardVector;
	CRuVector3							m_targetForwardVector;			//!< Forward direction vector

	// Settings
	REAL								m_rotationSpeed;				//!< hmmm....
	REAL								m_runThreshold;					//!< Threshold above which to begin using running animation

	CRuSegment3							m_swim_Surface_EntrySegment;	//!< Segment used for detecting entry into water
	CRuSegment3							m_swim_Surface_ExitSegment;		//!< Segment used for detecting exit from water
	CRuSegment3							m_swim_Dive_EntrySegment;		//!< Segment used for detecting entry into diving
	CRuSegment3							m_swim_Dive_ExitSegment;		//!< Segment used for detecting entry into diving

	// Movement data
	CRuVector3							m_inputVelocity;				//!< Current velocity due to user input (in canonical frame)
	CRuVector3							m_latentVelocity;				//!< Latent velocity (in local frame)
	REAL								m_gravitySpeed;					//!< Current speed contribution due to gravity

	REAL								m_targetBodyHeadingOffset;
	REAL								m_targetTorsoHeadingOffset;
	REAL								m_targetYawOffset;
	REAL								m_currentBodyHeadingOffset;
	REAL								m_currentTorsoHeadingOffset;
	REAL								m_currentYawOffset;

public:
										CRuFusion_Actor();
	virtual								~CRuFusion_Actor();

	CRuEntity*							GetTargetEntity();
	CRuFusion_Mime*						GetTargetMime();
	BOOL								SetTargetMime(CRuFusion_Mime *targetMime);

	CRuFusion_Sojourner*				GetSojourner();
	BOOL								SetCollisionObject(IRuObject *collisionObject);

	void								SetForwardVector(const CRuVector3 &forwardVector);
	void								SetRunThreshold(REAL runThreshold);
	void								Move(const CRuVector3 &impulse);
	BOOL								Jump(REAL risingImpulse);
	BOOL								ForcedJump(REAL risingImpulse, const CRuVector3 &latentVelocity);

	const CRuVector3&					GetLatentVelocity() const;

	CRuFusion_ActorState				GetBackgroundState();
	BOOL								SetBackgroundState(CRuFusion_ActorState actorState);
	CRuFusion_ActorState				GetForegroundState();
	BOOL								SetForegroundState(CRuFusion_ActorState actorState);
	CRuFusion_ActorState				GetTransientState();
	BOOL								SetTransientState(CRuFusion_ActorState actorState);

	void								Update(REAL elapsedTime);
};

// ************************************************************************************************************************************************************

#pragma managed

#endif
