#include "GameMain.h"
#include "../netwaker_member/NetWakerClientInc.h"
#include "../interface/Debug/DebugMessage.h"
#include "../Interface/WorldFrames/ItemClipboard.h"
#include "../Interface/WorldFrames/GameControl.h"
#include "../tools/CIni/Ini.h"

#define SEND_MOVE_DELAY_TIME		0.5f
#define MAX_CAMERA_THETA			0.15f
#define MIN_CAMERA_THETA			-0.93f
#define MAX_CAMERA_DISTANCE			500.0f
#define MIN_CAMERA_DISTANCE			10.0f

CGameMain						*g_pGameMain		= NULL;

int	LuaFunc_OnMouseDown		(lua_State* L);
int	LuaFunc_OnMouseUp		(lua_State* L);
int	LuaFunc_OnMouseWheel	(lua_State* L);
int	LuaFunc_OnMouseEnter	(lua_State* L);
int	LuaFunc_OnMouseLeave	(lua_State* L);

// ------------------------------------------------------------------------------------------------
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, INT iCmdShow)
{
	INT reuslt;
	g_pGameMain = new CGameMain;

	if ( g_pGameMain->RuneDevInitialize( hInstance, 1024, 768, TRUE) ) {
		reuslt = g_pGameMain->Run();
	}

	g_pGameMain->RuneDevRelease();
	delete g_pGameMain;
	return reuslt;
}

// --------------------------------------------------------------------------------------
void SpriteMessageProc(IBaseSprite* sprite, SpriteMessageType msg, int arg1, int arg2)
{
	switch (msg)
	{
	case eSpriteMsg_Position_Changed:
		break;
	case eSpriteMsg_HP_Changed:
		break;
	case eSpriteMsg_MaxHP_Changed:
		break;
	case eSpriteMsg_MP_Changed:
		break;
	case eSpriteMsg_MaxMP_Changed:
		break;
	case eSpriteMsg_SP_Changed:
		break;
	case eSpriteMsg_MaxSP_Changed:
		break;
	}
}

// --------------------------------------------------------------------------------------
CGameMain::CGameMain()
{
	m_ip.clear();
	m_port					= 0;

	m_playerID				= -1;
	m_DBID					= -1;
	m_zoneID				= -1;
	m_mapID					= -1;
	m_isEnterWorld			= false;	
	
	m_isLockFight			= false;
	m_pPlayer				= NULL;
	m_pTargetPlayer			= NULL;
	m_pMouseInPlayer		= NULL;
	m_sendMoveTime			= 0.0f;

	m_sendActorState.background	= ruFUSION_ACTORSTATE_NORMAL;
	m_sendActorState.foreground	= ruFUSION_ACTORSTATE_NORMAL;
	m_sendActorState.transient	= ruFUSION_ACTORSTATE_NORMAL;

	m_moveVector.Set(0.0f, 0.0f, 0.0f);
	m_direction.Set(0.0f, 0.0f, 0.0f);
	m_position.Set(0.0f, 0.0f, 0.0f);
	
};

// --------------------------------------------------------------------------------------
CGameMain::~CGameMain()
{	
}

// --------------------------------------------------------------------------------------
void CGameMain::Init()
{
	// Interface member create
	// InterfaceMemberInitial();

	// 載入INI設定
	LoadINI( "RuneDev.ini" );

	CNetGlobal::Initial( GetFullFilePath("Data\\") );

	// 設定游標圖形
	SetCursorIcon( CURSOR_NORMAL_POINT );

	/*
	// 註冊 Lua 函式
	CFrame::RegisterLuaObj();
    InterfaceMemberRegisterFunc();

	// 載入界面
	LoadInterface();
	*/

	IBaseSprite::SetSpriteMsgProc(SpriteMessageProc);

	// 載入界面
	if (m_interface)
	{
		m_interface->BuildFramesLogin(m_xScreen, m_yScreen);
		m_interface->BuildFramesWorld(m_xScreen, m_yScreen);
		m_interface->SetProcessType(CInterface::eIntreface_Process_Login);
	}
}

