#include "RoleDataEx.h"
#include <math.h>
bool    RoleDataEx::IsPlayer( )
{
    return ( Base.Type == EM_ObjectClass_Player );
}

bool    RoleDataEx::IsNPC( )
{
    return ( Base.Type == EM_ObjectClass_NPC || Base.Type == EM_ObjectClass_QuestNPC );
}
bool	RoleDataEx::IsQuestNPC()
{
	return ( Base.Type == EM_ObjectClass_QuestNPC );
}

bool    RoleDataEx::IsItem( )
{
    return ( Base.Type == EM_ObjectClass_Item );
}

bool    RoleDataEx::IsFlag( )
{
    return ( Base.Type == EM_ObjectClass_Flag );
}

bool	RoleDataEx::IsMirror()
{
	return ( TempData.Sys.ZoneID != G_ZoneID );
}

bool RoleDataEx::IsBodyEmpty( int Pos )
{
    if( BaseData.Body.Item[Pos].OrgObjID == 0 )
        return true;

    return false;
}

bool RoleDataEx::IsBankEmpty( int Pos )
{
    if( BaseData.Bank.Item[Pos].OrgObjID == 0 )
        return true;

    return false;
}

bool    RoleDataEx::IsAttack( )
{
   return TempData.Attr.Action.Attack;
}

void    RoleDataEx::IsAttack( bool Value )
{
    TempData.Attr.Action.Attack = Value;
}
bool    RoleDataEx::IsSit( )
{
	return TempData.Attr.Action.Sit;
}

void    RoleDataEx::IsSit( bool Value )
{
	TempData.Attr.Action.Sit = Value;
}

bool    RoleDataEx::IsAttackMode( )
{
    return TempData.Attr.Action.AttackMode;
}

void    RoleDataEx::IsAttackMode( bool Value )
{
    TempData.Attr.Action.AttackMode = Value;

    if( Value == false )
    {
        ClearHate( );
    }
	else
	{
		TempData.Attr.Action.Sit = false;
	}
}

bool    RoleDataEx::IsMove( )
{

	return RoleDataEx::CheckTime( TempData.Move.LastMoveTime ) == false;
}

bool    RoleDataEx::IsDead( )
{
    return TempData.Attr.Action.Dead;
}

void    RoleDataEx::IsDead( bool Value )
{
    TempData.Attr.Action.Dead = Value;
}

bool    RoleDataEx::IsFollow( )
{
    return TempData.Attr.Action.Follow;
}

void    RoleDataEx::IsFollow( bool Value )
{
    TempData.Attr.Action.Follow = Value;
}

bool    RoleDataEx::IsWalk( )
{
    return TempData.Attr.Action.Walk;
}

void    RoleDataEx::IsWalk( bool Value )
{
    TempData.Attr.Action.Walk= Value;
}

bool    RoleDataEx::IsTrade( )
{
    return TempData.Attr.Action.Trade;
}

void    RoleDataEx::IsTrade( bool Value )
{
    TempData.Attr.Action.Trade = Value;
}

bool    RoleDataEx::IsPet( RoleDataEx* PetOwner )
{
    if( PetOwner->TempData.Pet.PetID !=  GUID() )
        return false;
    if( OwnerGUID() != PetOwner->GUID() || SelfData.OwnerDBID != PetOwner->DBID() )
        return false;

    return true;
}
bool    RoleDataEx::IsSpell()
{
    return ( TempData.Magic.State != EM_MAGIC_PROC_STATE_NORMAL );
}

