#include "../mainproc/GameMain.h"
#include "../net_party/NetCli_PartyChild.h"
#include "../../Interface/Debug/DebugMessage.h"
#include "NetCli_MoveChild.h"

//-----------------------------------------------------------------------------
bool NetCli_MoveChild::_Init()
{
	if (This)
		return false;

	This = new NetCli_MoveChild;
	return Net_Move::_Init();
}

//-----------------------------------------------------------------------------
bool NetCli_MoveChild::_Release()
{
	Net_Move::_Release();

	if (This)
	{
		delete This;
		This = NULL;
	}
	return true;
}

//-----------------------------------------------------------------------------
void NetCli_MoveChild::AddToPartition( int GItemID , int LGItemID , int DBID , RolePosStruct* Pos , PlayerGraphStruct* GraphObj )
{
	g_pDebugMessage->DebugOutput( 2, "AddToPartition GItemID(%d) LGItemID(%d) Name(%s) LV(%d) MaxHP(%d)", GItemID, LGItemID , GraphObj->Name.Begin() , GraphObj->Level , GraphObj->MaxHP);
	CRoleSprite* pSprite = g_pGameMain->CreateRoleSprite( GItemID, LGItemID );
	if ( pSprite )
	{		
		CRuVector3 pos(Pos->X, Pos->Y, Pos->Z);
		float angle = Pos->Dir * PI / 180.0f;

		pSprite->ClearFade();

		pSprite->SetObjectId(GraphObj->OrgObjID);
		pSprite->SetName(GraphObj->Name.Begin());
		pSprite->SetMaxHP(GraphObj->MaxHP);
		pSprite->SetHP(GraphObj->HP);
		pSprite->SetMaxMP(GraphObj->MaxMP);
		pSprite->SetMP(GraphObj->MP);
		pSprite->SetMaxSP(GraphObj->MaxSP);
		pSprite->SetSP(GraphObj->SP);

		pSprite->SetLevel(GraphObj->Level);
		pSprite->SetMoveSpeed(GraphObj->MoveSpeed);
		pSprite->SetModelRate(GraphObj->ModelRate);
		pSprite->SetDirection(CRuVector3(cos( angle ), 0.0f, -sin( angle )));
		pSprite->AdjustSlefPos( pos );
		pSprite->Scale( GraphObj->ModelRate );
		pSprite->SetQuestInfo( GraphObj->NpcQuestID, GraphObj->TouchPlot_Range, GraphObj->RangePlot_Range );

		// 死亡
		if ( GraphObj->Action.Dead )
		{
		}

		// 戰鬥
		if ( GraphObj->Action.AttackMode )
		{
		}

		// 判斷物件行為. 原則是, 一個物件同時應該只能有一種行為. 要是有兩種以上, 那就代表資料設定錯誤
		//-------------------------------------------------------------------------------
		int	iSetCount = 0;

		// 判斷是否是可戰鬥的角色
		if ( GraphObj->Mode.Fight )
		{
			pSprite->SetCheckedStatus( eChecked_Fight );
			iSetCount++;
		}

		// 給予任務 NPC 或 任務 Obj
		//if( GraphObj->NpcQuestID != 0 )
		int iQuestNpcBeginID	= Def_ObjectClass_QuestNPC;
		int iQuestNpcEndID		= Def_ObjectClass_QuestNPC + Def_ObjectClass_QuestNPC_Total;
		if( GraphObj->OrgObjID >= iQuestNpcBeginID && GraphObj->OrgObjID < iQuestNpcEndID )
		{
			// 取得 QuestNpc 物件
			GameObjectNpcStruct			*pNPC	= NULL;
			GameObjDbStructEx			*pObj	= g_ObjectData->GetObj( GraphObj->OrgObjID );
			
			if( pObj )
				pNPC	= &( g_ObjectData->GetObj( GraphObj->OrgObjID )->NPC );

			if( pNPC && pNPC->iQuestMode == 0 )
			{
				pSprite->SetCheckedStatus( eChecked_QuestNPC );		
			}
			else
			{
				pSprite->SetCheckedStatus( eChecked_QuestObj );
			}

			iSetCount++;
		}

		// 觸碰觸發劇情 OBJ
		if ( GraphObj->TouchPlot_Range != 0 )
		{
			pSprite->SetCheckedStatus( eChecked_TouchPlot );
			iSetCount++;
		}

		// 距離觸發劇情 OBJ
		if ( GraphObj->RangePlot_Range != 0 )
		{
			pSprite->SetCheckedStatus( eChecked_RangePlot );
			iSetCount++;
		}

		if( iSetCount > 1 )
		{
			// POP Message AddToPartition 有兩個以上的行為設定.
			g_pDebugMessage->DebugOutput(0, "AddToPartition  GItemID(%d) LGItemID(%d) Obj 有兩個以上的行為設定", GItemID, LGItemID);
		}
		//-------------------------------------------------------------------------------
		ActionType( GItemID , GraphObj->Action );
	}
	
}