// --------------------------------------------------------------------------------------
void CGameMain::Release()
{
	// Interface member delete
	// InterfaceMemberRelease();

	CNetGlobal::Release();	
}

// --------------------------------------------------------------------------------------
void CGameMain::Update()
{
	// SleepEx( 1, true );
	CNetGlobal::Process( m_frameTime, m_elapsedTime );
	CRuneDev::Update();
	UpdateWorld();
}

// --------------------------------------------------------------------------------------
void CGameMain::SendCreateRoleSprite(CRoleSprite* pRoleSprite)
{
	CNetCli_Script::OnEvent_AddObj( pRoleSprite->GetIdentify() );
}

// --------------------------------------------------------------------------------------
void CGameMain::SendDeleteRoleSprite(CRoleSprite* pRoleSprite)
{
	if (pRoleSprite == m_pTargetPlayer)
		m_pTargetPlayer = NULL;
	if (pRoleSprite == m_pPlayer)
		m_pPlayer = NULL;
	if (pRoleSprite == m_pMouseInPlayer)
		m_pMouseInPlayer = NULL;

	CNetCli_Script::OnEvent_DelObj( pRoleSprite->GetIdentify() );

	/*	
	CWorldFrame::ReceiveRoleSpriteDelete( pRoleSprite );
	*/
}

// --------------------------------------------------------------------------------------
LRESULT	CGameMain::WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam )
{
	switch ( iMsg )
	{
	case WM_KEYDOWN:
		switch( wParam )
		{
		case VK_F1:
			m_interface->SetVisible(!m_interface->IsVisible());
			break;

		case VK_F2:
			m_interface->SetEnable(!m_interface->IsEnable());
			break;

		case VK_F3:
			g_pError->Show();
			break;

		case VK_F4:
			{
				CUiFrame* frame = (CUiFrame*)m_interface->GetUiWorld()->FindObject("DebugMessageFrame");
				if ( frame )
				{
					frame->SetVisible( !frame->IsVisible() );
				}
			}
			break;			

		case VK_F5:
			m_interface->BuildFramesWorld(m_xScreen, m_yScreen);
			break;

		case VK_F6:
			m_pRuTerrain->ToggleOption_RenderTerrain();
			break;

		case VK_F7:
			m_pRuTerrain->ToggleOption_RenderObjects();
			break;

		case VK_F8:
			m_pRuTerrain->ToggleOption_RenderGrass();
			break;

		case VK_F9:
			m_pRuTerrain->ToggleOption_RenderWater();
			break;
		}
		break;
	case WM_CLOSE:
		{
			WriteINI( "RuneDev.ini" );
		} break;
		
	}
	return CRuneDev::WndProc( hWnd, iMsg, wParam, lParam );
}
// --------------------------------------------------------------------------------------
void CGameMain::WriteINI( const char* fileName )
{
	//char tmp[MAX_PATH];
	char fullName[MAX_PATH];

	GetFullPathName( fileName, MAX_PATH, fullName, NULL );

	CIni ini(fullName);

	// Write ErrorList Pos to ini file

	RECT rect;
	if( GetWindowRect( CErrorList::GetHandle(), &rect ) )
	{
		int iX		= rect.left;
		int iY		= rect.top;
		int iWidth	= rect.right - rect.left;
		int iHeight	= rect.bottom - rect.top;

		ini.WriteInt("ErrorList", "PosX", iX );
		ini.WriteInt("ErrorList", "PosY", iY );
		ini.WriteInt("ErrorList", "Width", iWidth );
		ini.WriteInt("ErrorList", "Height", iHeight );
	}

}
// --------------------------------------------------------------------------------------
void CGameMain::LoadINI( const char* fileName )
{
	char tmp[MAX_PATH];
	char fullName[MAX_PATH];

	GetFullPathName( fileName, MAX_PATH, fullName, NULL );

	CIni ini(fullName);
	ini.GetString( "Path", "Resource", tmp, MAX_PATH, "Resource" );	

	// 設定資源目錄
	SetResourcePath(tmp);
	
	// 設定IP address
	ini.GetString("Server", "IP", tmp, MAX_PATH, "");
	SetIP( tmp );

	// 設定IP port
	ini.GetString("Server", "Port", tmp, MAX_PATH, "");
	SetPort( atoi(tmp) );

	// Set ErrorList Pos

	int iX		= ini.GetInt("ErrorList", "PosX", 0 );
	int iY		= ini.GetInt("ErrorList", "PosY", 0 );
	int iWidth	= ini.GetInt("ErrorList", "Width", 500 );
	int iHeight	= ini.GetInt("ErrorList", "Height", 500 );
	
	if( g_pError ) 
	{
		SetWindowPos( CErrorList::GetHandle(), HWND_NOTOPMOST, iX, iY, iWidth, iHeight, 0 );
	}
	
#ifdef _AUTOLOGIN
	CNetCli_Login::m_bAutoLogin = (ini.GetInt( "Login", "AutoLogin", 0 )) ? true : false;
	
	ini.GetString( "Login", "ID", CNetCli_Login::m_szAutoLogingID, 32, "" );
	ini.GetString( "Login", "PW", CNetCli_Login::m_szAutoLogingPW, 32, "" );
	
	CNetCli_Login::m_iAutoLoginRoleID = ini.GetInt( "Login", "RoleID", 0 );

	if( CNetCli_Login::m_bAutoLogin == 1 )
		CNetCli_Login::Login( GetIP(), GetPort(), CNetCli_Login::m_szAutoLogingID, CNetCli_Login::m_szAutoLogingPW );	

#endif
	
}