//************************************************************************************
//攻擊相關資訊
//************************************************************************************
//檢查是否為朋友
bool	RoleDataEx::CheckFriend( RoleDataEx*	Target )
{
    //(暫時)
    if( Target->RoomID() != RoomID() )
        return false;

//    if( Target->IsPlayer() == IsPlayer() )
//        return true;

//    return false;
	 return Camp.IsFriend( TempData.AI.CampID , Target->TempData.AI.CampID );
}
//-----------------------------------------------------------------------------------------------
//檢查是否敵對
bool	RoleDataEx::CheckEnemy( RoleDataEx* Target )
{
    if( CheckAttackable( Target ) == false )
		return false;

	return  Camp.IsEnemy( TempData.AI.CampID , Target->TempData.AI.CampID );
}
//-----------------------------------------------------------------------------------------------
bool	RoleDataEx::CheckHelp( RoleDataEx* Target )
{
	return  Camp.IsCanHelp( TempData.AI.CampID , Target->TempData.AI.CampID );
}
//-----------------------------------------------------------------------------------------------
//檢查此物件是否致能
bool	RoleDataEx::CheckEnabled( )
{
    //如果物件死亡或不在分割區則不處理
    if(		TempData.Sys.SecX == -1
        ||	TempData.Sys.SecZ == -1				)
        return false;

    return true;
}
//----------------------------------------------------------------------------------------
//檢查是否要收尋敵人
bool	RoleDataEx::CheckSearchEnemy( )
{//(暫時)
    if( ClockMod( 30 ) )
        return false;

    if( !CheckStrikback() )
        return false;

    return BaseData.Mode.Searchenemy;
}
//-----------------------------------------------------------------------------------------------
//檢查是否可以攻擊
bool	RoleDataEx::CheckAttackable( RoleDataEx* Target )
{//(暫時)

    RoleDataEx* Owner       = GetOrgOwner( );
    RoleDataEx* TargetOwner = Target->GetOrgOwner( );
    
    //(暫時)
    //如果在不同的空間中
    if( Target->RoomID() != RoomID() )
        return false;

    //是否同一個主人
    if( TargetOwner->GUID() == Owner->GUID() )
        return false;

    if(		Target->BaseData.Mode.Fight == false )
        return false;

    if(		Target->TempData.Attr.Action.Dead == true 
        ||	TempData.Attr.Action.Dead == true			)
        return false;

	//--------------------------------------------------------------------
	//陣營檢查
	
	return  Camp.IsCanAttck( Owner->TempData.AI.CampID , TargetOwner->TempData.AI.CampID );

    return false;
}
//-----------------------------------------------------------------------------------------------
//檢查兩物件距離是否可以攻擊
bool	RoleDataEx::CheckMainAttackRange( RoleDataEx* Target )
{
    float Dx = Target->BaseData.Pos.X - BaseData.Pos.X;
    float Dz = Target->BaseData.Pos.Z - BaseData.Pos.Z;
    if( Target->IsMove() )
    {
        if( sqrt( Dx*Dx + Dz*Dz ) < MainAttackRange( Target) + 20 )
            return true;
    }
    else
    {
        if( sqrt( Dx*Dx + Dz*Dz ) < MainAttackRange( Target) )
            return true;

    }
    return false;
}
//-----------------------------------------------------------------------------------------------
//檢查兩物件距離是否可以攻擊
bool	RoleDataEx::CheckSecAttackRange( RoleDataEx* Target )
{
	float Dx = Target->BaseData.Pos.X - BaseData.Pos.X;
	float Dz = Target->BaseData.Pos.Z - BaseData.Pos.Z;
	if( Target->IsMove() )
	{
		if( sqrt( Dx*Dx + Dz*Dz ) < SecAttackRange( Target) + 10 )
			return true;
	}
	else
	{
		if( sqrt( Dx*Dx + Dz*Dz ) < SecAttackRange( Target) )
			return true;

	}
	return false;
}
//-----------------------------------------------------------------------------------------------
//檢查是否要計算仇恨值
bool	RoleDataEx::CheckCalHate( )
{
    if( IsPlayer() )
        return false;

    return true;
}
//-----------------------------------------------------------------------------------------------
/*
//檢查是否Miss
// Type = 0  主手   1 副手
ATTACK_DMGTYPE_ENUM	RoleDataEx::CheckMiss( RoleDataEx*  Target , AttackHandTypeENUM Type )
{//(暫時)
    RoleValueData*		OAttr = &TempData.Attr;
    RoleValueData*		TAttr = &Target->TempData.Attr;

	int DLV = OAttr->Ability->Level - TAttr->Ability->Level;
    int Rate;

	switch( Type )
	{
	case EM_AttackHandType_Main:
		Rate = int(  OAttr->Fin.Main_HitRate - TAttr->Fin.DodgeRate  + DLV * RoleValueData::FixArg.Miss_DLV );
		break;
	case EM_AttackHandType_Second:
		Rate = int(  OAttr->Fin.Sec_HitRate - TAttr->Fin.DodgeRate  + DLV * RoleValueData::FixArg.Miss_DLV );
		break;
	case EM_AttackHandType_None:
		return false;
	}
	
	if( IsPlayer() )
	{
		float WeaponSkill;
		switch(Type)
		{
		case 0:
			WeaponSkill = OAttr->SkillValue->GetSkill( OAttr->MainWeaponType );
			break;
		case 1:
			WeaponSkill = OAttr->SkillValue->GetSkill( OAttr->SecWeaponType );
			break;
		}

		float SkillLV = WeaponSkill / 2;
		float SkillMissRate = ( SkillLV - Target->Level() ) * RoleValueData::FixArg.Miss_Skill_DLV;
		if( SkillMissRate > 10 )
			SkillMissRate = 10;
		else if( SkillMissRate < -30 )
			SkillMissRate = -30;

		Rate += (int)SkillMissRate;

	}

    if( Rate > 95 )
        Rate = 95;
    if( Rate < 25 )
        Rate = 25;
    
    if( rand() % 100 > Rate   )
        return true;

    return false;
}
*/
//-----------------------------------------------------------------------------------------------
//檢查某物件是否在視野內
bool	RoleDataEx::CheckInSight( RoleDataEx* Target , float Angle , GameObjDbStructEx* OwnerOrgDB )
{
	GameObjDbStructEx*	OrgDB;
	OrgDB = St_GetObjDB( BaseData.ItemInfo.OrgObjID );
	if( OrgDB == NULL )
		return false;

	int DLV = Target->Level() - Level();

	
	float Rate = 1 - DLV * 0.05f;

	switch( OwnerOrgDB->NPC.Brave )
	{
	case 0://極勇敢		20%  - 150%	(- 5%*等級差)	全打
		if( Rate < 0.2f )
			Rate = 0.2f;
		if( Rate > 1.5f )
			Rate = 1.5f;
		break;
	case 1://勇敢:		50%  - 120%	(- 5%*等級差)	+Lv10
		if( DLV > 10 )
			return false;

		if( Rate > 1.2f )
			Rate = 1.2f;

		break;
	case 2://一般:		85%  - 100%	(- 5%*等級差)	+Lv3
		if( DLV > 3 )
			return false;

		if( Rate > 1 )
			Rate = 1;

		break;
	case 3://有些膽小:	100% - 100%	(- 5%*等級差) 	-Lv1
		if( DLV > -1 )
			return false;

		if( Rate > 1 )
			Rate = 1;

		break;
	case 4://非常膽小:	100% - 100% (- 5%*等級差) 	-Lv5
		if( DLV > -5 )
			return false;

		if( Rate > 1 )
			Rate = 1;
		break;
	}

	float Len = OwnerOrgDB->NPC.SearchRange * Rate + OwnerOrgDB->ImageObj->BoundRadius;

	//如果目標為隱形 並且目標沒有偵測隱形
	if( TempData.Attr.Effect.Detect == false && Target->TempData.Attr.Effect.Cover == true)
	{
	//	Len = OwnerOrgDB->ImageObj->BoundRadius + 5;
		return false;
	}
	
	//如果目標在潛行狀態(  )
	if( Target->TempData.Attr.Effect.Sneak )
	{
		Len = float( OwnerOrgDB->ImageObj->BoundRadius + 3 );
		if( DLV < 0 )
		{
			Len = Len + DLV*DLV;
			if( Len >= OwnerOrgDB->NPC.SearchRange )
				Len = float( OwnerOrgDB->NPC.SearchRange );
		}
	}
	float TargetLen = Length( Target );

	if( TargetLen < OwnerOrgDB->ImageObj->BoundRadius + 5 )
		return true;

    //距離檢查
    if( Len < TargetLen )
        return false;

    //角度檢查
    float	Dir = CalDir( Target );

    float DirDF = Dir - BaseData.Pos.Dir;

    if( DirDF > 180 )
        DirDF = 360 - DirDF;
    else if ( DirDF < -180 )
        DirDF += 360;
    else if( DirDF < 0 )
        DirDF *= -1;

    //視角檢查
    if( DirDF > Angle/2 )
        return false;


    return true;
}
//-----------------------------------------------------------------------------------------------
//檢查是否可以要請人入隊伍
bool	RoleDataEx::CheckInvitable( RoleDataEx* Target )
{
    return false;
}
//-----------------------------------------------------------------------------------------------
//簡查是否要停止攻擊
//1 視野=200-1000內 四秒 一次 檢查 有 10% 機率會停止攻擊 
//2 視野=1000 以上 停止功擊
bool	RoleDataEx::CheckStopAttack()
{
    /*
    //每四秒處理一次
    if( ClockMod( 40 ) )
        return false;

    RoleDataEx	*Target = (RoleDataEx*)St_GetRoleData( TempData.AtkFol.TargetID );
    if( Target == NULL )
        return false;

    int Len = Length( Target );

    //
    if( Len > 1000 )
        return true;

    if( rand()%10 == 0  && Len > 200 )
        return true;
*/
    return false;
}
//-----------------------------------------------------------------------------------------------
//檢查是否可以反擊
bool		RoleDataEx::CheckStrikback( )
{
    return BaseData.Mode.Strikback;
}
//-----------------------------------------------------------------------------------------------
//檢查是否可以移動
bool		RoleDataEx::CheckMoveable( )
{

    return BaseData.Mode.Move && !TempData.Attr.Action.Dead;
}
//-----------------------------------------------------------------------------------------------
bool RoleDataEx::CheckAutoPlot()
{
    if( SelfData.AutoPlot.Size() == 0 )
        return false;
    return true;
}