//-----------------------------------------------------------------------------
void NetCli_MoveChild::DelFromPartition( int GItemID  )
{
	g_pDebugMessage->DebugOutput( 2, "DelFromPartition GItemID(%d)", GItemID );
	CRoleSprite* pSprite = g_pGameMain->FindRoleSprite( GItemID );
	if ( pSprite )
		pSprite->SetFade( true, 2.0f );
	g_pGameMain->DeleteRoleSprite( GItemID );
}

//-----------------------------------------------------------------------------
void NetCli_MoveChild::SetPos( int GItemID  , RolePosStruct* Pos )
{
	CRoleSprite* pSprite = g_pGameMain->FindRoleSprite( GItemID );	
	if ( pSprite )
	{	
		CRuVector3 pos(Pos->X, Pos->Y, Pos->Z);
		float angle = Pos->Dir * PI / 180.0f;

		pSprite->SetServerPos( pos );
		pSprite->SetPos( pos );
		pSprite->SetDirection(CRuVector3(cos(angle), 0.0f, -sin(angle)));

		if ( GItemID == g_pGameMain->GetPlayerID() )
			g_pGameMain->SetPlayerPos( pos );
	}
	else
		g_pDebugMessage->DebugOutput( 0, "[SetPos] Can't Find then GItemID(%d)", GItemID );
}

//-----------------------------------------------------------------------------
void NetCli_MoveChild::ObjectMove( int GItemID  , RolePosStruct* Pos , float vX , float vZ , ClientMoveTypeENUM Type  )
{
	CRoleSprite* pSprite = g_pGameMain->FindRoleSprite( GItemID );
	if ( pSprite )
	{
		float angle = Pos->Dir * PI / 180.0f;
		CRuVector3 tarPos(Pos->X, Pos->Y, Pos->Z);
		CRuVector3 moveVector = tarPos - pSprite->GetPos();		// 取得座標點差距
		moveVector.m_y = 0;

		pSprite->SetServerPos(tarPos);
		switch (pSprite->GetObjectType())
		{
		case eSpriteObject_Unknown:
			break;

		case eSpriteObject_Player:			
			pSprite->SetDirection(CRuVector3(cos(angle), 0.0f, -sin(angle)));

			// 若差距過大則做座標點修正
			if ( moveVector.Magnitude() > 5.0f )
				pSprite->SetPos(tarPos);

			if ( Type == EM_ClientMoveType_Normal )
			{
				// 結束移動
				if ( vX == 0.0f && vZ == 0.0f )
				{
					pSprite->SetMoveVector(CRuVector3(0.0f, 0.0f, 0.0f));			// 停止移動向量
				}
				// 向量移動
				else
				{
					CRuVector3 moveVector(vX, 0.0f, vZ);					
					
					// 將目標向量轉換為角色Z軸向量
					CRuQuaternion quaternion;
					quaternion.RotateIntoVector(CRuVector3(0.0f, 0.0f, 1.0f), pSprite->GetDirection());
					quaternion.TransformVector(moveVector);

					pSprite->SetMoveVector(moveVector, 2.0f);			// 角色朝目標移動兩秒
				}
				//g_pDebugMessage->DebugOutput(1, "(%.2f %.2f %.2f) (%.2f, %.2f) angle %.2f", tarPos.m_x, tarPos.m_y, tarPos.m_z, vX, vZ, Pos->Dir);
				break;
			}

		case eSpriteObject_NPC:
		case eSpriteObject_QuestNPC:
			pSprite->SetTargetPos(tarPos);
			break;

		case eSpriteObject_Effect:
			pSprite->SetDirection(CRuVector3(cos(angle), 0.0f, -sin(angle)));
			break;
		}
		// g_pDebugMessage->DebugOutput(1, "(%.2f %.2f %.2f) (%.2f, %.2f) angle %.2f", tarPos.m_x, tarPos.m_y, tarPos.m_z, vX, vZ, Pos->Dir);
	}
	else
		g_pDebugMessage->DebugOutput( 0, "[ObjectMove] Can't Find then GItemID(%d)", GItemID );
}