// --------------------------------------------------------------------------------------
void CGameMain::SetPlayerID(int playerID)
{
	m_playerID = playerID;
	IBaseSprite::SetMainPlayerId( m_playerID );
}

// --------------------------------------------------------------------------------------
void CGameMain::SetPlayerPos(CRuVector3& pos)
{
	if ( m_pPlayer )
	{
		m_pPlayer->SetServerPos(pos);
		m_pPlayer->SetPos(pos);

		m_moveVector	= m_pPlayer->GetMoveVector();
		m_direction		= m_pPlayer->GetDirection();
		m_position		= m_pPlayer->GetPos();
	}
}

// --------------------------------------------------------------------------------------
void CGameMain::SetZoneID(int zoneID)
{
	if ( m_zoneID != zoneID )
	{
		m_zoneID = zoneID;
	}
}

// --------------------------------------------------------------------------------------
void CGameMain::SetMapID(int mapID)
{
	if (m_mapID != mapID)
	{
		m_mapID = mapID;		
	}
}

// --------------------------------------------------------------------------------------
void CGameMain::SetTargetPlayer(CRoleSprite* target)
{	
	if( m_pTargetPlayer != target )
	{
		m_pTargetPlayer = target;
		GetInterface()->GetUi()->SendEvent( UiEvent_TargetChange );
	}
}

// --------------------------------------------------------------------------------------
void CGameMain::EnterWorld(int DBID, const char* playerName)
{
	m_DBID				= DBID;
	m_isEnterWorld		= true;
	m_playerName		= playerName;

	m_interface->SetPlayerName( playerName );
	m_interface->SetProcessType(CInterface::eIntreface_Process_World);

	// 載入地表
	LoadTerrain("world.wdb");

	m_interface->GetUiWorld()->SendEvent( UiEvent_EnterWorld );
}

// --------------------------------------------------------------------------------------
void CGameMain::LeaveWorld()
{
	m_DBID				= -1;
	m_playerID			= -1;
	m_zoneID			= -1;
	m_mapID				= -1;	
	m_isEnterWorld		= false;	
	m_isLockFight		= false;
	m_pPlayer			= NULL;
	m_pTargetPlayer		= NULL;
	m_pMouseInPlayer	= NULL;

	m_interface->SetPlayerName("");
	m_interface->SetProcessType(CInterface::eIntreface_Process_Login);
}