bool RoleDataEx::CheckClientAutoPlot()
{
    if( TempData.C_AutoPlot.Size() == 0 )
        return false;
    return true;
}

bool RoleDataEx::CheckRangePlot()
{
    if( TempData.RangePlot.Size() == 0 )
        return false;
    return true;
}

bool RoleDataEx::CheckTouchPlot()
{
    if( TempData.TouchPlot.Size() == 0 )
        return false;
    return true;
}

bool RoleDataEx::CheckDeadPlot()
{
    if( TempData.DeadPlot.Size() == 0 )
        return false;
    return true;
}
bool RoleDataEx::CheckSayPlot()
{
    if( TempData.SayPlot.Size() == 0 )
        return false;
    return true;
}

//第一次施法檢察
bool	RoleDataEx::CheckCanBeginSpell( RoleDataEx* Target , float TargetX , float TargetY , float TargetZ , GameObjDbStructEx* Magic )
{

	if( CheckCanSpell( Target , TargetX , TargetY , TargetZ , Magic ) == false )
		return false;

	//消耗物品檢查
	if( CheckSpellMagicCost( Magic ) == false)
	{
		Msg( "法術 需求有問題 " );
		return false;
	}

	//檢查Coldown
	if( CheckMagicColdown( Magic->MagicCol.Coldown.Class , Magic->MagicCol.Coldown.Type ) == false )
	{
		Msg( "法術 冷卻中 " );
		return false;
	}

	return true;
}
//檢查是否可以施法
bool RoleDataEx::CheckCanSpell( RoleDataEx* Target , float TargetX , float TargetY , float TargetZ , GameObjDbStructEx* Magic )
{

    //檢查法術技能狀態
	if( Magic->MagicCol.TargetType == EM_Releation_Self )
		Target = this;
	
	if( Magic->MagicCol.TargetType == EM_Releation_Locatoin )
	{
		//簡查距離
		if( Length( TargetX , TargetY , TargetZ )  > Magic->MagicCol.AttackDistance + 1 )
		{
			Msg( "法術 距離過遠" );
			return false;
		}
	}
	else
	{

		//目標檢查
		if( CheckRelation( Target , Magic->MagicCol.TargetType ) == false )
		{
			Msg( "法術 不可對此目標施展" );
			return false;
		}

		//簡查距離		
		if( Length( Target ) > Magic->MagicCol.AttackDistance + 1 )
		{
			Msg( "法術 距離過遠" );
			return false;
		}
	}


	//面向檢查
	if( Magic->MagicCol.Flag.Spell_Back )
	{
		if( Target->CalAngle( this ) < 90 )
		{
			Msg( "法術 要在背後施展" );
			return false;
		}
	}

	if( Magic->MagicCol.Flag.Spell_Front )
	{
		if( Target->CalAngle( this ) > 90 )
		{
			Msg( "法術 要在前面施斬" );
			return false;
		}
	}

	if( Magic->MagicCol.Flag.Spell_LookAtTarget )
	{	
		if( CalAngle( Target ) > 45 )
		{	
			Msg( "法術 要面對敵人才可施展" );
			return false;
		}	
	}
	/*
    //消耗物品檢查
    if( CheckSpellMagicCost( Magic ) == false)
	{
		Msg( "法術 需求有問題 " );
        return false;
	}

	//檢查Coldown
	if( CheckMagicColdown( Magic->MagicCol.Coldown.Class , Magic->MagicCol.Coldown.Type ) == false )
	{
		Msg( "法術 冷卻中 " );
		return false;
	}
	*/

    return true;
}
//-----------------------------------------------------------------------------------------------
//與目標關係檢查
bool	RoleDataEx::CheckRelation( RoleDataEx* Target , GameObjectRelationENUM Relation )
{
    switch( Relation )
    {
    case EM_Releation_Self:			
        {
           //if( GUID() == Target->GUID() )
           return true;
        }break;
    case EM_Releation_Member:		
        {

        }break;
    case EM_Releation_Self_Pet:		
        {
        }break;
    case EM_Releation_Member_Pet:	
        {
        }break;
    case EM_Releation_Friend:		
        {
			if( Target->IsDead() )
				return false;

			return CheckFriend( Target );
			/*
			if( IsNPC() && Target->IsNPC() )
				return true;

			if( IsPlayer() && Target->IsPlayer() )
				return true;			
*/
        }break;
    case EM_Releation_Friend_NPC:	
        {
			if( Target->IsDead() )
				return false;

			if( !Target->IsNPC() )
				return false;

			return CheckFriend( Target );
        }break;
    case EM_Releation_Enemy:		
        {
			if( Target->IsDead() )
				return false;
/*
            if( IsNPC() && Target->IsPlayer() )
                return true;

            if( IsPlayer() && Target->IsNPC() )
                return true;
				*/
			return CheckEnemy( Target );
        }break;
    case EM_Releation_Player:		
        {
			if( Target->IsDead() )
				return false;

            if( IsNPC() && Target->IsNPC() )
                return true;

            if( IsPlayer() && Target->IsPlayer() )
                return true;
        }break;
    case EM_Releation_All:			
        {
            return true;
        }break;
    case EM_Releation_GuildPlayer:	
        {
        }break;
    case EM_Releation_NotGuildPlayer:
        {
        }break;
	case EM_Releation_Corpse:			//屍體
		{
			if( Target->IsDead() )
				return true;
		}
		break;
	case EM_Releation_Npc_Corpse:		//NPC屍體
		{
			if( !Target->IsDead() )
				return false;

			if( Target->IsNPC() )
				return true;
		}
		break;
	case EM_Releation_Player_Corpse:	//玩家屍體
		{
			if( !Target->IsDead() )
				return false;

			if( Target->IsPlayer() )
				return true;
		}
		break;
	case EM_Releation_Locatoin:			//指定位置( 範圍法術 )
		{
			return true;
		}
		break;
    }

    return false;
}