//-----------------------------------------------------------------------------
void NetCli_MoveChild::DoAction( int GItemID  , int ActionID , int TempActionID )
{
	CRoleSprite* pSprite = g_pGameMain->FindRoleSprite( GItemID );
	if ( pSprite )
	{
		PLAYER_ACTOR_STATE state;
		state.value = TempActionID;

		if ( state.background != ruFUSION_ACTORSTATE_NORMAL )
			pSprite->SetActorState((CRuFusion_ActorState)state.background, 1);

		if ( state.transient != ruFUSION_ACTORSTATE_NORMAL )
			pSprite->SetActorState((CRuFusion_ActorState)state.background, 3);

		/*
		if ( ActionID ) 
		{
			pSprite->Motion(TempActionID);
		}
		else
		{
			RoleSpriteStatus status;
			status.flag = ActionID ;
			int action = status.action;

			pSprite->SetFight( status.isFight );
			pSprite->SetWalk( status.isWalk );
			pSprite->SetWeaponPosition( status.isUnholster );		

			switch ( action )
			{
			case eAction_Sit:
			case eAction_Sleep:
				if ( pSprite->IsMove() )
					pSprite->SetAction( action );
				else
				{
					SpriteEventInfo event;
					event.func = CRoleSprite::DelayAction;
					event.nowTime = 0.5f;
					event.userData[0] = action;
					pSprite->PushEvent( -2, event );
				}
				break;

			default:
				if ( action != eAction_Null )
					pSprite->SetAction( action );
				break;
			}
		}
		*/
	}
	else
		g_pDebugMessage->DebugOutput(0, "[DoAction] Can't Find then GItemID(%d)", GItemID);
}

//-----------------------------------------------------------------------------
void NetCli_MoveChild::MoveSpeed( int GItemID  , float Speed )
{
	CRoleSprite* pSprite = g_pGameMain->FindRoleSprite( GItemID );
	if ( pSprite )
	{
		pSprite->SetMoveSpeed(Speed);
	}
	else
		g_pDebugMessage->DebugOutput(0, "[MoveSpeed] Can't Find then GItemID(%d)", GItemID);
}

//-----------------------------------------------------------------------------
void NetCli_MoveChild::ModelRate( int GItemID  , float ModelRate )
{
	CRoleSprite* pSprite = g_pGameMain->FindRoleSprite( GItemID );
	if ( pSprite )
	{
		pSprite->Scale( ModelRate );
	}
	else
		g_pDebugMessage->DebugOutput( 0, "[ModelRate] Can't Find then GItemID(%d)", GItemID );
}

//-----------------------------------------------------------------------------
void NetCli_MoveChild::EQInfo( int GItemID , LookEQInfoStruct&    EQLook )
{
	CRoleSprite* pSprite = g_pGameMain->FindRoleSprite( GItemID );
	if ( pSprite )
	{
		bool isChange = false;
		pSprite->SetPaperdollId( ePaperdoll_Helmet, EQLook.Head );
		pSprite->SetPaperdollId( ePaperdoll_Hand, EQLook.Gloves );
		pSprite->SetPaperdollId( ePaperdoll_Shoulder, EQLook.Shoulder );
		pSprite->SetPaperdollId( ePaperdoll_Torso, EQLook.Clothes );
		pSprite->SetPaperdollId( ePaperdoll_Leg, EQLook.Pants );
		pSprite->SetPaperdollId( ePaperdoll_Belt, EQLook.Belt );
		pSprite->SetPaperdollId( ePaperdoll_Foot, EQLook.Shoes );
		pSprite->SetPaperdollId( ePaperdoll_Back, EQLook.Back );
		pSprite->PaperdollBuild();

		pSprite->SetRightObjectId( EQLook.MainHand );
		pSprite->SetLeftObjectId( EQLook.SecondHand );
	}
	else
		g_pDebugMessage->DebugOutput( 0, "[EQInfo] Can't Find then GItemID(%d)", GItemID );
}

//-----------------------------------------------------------------------------
void NetCli_MoveChild::FixEQInfo( int GItemID , EQWearPosENUM  Pos , int EQ )
{
	CRoleSprite* pSprite = g_pGameMain->FindRoleSprite( GItemID );
	if ( pSprite )
	{		
		switch ( Pos )
		{
		case EM_EQWearPos_Head:
			pSprite->SetPaperdollId( ePaperdoll_Helmet, EQ );
			break;

		case EM_EQWearPos_Gloves:
			pSprite->SetPaperdollId( ePaperdoll_Hand, EQ );
			break;

		case EM_EQWearPos_Shoes:
			pSprite->SetPaperdollId( ePaperdoll_Foot, EQ );
			break;

		case EM_EQWearPos_Clothes:
			pSprite->SetPaperdollId( ePaperdoll_Torso, EQ );
			break;

		case EM_EQWearPos_Pants:
			pSprite->SetPaperdollId( ePaperdoll_Leg, EQ );
			break;

		case EM_EQWearPos_Back:
			pSprite->SetPaperdollId( ePaperdoll_Back, EQ );
			break;

		case EM_EQWearPos_Belt:
			pSprite->SetPaperdollId( ePaperdoll_Belt, EQ );
			break;

		case EM_EQWearPos_Shoulder:
			pSprite->SetPaperdollId( ePaperdoll_Shoulder, EQ );
			break;

		case EM_EQWearPos_Necklace:
			break;

		case EM_EQWearPos_Ammo:
			break;

		case EM_EQWearPos_Ring1:
			break;

		case EM_EQWearPos_Ring2:
			break;

		case EM_EQWearPos_Earring1:
			break;

		case EM_EQWearPos_Earring2:
			break;

		case EM_EQWearPos_MainHand:
			pSprite->SetLeftObjectId( EQ );			
			break;

		case EM_EQWearPos_SecondHand:
			pSprite->SetLeftObjectId( EQ );
			break;
		}

		pSprite->PaperdollBuild();
	}
	else
		g_pDebugMessage->DebugOutput(0, "[FixEQInfo] Can't Find then GItemID(%d)", GItemID);
}