// --------------------------------------------------------------------------------------
float CGameMain::GetDistanceWithPlayer(CRoleSprite* sprite)
{
	if ( sprite == NULL || m_pPlayer == NULL )
		return 100000.0f;

	CRuVector3 dis = m_pPlayer->GetPos() - sprite->GetPos();
	return dis.Magnitude();
}

// --------------------------------------------------------------------------------------
void CGameMain::LockFight()
{
	m_isLockFight = true;
	EnterFightMode();
	m_interface->GetUiWorld()->SendEvent(UiEvent_PlayerEnterFight);
}

// --------------------------------------------------------------------------------------
void CGameMain::UnlockFight()
{	
	m_isLockFight = false;
	LeaveFightMode();
	m_interface->GetUiWorld()->SendEvent(UiEvent_PlayerLeaveFight);
}

// --------------------------------------------------------------------------------------
void CGameMain::UpdateWorld()
{
	if (!IsEnterWorld())
		return;

	// 初始化角色物件
	if (m_pPlayer == NULL)
	{
		m_pPlayer = g_pGameMain->FindRoleSprite(m_playerID);

		if ( m_pPlayer )
		{
			// 暫時填入 MP 和 SP
			RoleDataEx* pRole = CNetGlobal::RoleData();
			m_pPlayer->SetMP	( pRole->BaseData.MP );
			m_pPlayer->SetMaxMP	( (int)pRole->TempData.Attr.Fin.MaxMP );
		}

		// 設定攝影機位置
		if (m_pCamera)
		{
			if ( m_pPlayer )
			{
				m_pCamera->SetCameraPosition( CRuVector3(0.0f, 0.0f, 0.0f) );		// 鏡頭所在位置
				m_pCamera->SetTargetPosition( m_pPlayer->GetDirection() * 50 );		// 鏡頭目的位置
				m_pCamera->SetCameraUpVector( CRuVector3(0.0f, 1.0f, 0.0f) );		// 鏡頭上方所朝方向
			}
			else
			{
				m_pCamera->SetCameraPosition( CRuVector3(0.0f, 0.0f, 50.0f) );		// 鏡頭所在位置
				m_pCamera->SetTargetPosition( CRuVector3(0.0f, 0.0f, 0.0f) );		// 鏡頭目的位置
				m_pCamera->SetCameraUpVector( CRuVector3(0.0f, 1.0f, 0.0f) );		// 鏡頭上方所朝方向
			}
		}
	}
	
	if (m_pPlayer)
		SetPlayerAnchor( m_pPlayer->GetPos() );

	/*
	// 記算按鍵按下時間
	if ( m_mouseState & CUiFrame::eMouse_Flag_LButton )
		m_buttonPress[0] += m_elapsedTime;
	else
		m_buttonPress[0] = 0.0f;

	if ( m_mouseState & CUiFrame::eMouse_Flag_RButton )
		m_buttonPress[1] += m_elapsedTime;
	else
		m_buttonPress[1] = 0.0f;
	*/

	CUi* ui = m_interface->GetUiWorld();
	CRoleSprite* focusPlayer = NULL;
	if (ui)
	{
		if (ui->GetMouseOver() == g_pGameControl->GetWorldFrame())
			focusPlayer = GetTopRoleSprite(m_xCursor, m_yCursor, m_playerID);
	}

	if ( m_pMouseInPlayer != focusPlayer )
	{
		m_pMouseInPlayer = focusPlayer;

		lua_State* L = ui->GetLuaState();
		const char* name = NULL;
		int id = 0;

		if ( m_pMouseInPlayer )
		{
			name = m_pMouseInPlayer->GetName();
			id = m_pMouseInPlayer->GetIdentify();
		}
		lua_pushstring(L, name);
		lua_setglobal(L, "arg1");
		lua_pushnumber(L, id);
		lua_setglobal(L, "arg2");
		
		ui->SendEvent("UPDATE_MOUSEOVER_UNIT");
	}	

	// 游標選到物件閃爍
	SetHighlightSprite(m_pMouseInPlayer);

	// 事件檢測
	CheckTargetStatus();

	// 改變游標狀態
	ChangeCursor();	

	// 檢測是否需要送出移動封包
	SendPlayerPos();

	// 檢測角色動作
	SendPlayerActor();

	// 鏡頭控制
	ControlCamera();
}