//-----------------------------------------------------------------------------------------------
//簡查施法必要消費
bool	RoleDataEx::CheckSpellMagicCost( GameObjDbStructEx* Magic )
{

	MagicSpellCostTypeENUM CostType	= Magic->MagicCol.Cost.Type ;
	int CostValue	= Magic->MagicCol.Cost.Value;
	
	//檢查消費
	switch( CostType )
	{
	case EM_MagicSpellCostType_None:					//無消耗

		break;
	case EM_MagicSpellCostType_HP:						//消耗 HP
		{
			if( BaseData.HP <= CostValue )
			{
				Msg( "施法 HP不足" );
				return false;
			}
		}
		break;
	case EM_MagicSpellCostType_MP:						//消耗 MP
		{
			CostValue = (int)(  CostValue * ( 100 - TempData.Attr.Fin.ManaDecrease )/100 ); 
			if( BaseData.MP <= CostValue )
			{		
				Msg( "施法 MP不足" );
				return false;
			}
		}
		break;
	case EM_MagicSpellCostType_SP_Warrior:		//消耗 SP 戰士	
		{
			if( BaseData.Voc == EM_Vocation_Warrior )
			{
				if( BaseData.SP <= CostValue )
				{
					Msg( "戰士 SP不足" );
					return false;
				}
			}
			else if( BaseData.Voc_Sub == EM_Vocation_Warrior )
			{
				if( BaseData.SP_Sub <= CostValue )
				{
					Msg( "戰士 SP不足" );
					return false;
				}
			}
		}
		break;
	case EM_MagicSpellCostType_SP_Ranger:		//消耗 SP 遊俠
		{
			if( BaseData.Voc == EM_Vocation_Ranger )
			{
				if( BaseData.SP <= CostValue )
				{
					Msg( "遊俠 SP不足" );
					return false;
				}
			}
			else if( BaseData.Voc_Sub == EM_Vocation_Ranger )
			{
				if( BaseData.SP_Sub <= CostValue )
				{
					Msg( "遊俠 SP不足" );
					return false;
				}
			}
		}
		break;
	case EM_MagicSpellCostType_SP_Rogue:		//消耗 SP 盜賊	
		{
			if( BaseData.Voc == EM_Vocation_Rogue )
			{
				if( BaseData.SP <= CostValue )
				{
					Msg( "盜賊 SP不足" );
					return false;
				}
			}
			else if( BaseData.Voc_Sub == EM_Vocation_Rogue )
			{
				if( BaseData.SP_Sub <= CostValue )
				{
					Msg( "盜賊 SP不足" );
					return false;
				}
			}
		}
		break;

		/*
	case EM_MagicSpellCostType_SP:						//消耗 SP
		{
			if( BaseData.SP <= CostValue )
			{
				Msg( "施法 SP不足" );
				return false;
			}
		}
		break;*/
	case EM_MagicSpellCostType_Item:					//消耗 物品
		{
			if( CalBodyItemCount( CostValue ) == 0 )
			{
				Msg( "施法 消耗物品有問題" );
				return false;
			}
		}
		break;
	case EM_MagicSpellCostType_Ammo_Gun:				//消耗 子彈
		{
			ItemFieldStruct* Item = GetEqItem( EM_EQWearPos_Ammo );
			GameObjDbStructEx*	OrgDB;
			OrgDB = St_GetObjDB( Item->OrgObjID );
			if(		OrgDB->IsWeapon() == false 
				||	OrgDB->Item.WeaponType != EM_Weapon_Gun 
				||  OrgDB->Item.WeaponPos != EM_WeaponPos_Ammo )
			{
				Msg( "施法 沒有子彈" );
				return false;
			}
		}
		break;
	case EM_MagicSpellCostType_Ammo_Bow:				//消耗 弓箭矢
		{
			ItemFieldStruct* Item = GetEqItem( EM_EQWearPos_Ammo );
			GameObjDbStructEx*	OrgDB;
			OrgDB = St_GetObjDB( Item->OrgObjID );
			if(		OrgDB->IsWeapon() == false 
				||	OrgDB->Item.WeaponType != EM_Weapon_Bow
				||  OrgDB->Item.WeaponPos != EM_WeaponPos_Ammo )
			{
				Msg( "施法 沒有弓箭矢" );
				return false;
			}
		}
		break;
	case EM_MagicSpellCostType_Ammo_CossBow:			//消耗 十字弓箭矢
		{
			ItemFieldStruct* Item = GetEqItem( EM_EQWearPos_Ammo );
			GameObjDbStructEx*	OrgDB;
			OrgDB = St_GetObjDB( Item->OrgObjID );
			if(		OrgDB->IsWeapon() == false 
				||	OrgDB->Item.WeaponType != EM_Weapon_CossBow 
				||  OrgDB->Item.WeaponPos != EM_WeaponPos_Ammo	)
			{
				Msg( "施法 沒有十字弓箭矢" );
				return false;			
			}
		}
		break;
	case EM_MagicSpellCostType_Ammo_Throw:				//消耗 投擲物
		{
			ItemFieldStruct* Item = GetEqItem( EM_EQWearPos_Ammo );
			GameObjDbStructEx*	OrgDB;
			OrgDB = St_GetObjDB( Item->OrgObjID );
			if(		OrgDB->IsWeapon() == false 
				||	OrgDB->Item.WeaponType != EM_Weapon_Throw 
				||  OrgDB->Item.WeaponPos != EM_WeaponPos_Ammo	)
			{
				Msg( "施法 沒有投擲物" );
				return false;	
			}
		}
		break;

	}
	//檢查需求
	MagicSpellNeedTypeENUM NeedType	= Magic->MagicCol.Need.Type ;
	int NeedValue	= Magic->MagicCol.Need.Value;

	switch( NeedType )
	{
	case EM_MagicSpellNeedType_None:				//無需求
		break;
	case EM_MagicSpellNeedType_Weapon:				//需求 自己裝 武器
		{
			if(		GetEqItem( EM_EQWearPos_MainHand )->OrgObjID	!= NeedValue 
				&&	GetEqItem( EM_EQWearPos_SecondHand )->OrgObjID	!= NeedValue )
			{
				Msg( "施法 此武器不可使用" );
				return false;
			}
		}
		break;
	case EM_MagicSpellNeedType_EQ:					//需求 自己裝 裝備
		break;
	case EM_MagicSpellNeedType_Suit:				//需求 自己裝 套裝
		break;
	case EM_MagicSpellNeedType_Buf:					//需求 自己有 法術Buf
		break;
	case EM_MagicSpellNeedType_Buf_Target:			//需求 目標有 法術Buf
		break;
	case EM_MagicSpellNeedType_NoBuf:				//需求 自己沒有 法術Buf
		break;
	case EM_MagicSpellNeedType_NoBuf_Target:		//需求 目標沒有 法術Buf
		break;
	case EM_MagicSpellNeedType_NoAtk:				//需求 自己非戰鬥
		break;
	case EM_MagicSpellNeedType_NoAtk_Target:		//需求 目標非戰鬥
		break;
	case EM_MagicSpellNeedType_WeaponType_Unarmed:	//需求 自己裝 武器類型 空手
		{
			if( TempData.Attr.MainWeaponType != EM_Weapon_Unarmed )
			{
				Msg( "施法 主手要空手" );
				return false;
			}
		}
		break;
	case EM_MagicSpellNeedType_WeaponType_Blade:    //需求 自己裝 武器類型 劍
		{
			if( TempData.Attr.MainWeaponType != EM_Weapon_Blade )
			{
				Msg( "施法 主手要拿單手劍" );
				return false;
			}
		}
		break;
	case EM_MagicSpellNeedType_WeaponType_Dagger:   //需求 自己裝 武器類型 匕首
		{
			if( TempData.Attr.MainWeaponType != EM_Weapon_Dagger )
			{
				Msg( "施法 主手要拿匕首" );
				return false;
			}
		}
		break;
	case EM_MagicSpellNeedType_WeaponType_Wand:     //需求 自己裝 武器類型 權杖
		{
			if( TempData.Attr.MainWeaponType != EM_Weapon_Wand )
			{
				Msg( "施法 主手要拿權杖" );
				return false;
			}
		}
		break;
	case EM_MagicSpellNeedType_WeaponType_Axe:      //需求 自己裝 武器類型 斧
		{
			if( TempData.Attr.MainWeaponType != EM_Weapon_Axe )
			{
				Msg( "施法 主手要拿單手斧" );
				return false;
			}
		}
		break;
	case EM_MagicSpellNeedType_WeaponType_Bludgeon: //需求 自己裝 武器類型 鎚棍棒
		{
			if( TempData.Attr.MainWeaponType != EM_Weapon_Bludgeon )
			{
				Msg( "施法 主手要拿鎚棍棒" );
				return false;
			}
		}
		break;
	case EM_MagicSpellNeedType_WeaponType_Claymore: //需求 自己裝 武器類型 雙手劍
		{
			if( TempData.Attr.MainWeaponType != EM_Weapon_Claymore )
			{
				Msg( "施法 主手要拿雙手劍" );
				return false;
			}
		}
		break;
	case EM_MagicSpellNeedType_WeaponType_Staff:    //需求 自己裝 武器類型 杖
		{
			if( TempData.Attr.MainWeaponType != EM_Weapon_Staff )
			{
				Msg( "施法 主手要拿杖" );
				return false;
			}
		}
		break;
	case EM_MagicSpellNeedType_WeaponType_2H_Axe:   //需求 自己裝 武器類型 雙手斧
		{
			if( TempData.Attr.MainWeaponType != EM_Weapon_2H_Axe )
			{
				Msg( "施法 主手要拿雙手斧" );
				return false;
			}
		}
		break;
	case EM_MagicSpellNeedType_WeaponType_2H_Hammer://需求 自己裝 武器類型 雙手鎚
		{
			if( TempData.Attr.MainWeaponType != EM_Weapon_2H_Hammer )
			{
				Msg( "施法 主手要拿雙手鎚" );
				return false;
			}
		}
		break;
	case EM_MagicSpellNeedType_WeaponType_Polearm:	//需求 自己裝 武器類型 槍(長矛)
		{
			if( TempData.Attr.MainWeaponType != EM_Weapon_Polearm )
			{
				Msg( "施法 主手要拿槍(長矛)" );
				return false;
			}
		}
		break;
	case EM_MagicSpellNeedType_WeaponType_SwordType: //需求 自己裝 武器類型 劍類(單雙手)
		{
			if(		TempData.Attr.MainWeaponType != EM_Weapon_Blade 
				&&	TempData.Attr.MainWeaponType != EM_Weapon_Claymore )
			{
				Msg( "施法 主手要拿劍類" );
				return false;
			}
		}
		break;
	case EM_MagicSpellNeedType_WeaponType_AxeType:	//需求 自己裝 武器類型 斧類(單雙手)
		{
			if(		TempData.Attr.MainWeaponType != EM_Weapon_2H_Axe 
				&&	TempData.Attr.MainWeaponType != EM_Weapon_Axe )
			{
				Msg( "施法 主手要拿斧類" );
				return false;
			}
		}
		break;
	}
 
    return true;
}
//-----------------------------------------------------------------------------------------------
bool	RoleDataEx::CheckMagicInterrupt( )
{
	GameObjDbStructEx*	OrgDB;
	OrgDB = St_GetObjDB( TempData.Magic.MagicCollectID );
	if( OrgDB == NULL )
		return true;
	
	if( OrgDB->MagicCol.Flag.Interrupt_OnMove )
	    return TempData.Magic.CheckInterrupt( X() , Z() );

	return false;
}
//-----------------------------------------------------------------------------------------------
//檢查是否可以對目標失法
bool	RoleDataEx::CheckUseItem(  int TargetID , float TargetX , float TargetY , float TargetZ , int Pos , int Type , ItemFieldStruct&  Item )
{
    RoleDataEx*		Target = (RoleDataEx*)St_GetRoleData( TargetID );
    if( Target == NULL )
        Target = this;

    if( Item.Pos != EM_ItemState_NONE )
        return false;

    //如果還有物品使用中則不可使用
    if( TempData.Magic.UseItem != 0 )
        return false;

	//如果使用物品被封住
	if( TempData.Attr.Effect.UseItemDisable )
		return false;


    GameObjDbStructEx*	OrgDB;
    GameObjDbStructEx*	MagicDB;
    OrgDB = St_GetObjDB( Item.OrgObjID );
    if( OrgDB == NULL )
        return false;

    MagicDB = St_GetObjDB( OrgDB->Item.IncMagic_Onuse );
    if( MagicDB == NULL )
        return false;

	//MagicProcInfo* MagicProc = &Owner->TempData.Magic;
    //檢查是否可以對目標施法
    if( CheckCanSpell( Target , TargetX , TargetY , TargetZ , MagicDB ) == false )
        return false;


    return true;
}
//-----------------------------------------------------------------------------------------------
//檢查魔法是否命中
bool    RoleDataEx::CheckMagicHit( RoleDataEx* Target , GameObjDbStructEx* OrgDB )
{
	/*
    int DLV = Level() - Target->Level();
    float HitRate =  OrgDB->Magic.HitRate + OrgDB->Magic.DLv_HitRate * DLV   ;
    float Rd = float(rand()%100 ) / 100 ;
    return ( HitRate > Rd );
	*/
	return true;
}