//-----------------------------------------------------------------------------
void NetCli_MoveChild::LookFace( int GItemID , LookStruct& Look )
{
	CRoleSprite* pSprite = g_pGameMain->FindRoleSprite( GItemID );
	if ( pSprite )
	{
		g_pDebugMessage->DebugOutput(2, "[LookFace] GItemID(%d)", GItemID);

		pSprite->SetPaperdollColor( Look.HairColor, Look.BodyColor );
		pSprite->SetPaperdollId( ePaperdoll_Face, Look.FaceID );
		pSprite->SetPaperdollId( ePaperdoll_Hair, Look.HairID );
		pSprite->PaperdollBuild();
	}
	else
		g_pDebugMessage->DebugOutput(0, "[LookFace] Can't Find then GItemID(%d)", GItemID);
}

//-----------------------------------------------------------------------------
void NetCli_MoveChild::ClientAutoPlot( int GItemID , char* AutoPlot )
{
}

//-----------------------------------------------------------------------------
void NetCli_MoveChild::ActionType( int GItemID , RoleActionStruct	Action )
{
	if ( GItemID == g_pGameMain->GetPlayerID() )
	{
		if ( Action.AttackMode )
		{
			g_pDebugMessage->DebugOutput(2, "AttackMode ON ");
			g_pGameMain->LockFight();
		}
		else
		{
			g_pDebugMessage->DebugOutput(2, "AttackMode OFF ");
			g_pGameMain->UnlockFight();
		}		
	}
	else
	{
		CRoleSprite* sprite = g_pGameMain->FindRoleSprite(GItemID);
		if ( sprite )
		{
			switch (sprite->GetObjectType())
			{
			case eSpriteObject_NPC:
			case eSpriteObject_QuestNPC:
				sprite->SetWalkState(Action.Walk);
				break;
			}
		}
	}
}

//-----------------------------------------------------------------------------
void NetCli_MoveChild::R_JumpBegin( int GItemID , float X , float Y , float Z , float Dir , float vX , float vY , float vZ )
{
	char Buf[256];
	sprintf( Buf , "[R_JumpBegin]GItemID = %d (%.2f %.2f %.2f) (%.2f, %.2f, %.2f)", GItemID, X , Y , Z, vX, vY, vZ );
	// g_pDebugMessage->DebugOutput( 2, Buf );

	CRoleSprite* pSprite = g_pGameMain->FindRoleSprite( GItemID );
	if ( pSprite )
	{
		float angle = Dir * PI / 180.0f;
		pSprite->SetPos(CRuVector3(X, Y, Z));
		pSprite->SetDirection(CRuVector3(cos(angle), 0.0f, -sin(angle)));
		pSprite->ForcedJump(CRuVector3(vX, vY, vZ));
	}
}

//-----------------------------------------------------------------------------
void NetCli_MoveChild::R_Relation( int GItemID , RoleRelationENUM   Relation )
{
	char Buf[256];
	sprintf( Buf , "GItemID = %d Relation=%d " , GItemID , Relation );
	g_pDebugMessage->DebugOutput( 2, Buf );
}

//-----------------------------------------------------------------------------
void NetCli_MoveChild::R_PartyMemberMove	( int DBID , int ZoneID , float X , float Y , float Z )
{
	char Buf[256];
	sprintf( Buf , "[Party成員移動資訊]DBID = %d ZoneID=%d X=%f Y=%f Z=%f" , DBID , ZoneID , X , Y , Z );
	g_pDebugMessage->DebugOutput( 2, Buf );

	NetCli_PartyChild::SetPartyMemberPosition( DBID, ZoneID, X, Y, Z );
}
//-----------------------------------------------------------------------------
void NetCli_MoveChild::PlayMotion			( int iObjID, const char* pszMotion )
{
	CRoleSprite* pObj = g_pGameMain->FindRoleSprite( iObjID );

	if( pObj )
	{
		int iMotionID = IBaseSprite::GetMotionEnum( pszMotion );
		if( iMotionID != 0 )
			pObj->Motion( iMotionID );
	}
}