// --------------------------------------------------------------------------------------
void CGameMain::SendPlayerPos()
{
	if ( m_pPlayer == NULL )
		return;

	bool isSend = false;
	m_sendMoveTime += m_elapsedTime;
	CRuVector3 vec = m_pPlayer->GetMoveVector();
	CRuVector3 dir = m_pPlayer->GetDirection();
	CRuVector3 pos = m_pPlayer->GetPos();	
	ClientMoveTypeENUM moveType = EM_ClientMoveType_Normal;	

	if ( m_pPlayer->GetActorState() == ruFUSION_ACTORSTATE_JUMP )
	{
		moveType = EM_ClientMoveType_Jump;
		if ( m_sendMoveTime > SEND_MOVE_DELAY_TIME )
		{			
			isSend = true;
			vec = m_pPlayer->GetLatentVelocity();
		}
	}
	else if ( m_jumpState )
	{
		isSend = true;
		m_jumpState = false;
	}
	else
	{
		// 當面向改變時,每隔 SEND_MOVE_DELAY_TIME 時間送出封包
		if ( dir != m_direction && m_sendMoveTime > SEND_MOVE_DELAY_TIME )
			isSend = true;
		// 當向量與方向改變時
		if ( !isSend && vec != m_moveVector )
			isSend = true;
		// 當固定朝向某個方向移動時，間隔2秒更新封包一次
		if ( !isSend && m_sendMoveTime > 2.0f )
		{
			if ( pos.m_x != m_position.m_x || pos.m_z != m_position.m_z || abs(m_position.m_y - pos.m_y) > 1.0f )
				isSend = true;
		}
	}

	// 當玩不停改變移動方向時，減少封包傳遞次數
	if ( isSend )
	{
		static int packageCount = 0;	// 記錄短時間傳遞移動封包個數

		// 檢查是否封包傳遞間隔太短，若時間間隔太短累計封包個數
		if ( m_sendMoveTime > SEND_MOVE_DELAY_TIME )
		{
			if ( packageCount > 0 )
				packageCount--;
		}		
		else if ( packageCount < 5 )
			packageCount++;
		else
			isSend = false;
	}	

	if ( isSend )
	{
		CRuQuaternion quaternion;
		m_moveVector	= vec;
		m_direction		= dir;
		m_position		= pos;
		m_sendMoveTime	= 0.0f;

		switch ( moveType )
		{
		case EM_ClientMoveType_Normal:
			// 轉換為角色朝向目標向量
			quaternion.RotateIntoVector(dir, CRuVector3(0.0f, 0.0f, 1.0f));
			quaternion.TransformVector(vec);
			break;

		case EM_ClientMoveType_Jump:
			// 將目標向量轉換為角色Z軸向量
			quaternion.RotateIntoVector(CRuVector3(0.0f, 0.0f, 1.0f), dir);
			quaternion.TransformVector(m_moveVector);
			break;
		}

		// 取得角色所朝方向
		float theta = acos( dir.Dot( CRuVector3(1.0f, 0.0f, 0.0f) ) );
		if ( dir.m_z > 0.0f )
			theta = PI + PI - theta;

		// 轉換為角度
		theta = theta * 180.0f / PI;
		
		Net_Move::PlayerMoveObject(m_playerID, pos.m_x, pos.m_y, pos.m_z, theta, vec.m_x, vec.m_z, moveType);
		// g_pDebugMessage->DebugOutput(0, "(%.2f %.2f %.2f) (%.2f, %.2f)", pos.m_x, pos.m_y, pos.m_z, vec.m_x, vec.m_z);
	}
}