//檢查是否要逃跑
bool    RoleDataEx::CheckEscape( RoleDataEx* Target )
{
    if( TempData.Attr.Effect.Fear )
        return true;

	GameObjDbStructEx*	OrgDB;
	OrgDB = St_GetObjDB( BaseData.ItemInfo.OrgObjID );

	if( OrgDB->IsNPC() == false )
		return false;
	
	switch( OrgDB->NPC.EscapeType )
	{
	case 0:
		return false;
		break;
	case 1:
		if( TempData.Attr.Fin.MaxHP > BaseData.HP * 5 && rand() % 20 == 0 )
			return true;
		break;
	case 2:
		if( TempData.Attr.Fin.MaxHP > BaseData.HP * 4 && rand() % 20 == 0 )
			return true;
		break;
	case 3:
		if( TempData.Attr.Fin.MaxHP > BaseData.HP * 3 && rand() % 20 == 0 )
			return true;
		break;
	case 4:
		if( TempData.Attr.Fin.MaxHP > BaseData.HP * 2 && rand() % 20 == 0 )
			return true;
		break;
	case 5:
		if( TempData.Attr.Fin.MaxHP*3 > BaseData.HP * 4 && rand() % 20 == 0 )
			return true;
		break;
	case 6:
		return true;
		
	}
	
    return false;
}
bool    RoleDataEx::IsUnderAttack( )
{
    return TempData.NPCHate.Hate.Size() != 0;
}