// --------------------------------------------------------------------------------------
void CGameMain::SendPlayerActor()
{
	if ( m_pPlayer )
	{
		bool isSendActor = false;
		PLAYER_ACTOR_STATE state;
		state.background	= m_pPlayer->GetActorState(1);
		state.foreground	= m_pPlayer->GetActorState(2);
		state.transient		= m_pPlayer->GetActorState(3);
		
		// 某些情況需要排除封包傳遞
		switch ( state.background )
		{
		case ruFUSION_ACTORSTATE_SIT_BEGIN:
		case ruFUSION_ACTORSTATE_SIT_LOOP:
		case ruFUSION_ACTORSTATE_SIT_END:
		case ruFUSION_ACTORSTATE_SLEEP_BEGIN:
		case ruFUSION_ACTORSTATE_SLEEP_LOOP:
		case ruFUSION_ACTORSTATE_SLEEP_END:
		case ruFUSION_ACTORSTATE_DYING:
		case ruFUSION_ACTORSTATE_DEAD:
		case ruFUSION_ACTORSTATE_REVIVING:
			if ( m_sendActorState.background != state.background )
				isSendActor = true;
			break;
		}

		switch ( state.transient )
		{
		case ruFUSION_ACTORSTATE_EMOTE_ANGRY:
		case ruFUSION_ACTORSTATE_EMOTE_APPLAUSE:
		case ruFUSION_ACTORSTATE_EMOTE_APPROVAL:
		case ruFUSION_ACTORSTATE_EMOTE_BEG:
		case ruFUSION_ACTORSTATE_EMOTE_CRY:
		case ruFUSION_ACTORSTATE_EMOTE_HEAD_NOD:
		case ruFUSION_ACTORSTATE_EMOTE_HEAD_SHAKE:
		case ruFUSION_ACTORSTATE_EMOTE_LAUGH:
		case ruFUSION_ACTORSTATE_EMOTE_POINT:
		case ruFUSION_ACTORSTATE_EMOTE_PROVOKE:
		case ruFUSION_ACTORSTATE_EMOTE_SALUTE:
		case ruFUSION_ACTORSTATE_EMOTE_SPEAK:
		case ruFUSION_ACTORSTATE_EMOTE_SURRENDER:
		case ruFUSION_ACTORSTATE_EMOTE_THREATEN:
		case ruFUSION_ACTORSTATE_EMOTE_VICTORY:
		case ruFUSION_ACTORSTATE_EMOTE_WAVE:
		case ruFUSION_ACTORSTATE_HOLSTER:
		case ruFUSION_ACTORSTATE_UNHOLSTER:
		case ruFUSION_ACTORSTATE_HOLSTER_2H:
		case ruFUSION_ACTORSTATE_UNHOLSTER_2H:
			if ( m_sendActorState.transient != state.transient )
				isSendActor = true;
			break;
		}

		if ( isSendActor )
		{
			m_sendActorState = state;
			Net_Move::S_DoAction(m_playerID, 0, m_sendActorState.value);
		}
	}
}

// --------------------------------------------------------------------------------------
void CGameMain::CheckTargetStatus()
{	
	/*
	// 檢查事件觸發
	if ( m_isTouchQuest )
	{
		m_isTouchQuest = false;

		if ( m_pTargetPlayer && m_pPlayer )
		{
			CRuVector3 dir = m_pTargetPlayer->GetPos() - m_pPlayer->GetPos();

			// 判別可對目標物執行動作
			switch ( m_pTargetPlayer->GetCheckedStatus() )
			{
			case eChecked_TouchPlot:
			case eChecked_QuestNPC:
			case eChecked_QuestObj:
				// 判斷距離
				{
					float fRange = dir.Magnitude();
					if ( fRange > 25.0f )
					{						
						if ( g_pUIOptionsFrame->m_isHitMove )
						{
						MoveToPlayer( m_pTargetPlayer );
						m_isTouchQuest = true;
						}
						else
						
						g_pDebugMessage->DebugOutput(2, "距離過遠,無法觸發事件");
					}
					else
					{
						if ( g_pUIOptionsFrame->m_isAutoFaceToFace )
						m_pPlayer->SetDirection( m_pTargetPlayer->GetPos() - m_pPlayer->GetPos() );
						
						switch ( m_pTargetPlayer->GetCheckedStatus() )
						{

						case eChecked_QuestNPC:
							CNetCli_Script::OnEvent_TouchQuestNPC( m_pTargetPlayer->GetIdentify() );
							break;

						case eChecked_TouchPlot:
							CNetCli_Script::OnEvent_TouchPlot( m_pTargetPlayer->GetIdentify() );
							break;

						case eChecked_QuestObj:
							CNetCli_Script::OnEvent_TouchQuestObj( m_pTargetPlayer->GetIdentify() );
							break;
						}
					}
				}
				break;
			}
		}
	}

	// 檢查攻擊觸發
	if ( m_isAttack )
	{
		m_isAttack = false;

		if ( m_pTargetPlayer && m_pPlayer )
		{
			CRuVector3 dir = m_pTargetPlayer->GetPos() - m_pPlayer->GetPos();

			switch (m_pTargetPlayer->GetCheckedStatus())
			{
				// 判斷距離
			case eChecked_Fight:
				// 判斷距離
				if ( dir.Magnitude() > 20.0f )
				{					
					if ( g_pUIOptionsFrame->m_isHitMove )
					{
					m_isAttack = true;
					MoveToPlayer( m_pTargetPlayer );
					}
				}
				else
					m_pPlayer->ClearPathMove();

				break;
			}
		}
	}
	*/

	if ( m_pPlayer )
	{
		if ( m_pPlayer->GetCombatState() && m_pTargetPlayer == NULL )
			CancelAttack();
	}
}

// --------------------------------------------------------------------------------------
void CGameMain::ChangeCursor()
{	
	if (g_pItemClipboard->GetType() != CItemClipboard::eItem_Type_None)
	{
		SetCursorIcon(CURSOR_DRAG_ITEM);
		SetDragCursorIcon(g_pItemClipboard->GetFile());
	}
	else
	{
		SetCursorIcon(CURSOR_NORMAL_POINT);
		ClearDragCursorIcon();

		if ( m_pMouseInPlayer )
		{
			switch ( m_pMouseInPlayer->GetCheckedStatus() )
			{
			case eChecked_Fight:
				SetCursorIcon(CURSOR_ATTACK);
				break;

			case eChecked_TouchPlot:
			case eChecked_QuestObj:
				SetCursorIcon(CURSOR_QUEST_POINT);
				break;

			case eChecked_QuestNPC:
				SetCursorIcon(CURSOR_QUEST_SPEAK);
				break;
			}
		}
	}
}

// --------------------------------------------------------------------------------------
void CGameMain::ControlCamera()
{
	if (m_pCamera == NULL) 
		return;

	// 鏡頭跟隨角色移動
	if ( m_pPlayer )
	{		
		CRuVector3 relativeCamPos = m_pCamera->GetCameraPosition() - m_pCamera->GetTargetPosition();
		CRuVector3 absoluteCamPos = relativeCamPos + m_pPlayer->GetPos();
		m_pCamera->SetTargetPosition( m_pPlayer->GetPos() + CRuVector3(0.0f, 16.0f, 0.0f) );
		m_pCamera->SetCameraPosition( absoluteCamPos + CRuVector3(0.0f, 16.0f, 0.0f) );
		m_pCamera->SetCameraUpVector( CRuVector3(0.0f, 1.0f, 0.0f) );
	}
}

// --------------------------------------------------------------------------------------
void CGameMain::CancelAttack()
{
	m_isAttack = false;
	NetCli_Attack::S_EndAttackSignal();

	if ( !IsLockFight() )
		LeaveFightMode();
}

// --------------------------------------------------------------------------------------
void CGameMain::EnterFightMode()
{
	if ( m_pPlayer && !m_pPlayer->GetCombatState() )
		m_pPlayer->SetCombatState(true);
}

// --------------------------------------------------------------------------------------
void CGameMain::LeaveFightMode()
{
	if ( m_pPlayer && m_pPlayer->GetCombatState() )
		m_pPlayer->SetCombatState(false);
}