//檢查是否可以物理攻擊
bool	RoleDataEx::CheckPhyAttack( RoleDataEx* Target )
{
	//如果自己  不可用物理攻擊
	if( TempData.Attr.Effect.UsePhyDisable )
		return false;

	//如果目標  物理無效(物理技能與一般攻擊無效)
	if( Target->TempData.Attr.Effect.PhyInvincible )
		return false;

	return true;
}
//檢查是否可以法術攻擊
bool	RoleDataEx::CheckMagicAttack( RoleDataEx* Target )
{
	//如果自己  不可用法術攻擊
	if( TempData.Attr.Effect.UseMagicDisable )
		return false;

	//如果目標  法術無效
	if( Target->TempData.Attr.Effect.MagicInvincible )
		return false;

	return true;
}

bool	RoleDataEx::IsRoleDataWriteable( )
{
	if( IsDestroy() )
		return false;

	if( RoleDataEx::G_ZoneID != ZoneID() )
		return false;
	
	if( IsMirror() )
		return false;
	
	return true;
}

//檢查時間
bool	RoleDataEx::CheckTime( int Time )
{
	return int( G_SysTime - Time ) >= 0;
}

//檢查是否已經有某輔助法術
bool	RoleDataEx::CheckHasAssistMagic( GameObjDbStructEx* MagicBaseDB )
{
	if( MagicBaseDB == NULL )
		return false;

	if( BaseData.Buff.Size() >= BaseData.Buff.MaxSize() )
		return false;

	for( int i = 0 ; i < BaseData.Buff.Size() ; i++ )
	{
		BuffBaseStruct&  Buf = BaseData.Buff[ i ];

		GameObjDbStructEx*  MagBuf = St_GetObjDB( Buf.BuffID );

		if( MagBuf->GUID == MagicBaseDB->GUID )
		{
			return false;

		}
		else if(     MagBuf->MagicBase.AssistType != EM_Magic_Type_NULL 
			&&  MagBuf->MagicBase.AssistType == MagicBaseDB->MagicBase.AssistType )
		{
			//如果可不可互蓋
			if(		MagicBaseDB->MagicBase.EffectAddonType == 1  
				&&	MagBuf->MagicBase.EffectLV == MagicBaseDB->MagicBase.EffectLV)
				continue;

			if( MagBuf->MagicBase.EffectLV > MagicBaseDB->MagicBase.EffectLV )
				continue;

			return false;

		}
	}
	return true;

}