// --------------------------------------------------------------------------------------
void CGameMain::SetPlayerAction( int action )
{
	/*
	if ( m_pPlayer && SUCCEEDED( m_pPlayer->SetAction(action) ) )
	{
		switch ( action )
		{
		case eAction_Idle:
		case eAction_Fight_Idle:
		case eAction_Sit:
		case eAction_StandUp:
		case eAction_Sleep:
		case eAction_Holster:
		case eAction_Unholster:
			SendDoAction( action, m_pPlayer->GetStateFlag() );
			break;
		}
	}
	*/
}

// --------------------------------------------------------------------------------------
void CGameMain::Fight()
{
	EnterFightMode();

	if ( m_pTargetPlayer )
	{
		NetCli_Attack::S_AttackSignal( m_pTargetPlayer->GetIdentify() );
	}
}

// --------------------------------------------------------------------------------------
void CGameMain::Jump()
{
	if ( m_pPlayer == NULL || !m_pPlayer->Jump() )
		return;	
	
	CRuVector3 pos = m_pPlayer->GetPos();
	CRuVector3 dir = m_pPlayer->GetDirection();
	CRuVector3 vec = m_pPlayer->GetLatentVelocity();

	m_jumpState		= true;
	m_moveVector	= vec;
	m_direction		= dir;
	m_position		= pos;
	m_sendMoveTime	= 0.0f;

	// 將目標向量轉換為角色Z軸向量
	CRuQuaternion quaternion;
	quaternion.RotateIntoVector(CRuVector3(0.0f, 0.0f, 1.0f), dir);
	quaternion.TransformVector(m_moveVector);

	// 取得角色所朝方向
	float theta = acos( dir.Dot( CRuVector3(1.0f, 0.0f, 0.0f) ) );
	if ( dir.m_z > 0.0f )
		theta = PI + PI - theta;

	// 轉換為角度
	theta = theta * 180.0f / PI;
	Net_Move::S_JumpBegin(m_playerID, pos.m_x, pos.m_y, pos.m_z, theta, vec.m_x, vec.m_y, vec.m_z);
	// g_pDebugMessage->DebugOutput(0, "Jump (%.2f %.2f %.2f) (%.2f, %.2f,%.2f)", pos.m_x, pos.m_y, pos.m_z, vec.m_x, vec.m_y, vec.m_z);
}

// --------------------------------------------------------------------------------------
void CGameMain::SendDoAction( int action, int status )
{
	RoleSpriteStatus Temp;
	Temp.flag = status;
	Temp.action = action;

	switch ( action )
	{
	case eAction_Sit:
	case eMotion_Sit_Idle:
		Temp.isSit = true;
		break;
	}

	Net_Move::S_DoAction( m_playerID, Temp.flag , 0 );
}

/*
// --------------------------------------------------------------------------------------
void CGameMain::MoveToScreenPoint(int x, int y)
{
	if (m_pPlayer == NULL || m_pPlayer->IsDead())
		return;

	CRuVector3 tarPt;
	if (g_pGameMain->ChangeScreenPoint(x, y, tarPt))
	{
		//m_pMoveTarget->SetPos(tarPt);
		//m_pMoveTarget->Show();

		m_pPlayer->SetDirection(tarPt - m_pPlayer->GetPos());
		m_pPlayer->PathMove(tarPt);
	}
}

// --------------------------------------------------------------------------------------
void CGameMain::MoveToPlayer(CRoleSprite* pPlayer)
{
	static CRoleSprite* pLastPlayer = NULL;
	static float lastMoveTime = 0.0f;

	if (m_pPlayer == NULL || m_pPlayer->IsDead() || pPlayer == m_pPlayer)
		return;

	float time = g_pGameMain->GetFrameTime();
	if ( pLastPlayer != pPlayer || time - lastMoveTime > 0.5f )
	{
		CRuVector3 pos;
		m_pPlayer->SetDirection(pPlayer->GetPos() - m_pPlayer->GetPos());
		m_pPlayer->PathMove(pPlayer->GetPos());

		lastMoveTime = time;
	}
	pLastPlayer = pPlayer;	
}
*/