#!/usr/bin/python
# -*- coding: GBK -*-
#
# @todo: ¼¼Äܹ¥»÷¹ÜÀíÆ÷
#
# @author: Alee
# @date 2017-11-10 ÉÏÎç10:36:33
# @version 1.0
#
# @note: ¼¼ÄÜ¿ò¼Üº¯Êý
#
#---------------------------------------------------------------------
import GameWorld
import IPY_GameWorld
import GameSkills
import GameBuffs
import BuffSkill
import PlayerControl
import ChConfig
import BaseAttack
import CalcLineEffect
import CalcNoLineEffect
import NPCCommon
import SkillCommon
import AttackCommon
import PlayerState
import FBLogic
import ItemCommon
import OperControlManager
import PetControl
import ReadChConfig
import DataRecordPack
#import ChItem
import ShareDefine
import PlayerGreatMaster
import PlayerHorse
import GameObj
import random
import NetPackCommon
import ChPyNetSendPack
import GameMap
import collections
import PassiveBuffEffMng
import ChEquip
import SkillShell
import FBCommon
import IpyGameDataPY
import PyGameData
import EventShell
#---------------------------------------------------------------------
GameWorld.ImportAll("Script\\Skill\\" , "GameSkills")
GameWorld.ImportAll("Script\\Skill\\" , "GameBuffs")
GameWorld.ImportAll("Script\\Skill\\" , "")
# ¼Ç¼¿Í»§¶ËÉ˺¦ {(objID, objType):[HurtHP, AttackType]}
g_ClientHurtDict = collections.OrderedDict()
g_UseSkillPlayerID = 0  # È«·þ¹¥»÷Ϊµ¥Ïß³Ì ¼Ç¼µÄÊǵ±Ç°Ê¹Óü¼ÄܵÄÍæ¼Ò ÓÃÓÚÅжÏg_ClientHurtDictµÄ¹éÊô
#---------------------------------------------------------------------
##C++µ÷Óú¯Êý, ÖØÐ¶ÁÈ¡ËùÓм¼ÄÜ
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks C++µ÷Óú¯Êý, ÖØÐ¶ÁÈ¡ËùÓм¼ÄÜ
def ReloadSkill(tick):
    scriptPath = ChConfig.GetAppPath() + "Script\\Skill\\GameSkills"
    GameWorld.ReloadScript(scriptPath, "GameSkills")
    
    scriptPath = ChConfig.GetAppPath() + "Script\\Skill"
    GameWorld.ReloadScript(scriptPath, "")
    return
#---------------------------------------------------------------------
##C++µ÷Óú¯Êý, ÖØÐ¶ÁÈ¡ËùÓÐBuff
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks C++µ÷Óú¯Êý, ÖØÐ¶ÁÈ¡ËùÓÐBuff
def ReloadBuff(tick):
    scriptPath = ChConfig.GetAppPath() + "Script\\Skill\\GameBuffs"
    GameWorld.ReloadScript(scriptPath, "GameBuffs")
    return
#---------------------------------------------------------------------
##»ñµÃ¼¼ÄܵÄÓ°Ïì¶ÔÏó
# @param curSkill Íæ¼ÒʵÀý
# @return ¼¼ÄܵÄÊÜЧ¹û¶ÔÏó 
# @remarks »ñµÃ¼¼ÄܵÄÓ°Ïì¶ÔÏó ²Î¿¼ Def_UseSkillTag_Type
def GetSkillAffectTag(curSkill):
    return curSkill.GetTag()/10    
##»ñµÃ¼¼ÄܵÄÊÍ·ÅÄ¿±ê
# @param curSkill Íæ¼ÒʵÀý
# @return ¼¼ÄܵÄÊÜЧ¹û¶ÔÏó 
# @remarks »ñµÃ¼¼ÄܵÄÊÍ·ÅÄ¿±ê £¨ÎÞ¶ÔÏó£¬ ÓжÔÏ󣬵ØÃ棩
def GetSkillFireAim(curSkill):
    return curSkill.GetTag()%10
# µ±Ç°ÊÍ·ÅÖ÷¶¯¼¼ÄܵÄÍæ¼Ò
def GetUseSkillPlayerID():
    global g_UseSkillPlayerID
    return g_UseSkillPlayerID
# ¿Í»§¶ËÉËѪÁÐ±í£¬ÐÞ¸ÄÁ˱éÀú¶ÔÏóºÍ¼ÆËãѪÁ¿
def GetClientHurtDict():
    global g_ClientHurtDict
    return g_ClientHurtDict
def ClearClientHurtDict(curPlayer):
    global g_ClientHurtDict
    global g_UseSkillPlayerID
    g_ClientHurtDict = collections.OrderedDict()
    g_UseSkillPlayerID = 0
    
    
def GetClientHurtByObj(objID, objType):
    global g_ClientHurtDict
    return g_ClientHurtDict.get((objID, objType), [])
# ´æÔÚ¿Í»§¶Ë¼ÆËãÇé¿ö ²»¹ã²¥ ÑéËãÉ˺¦
def isClientHurtValue(objID, objType):
    global g_ClientHurtDict
    result = g_ClientHurtDict.get((objID, objType), [])
    if not result:
        return False
    
    if result[1] == 0:
        return False
    
    return True
# ¼¼ÄÜ¿ªÊ¼³õʼ»¯¿Í»§¶ËÉËѪÁбí
def InitClientHurtDict(curPlayer, curSkill, hurtList):
    global g_ClientHurtDict
    global g_UseSkillPlayerID
    ClearClientHurtDict(curPlayer)
    
    #¼¼Äܹ¥»÷×î´óÊýÁ¿
    hurtCount = SkillCommon.GetSkillArea_Atk_Count(curPlayer, curSkill)
    if len(hurtList) > hurtCount:
        # ¿Í»§¶ËÄ¿±ê¹ý¶à
        return False
    
#    mapType = GameWorld.GetMap().GetMapFBType()
    # Ò°ÍâС¹Ö»òÕ߯äËûÖ¸¶¨µÄ¹ÖΪÁ˸ü¼°Ê±µÄ´ò»÷¸Ð£¬Óɿͻ§¶Ë¼ÆËã
    for hurobj in hurtList:
        hurtHP = hurobj.HurtHP + hurobj.HurtHPEx * ShareDefine.Def_PerPointValue
        if hurtHP == 0:
            g_ClientHurtDict[(hurobj.ObjID, hurobj.ObjType)] = [hurtHP, hurobj.AttackType]
            continue
        if hurobj.ObjType != IPY_GameWorld.gotNPC:
            # ·ÇNPC
            return False
        
#        if mapType != IPY_GameWorld.fbtNull:
#            # ·ÇÆÕͨµØÍ¼£¬ºóÐø¿É¼ÓÈëÖ¸¶¨Ìõ¼þ
#            return False
        
        curTag = GameWorld.GetObj(hurobj.ObjID, hurobj.ObjType)
        if not curTag:
            return False
        
        if curTag.GetIsBoss() != 0:
            # ·ÇС¹Ö
            return False
        
        if (hurobj.ObjID, hurobj.ObjType) in g_ClientHurtDict:
            # ÖØ¸´¶ÔÏó
            return False
        
        g_ClientHurtDict[(hurobj.ObjID, hurobj.ObjType)] = [hurtHP, hurobj.AttackType]
    
    g_UseSkillPlayerID = curPlayer.GetID()
    return True
#---------------------------------------------------------------------    
# ·Ç¿Í»§¶ËÍæ¼ÒÊͷŵļ¼ÄÜ
def IsPlayerUseSkill(attacker, curSkill):
    if attacker.GetGameObjType() != IPY_GameWorld.gotPlayer:
        return False
    
    if not curSkill:
        # Íæ¼ÒÆÕͨҲÊǼ¼ÄÜ£¬Õý³£ÊDz»»á×ßµ½Õâ±ß
        return False
    
    if GetUseSkillPlayerID() != attacker.GetID():
        # ·ÇÊÍ·ÅÕß
        return False
    
    useSkillData = attacker.GetUseSkill()
    if useSkillData and curSkill.GetSkillTypeID() != useSkillData.GetSkillTypeID():
        # ĬÈÏȺ¹¥¸½¼Ó´¥·¢buffµÄ¶ÔÏóÓë¹¥»÷¶ÔÏóÒ»ÖÂ
        if not SkillCommon.IsBuff(curSkill):
            return False
    
    
    if not GetClientHurtDict():
        return False
    
    #GameWorld.DebugLog("IsPlayerUseSkill -%s"%curSkill.GetSkillID())
    return True
    
## Êͷż¼ÄÜͨÓüì²é
# @param curPlayer Íæ¼ÒʵÀý
# @param curSkill ¼¼ÄÜʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÕæ, ¼ì²éͨ¹ý¿ÉÒÔÊÍ·Å
# @remarks Êͷż¼ÄÜͨÓüì²é
def CheckSkillCondition(curPlayer, curSkill, tick):
    if curPlayer.GetGMForbidenFight():
        #Play_Attack_Null ¶Ô²»Æð£¬ÄúÒѱ»GM½ûÖ¹Õ½¶·£¬¹¥»÷ʧ°Ü
        PlayerControl.NotifyCode(curPlayer , "Play_Attack_Null")
        return
    
    if GameObj.GetHP(curPlayer) <= 0:
        #Íæ¼ÒÒѾËÀÍö
        PlayerControl.NotifyCode(curPlayer, "PK_chenxin_612029")
        return False
    
    #Íæ¼Òµ±Ç°×´Ì¬
    curPlayerAction = curPlayer.GetPlayerAction()
    
    if curPlayerAction not in ChConfig.Def_PlayerCanAttackState:
        #״̬ÅжÏ, Ö»ÓÐÔÚ¿ÕÏÐ״̬, ²Å¿ÉÒÔ¹¥»÷
        PlayerControl.NotifyCode(curPlayer, "PK_chenxin_612029")
        return False
    
    if not curSkill:
        #Íæ¼ÒûÓÐÕâ¸ö¼¼ÄÜ
        PlayerControl.NotifyCode(curPlayer, "UseMagicLost02")
        return False
    
    #±»¶¯¼¼ÄÜÎÞ·¨Ê¹ÓÃ
    if SkillCommon.isPassiveSkill(curSkill):
        return False
    
    skillTypeID = curSkill.GetSkillTypeID()
    #===========================================================================
    # if SkillCommon.CheckPlayerAtkInterval(curPlayer, skillTypeID, tick):
    #    return False
    #===========================================================================
    
    #1:¼ì²é,ÊÇ·ñÊǵ±Ç°Ö°Òµ¼¼ÄÜ
    if not SkillCommon.CheckSkillJob(curPlayer, curSkill):
        PlayerControl.NotifyCode(curPlayer, "UseMagicLost09")
        return False
    
    #2:¼ì²é×Ë̬¼¼ÄÜ
#    stateSkillReq = curSkill.GetStateSkillReq()
#    if stateSkillReq != 0 :
#        buffState = curPlayer.GetBuffState()
#        if buffState.FindBuff(stateSkillReq) == None:
#            PlayerControl.NotifyCode(curPlayer, "GeRen_mx_774664")
#            return False
#        
    
    #4:¼ì²é¼¼ÄÜרÓÃCDʱ¼ä
    playerSkill = curPlayer.GetSkillManager().FindSkillBySkillTypeID(skillTypeID)
    
    if not playerSkill:
        PlayerControl.NotifyCode(curPlayer, "UseMagicLost02")
        return False
    #»¹ÔÚÀäȴʱ¼äÄÚÎÞ·¨ÊÍ·Å
    if SkillCommon.RefreshSkillRemainTime(playerSkill, tick) != 0:
        #PlayerControl.NotifyCode(curPlayer, "UseSkillCDLimit")
        #AttackFailNotify(curPlayer, curSkill, ChConfig.SkillFail_CD)
        playerSkill.Sync_Skill()
        return False
    #5:¼ì²éÍæ¼ÒµÄħ·¨ÖµÊÇ·ñ¹»ÓÃÕâ¸ö¼¼ÄÜ
    #===========================================================================
    # if curPlayer.GetMP() < curSkill.GetMP():
    #    curPlayer.Notify_AttackFail(0, 0, 0, 0, IPY_GameWorld.afrMP)
    #    PlayerControl.NotifyCode(curPlayer, "MagicLack")
    #    ChItem.UseMagicPotion(curPlayer, tick)
    #    
    #    return False
    #===========================================================================
#        #×Ô¶¯ºÈÀ¶
#        if not ChItem.UseMagicPotion(curPlayer, tick):
#            curPlayer.Notify_AttackFail(0, 0, 0, 0, IPY_GameWorld.afrMP)
#            PlayerControl.NotifyCode(curPlayer, "MagicLack")
#            return False
    
    #6:¼ì²éÍæ¼ÒµÄXPµãÊýÊÇ·ñ¹»ÓÃÕâ¸ö¼¼ÄÜ
#    curSkillNeedXP = curSkill.GetXP()
#    
#    if curSkillNeedXP > 0 and curPlayer.GetXP() < curSkillNeedXP:
#        curPlayer.Notify_AttackFail(0, 0, 0, 0, IPY_GameWorld.afrXP)
#        PlayerControl.NotifyCode(curPlayer, "PK_liubo_917284")
#        GameWorld.DebugLog("¼ì²éÍæ¼ÒµÄXPµãÊýÊÇ·ñ¹»ÓÃÕâ¸ö¼¼ÄÜ")
#        return False
#    
#    #7:¼ì²éÍæ¼ÒµÄHPÊÇ·ñ×ã¹»
#    curSkillNeedHP = curSkill.GetHP()
#    
#    if curSkillNeedHP > 0 and GameObj.GetHP(curPlayer) < curSkillNeedHP:
#        curPlayer.Notify_AttackFail(0, 0, 0, 0, IPY_GameWorld.afrHP)
#        PlayerControl.NotifyCode(curPlayer, "PK_jin_0")
#        GameWorld.DebugLog("¼ì²éÍæ¼ÒµÄHPÊÇ·ñ×ã¹»")
#        return False
#    
#    #8:Ê©·¨²ÄÁϼì²é
#    if not __CheckSkillUseItem(curPlayer , curSkill):
#        #UseMagicLost10 Ê©·¨²ÄÁϲ»×ã
#        PlayerControl.NotifyCode(curPlayer, "UseMagicLost10")
#        GameWorld.DebugLog("Ê©·¨²ÄÁϲ»×ã")
#        return False
    
#===============================================================================
#    #9:ÎäÆ÷ÏûºÄ×Óµ¯¼ì²é
#    if not ItemControler.CheckAttackConsumeArrow(curPlayer, True):
#        #GameWorld.Log("×Óµ¯¼ì²é²»Âú×ã")
#        return False
#===============================================================================
    
    #10:ÌØÊ⸱±¾²»ÄÜʹÓü¼ÄÜ
    if FBLogic.OnForbidUseSkill(curPlayer , tick):
        #FB_Skill_Lost ¶Ô²»Æð£¬¸Ã³¡¾°ÎÞ·¨Ê¹Óü¼ÄÜ£¬Ê¹Óü¼ÄÜʧ°Ü
        PlayerControl.NotifyCode(curPlayer, "FB_Skill_Lost")
        return False
    
    return True
#---------------------------------------------------------------------
##¼ì²é¼¼ÄÜÊ©·¨²ÄÁÏ
# @param curPlayer Íæ¼ÒʵÀý
# @param curSkill ¼¼ÄÜʵÀý
# @return ·µ»ØÖµÕæ, ÓµÓÐ×ã¹»µÄ²ÄÁÏ
# @remarks ¼ì²é¼¼ÄÜÊ©·¨²ÄÁÏ
def __CheckSkillUseItem(curPlayer , curSkill):
    useItemID = curSkill.GetUseItemID() 
    useItemCount = curSkill.GetUseItemCount()
    
    if not useItemID or not useItemCount:
        return True
    
    item = ItemCommon.FindItemInPackByItemID(curPlayer , useItemID , IPY_GameWorld.rptItem)
    
    if not item:
        return False
    
    return (item.GetCount() >= useItemCount)
#------------------------NPCʹÓü¼ÄÜ
##NPCʹÓÃÎÞ¶ÔÏó¼¼ÄÜ
# @param curNPC NPCʵÀý
# @param curSkill ¼¼ÄÜʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÕæ, ¼ì²éͨ¹ý
# @remarks ×Ô¶¨Ò庯Êý, NPCʹÓÃÎÞ¶ÔÏó¼¼ÄÜ
def NPCUseSkill(curNPC, curSkill, tick):
    if curSkill.GetCastTime():
        return NPCUseSkillWarn(curNPC, None, curSkill, tick)
    return DoLogic_UseSkill(curNPC, curNPC, curSkill, tick)
#---------------------------------------------------------------------
##NPCʹÓÃÓжÔÏó¼¼ÄÜ
# @param curNPC NPCʵÀý
# @param curTag ¶ÔÏóʵÀý
# @param curSkill ¼¼ÄÜʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÕæ, ¼ì²éͨ¹ý
# @remarks ×Ô¶¨Ò庯Êý, NPCʹÓÃÓжÔÏó¼¼ÄÜ
def NPCUseSkillTag(curNPC, curTag, curSkill, tick):
    skillTag = GetSkillAffectTag(curSkill)
    if skillTag == ChConfig.Def_UseSkillTag_AppointNPC:
        # Ö¸¶¨ÊͷŵÄNPCID ºÍ Def_UseSkillTag_AppointNPC ´îÅäʹÓÃ
        curTag = GetAppointNPCBySkillEffect(curSkill)
        if not curTag:
            return False
    
    if not NPCCanUseSkillTag(curNPC, curTag, curSkill, tick):
        return False
    
    NPCAttackMovePos(curNPC, curTag, curSkill)
    
    if curSkill.GetCastTime():
        return NPCUseSkillWarn(curNPC, curTag, curSkill, tick)
    
    result = DoLogic_UseSkill(curNPC, curTag, curSkill, tick)
    if result and curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_AtkMovePosX) != 0:
        curNPC.ChangePos(curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_AtkMovePosX), 
                         curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_AtkMovePosY))
        curNPC.SetDict(ChConfig.Def_NPC_Dict_AtkMovePosX, 0)
        curNPC.SetDict(ChConfig.Def_NPC_Dict_AtkMovePosY, 0)
        
    return result
# Ö¸¶¨ÊͷŵÄNPCID ºÍ Def_UseSkillTag_AppointNPC ´îÅäʹÓÃ
def GetAppointNPCBySkillEffect(curSkill):
    npcID = 0
    effectID = ChConfig.Def_Skill_Effect_AppointNPC
    for i in xrange(0, curSkill.GetEffectCount()):
        curEffect = curSkill.GetEffect(i)
        curEffectID = curEffect.GetEffectID()
        
        if not curEffectID:
            #²ß»®ÓпÉÄÜÖÐ;ɾ³ý£¬²»ÓÃreturn
            continue
        
        #²»ÊÇÐèÒªµÄЧ¹û
        if curEffectID != effectID:
            continue
        npcID = curEffect.GetEffectValue(0)
        break
    if not npcID:
        return None
    return GameWorld.FindNPCByNPCID(npcID)
# ¼ÆËãNPC¼¼ÄÜÎ»ÒÆ×ø±ê£¬Ô¤¾¯ºÍ·ÇÔ¤¾¯¶¼¿ÉÒÔÓÃ
def NPCAttackMovePos(curNPC, curTag, curSkill):
    if curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_AtkMovePosX) != 0:
        return
    
    # Õ½¶·Î»ÒƼ¼ÄÜ
    skillEffect = SkillCommon.GetSkillEffectByEffectID(curSkill, ChConfig.Def_Skill_Effect_AttackMove)
    if not skillEffect:
        return
    
    moveDist = skillEffect.GetEffectValue(0)
    if moveDist > 0:
        #Ö±Ï߳巿£¬Ô¤¾¯Îª¾ØÐΣ¬È¡ÓëÄ¿±êÖ±½ÓµÄ×îÔ¶¾àÀ룬´Ë´¦Ò»¶¨ÊÇÒªÓй¥»÷Ä¿±ê
        tagPosX = curTag.GetPosX()
        tagPosY = curTag.GetPosY()
        for dist in xrange(moveDist, 1, -1):
            posX, posY = GameWorld.PosInLineByDistEx(dist, tagPosX, tagPosY, curNPC.GetPosX(), curNPC.GetPosY())
            if not GameWorld.GetMap().CanMove(posX, posY):
                continue
            break
        
        if not GameWorld.GetMap().CanMove(posX, posY):
            posX, posY = tagPosX, tagPosY
    else:
        # ·ÉÔ¾Ðͼ¼ÄÜ£¬Ô¤¾¯ÎªÄ¿±êµãÔ²ÐÎ
        posX = curTag.GetPosX() if curTag else curNPC.GetPosX()
        posY = curTag.GetPosY() if curTag else curNPC.GetPosY()
        
    curNPC.SetDict(ChConfig.Def_NPC_Dict_AtkMovePosX, posX)
    curNPC.SetDict(ChConfig.Def_NPC_Dict_AtkMovePosY, posY)
    return
        
def NPCUseSkillWarn(curNPC, curTag, curSkill, tick):
    ## NPCʹÓü¼ÄÜÔ¤¾¯
    
    # ÓÐÊ©·¨Ê±¼äµÄ²Å½øÐÐÔ¤¾¯
    warnTime = curSkill.GetCastTime()
    if not warnTime:
        return False
    
    # ¶àµãÔ¤¾¯ÔÝʱֻ֧³ÖÕÙ»½¼¼ÄÜ
    if curSkill.GetSkillType() == ChConfig.Def_SkillType_Summon:
        warnPosList = []
        curSummonID = curSkill.GetEffect(0).GetEffectValue(0)
        curSummonCount = max(curSkill.GetEffect(0).GetEffectValue(1), 1)  # µ¥´ÎÕÙ»½ÊýÁ¿
        summonCountAll = max(curSkill.GetEffect(0).GetEffectValue(2), 1)  # ×ÜÕÙ»½ÊýÁ¿
        curSummonNPCCnt = SkillCommon.GetSummonCountByNPCID(curNPC, curSummonID)
        if curSummonNPCCnt >= summonCountAll:
            return False
        
        canSummonCnt = min(curSummonCount, summonCountAll - curSummonNPCCnt)
        if curSkill.GetAtkType() == 16:
            # À౩·çÑ©¼¼ÄÜ ¶ÔÄ¿±ê¶¨µãÊÍ·Å£¬Ö»Ö§³Öµ¥µã
            warnPosList.append([curTag.GetPosX() , curTag.GetPosY()])
        else:
            # ÒÔNPC×Ô¼ºÎªÖÐÐĵ㣬·¶Î§ÄÚËæ»úµã
            atkDist = ChConfig.Def_DropItemDist if not curSkill.GetAtkDist() else curSkill.GetAtkDist()
            #GameWorld.DebugLog("¿ªÊ¼Ëæ»úÕÙ»½Ô¤¾¯×ø±êµã: curNPC.GetPosX()=%s, curNPC.GetPosY()=%s, atkDist=%s" % (curNPC.GetPosX(), curNPC.GetPosY(), atkDist))
            for i in xrange(canSummonCnt):
                resultPos = GameMap.GetEmptyPlaceInArea(curNPC.GetPosX(), curNPC.GetPosY(), atkDist)
                warnPosList.append([resultPos.GetPosX() , resultPos.GetPosY()])
        
    else:            
        skillEffect = SkillCommon.GetSkillEffectByEffectID(curSkill, ChConfig.Def_Skill_Effect_RandWarn)
        if skillEffect:
            # ÒÔNPC×Ô¼ºÎªÖÐÐĵ㣬·¶Î§ÄÚËæ»úµã
            atkDist = curSkill.GetAtkDist() - 1
                
            fromX, toX = max(curNPC.GetPosX() - atkDist, 1), curNPC.GetPosX() + atkDist
            fromY, toY = max(curNPC.GetPosY() - atkDist, 1), curNPC.GetPosY() + atkDist
            warnPoints = []
            for x in range(fromX, toX, 3):
                for y in range(fromY, toY, 3):
                    warnPoints.append([x, y])
            
            warnPosList = random.sample(warnPoints, min(skillEffect.GetEffectValue(0)-1, len(warnPoints)))
            warnPosList.append([curTag.GetPosX(), curTag.GetPosY()])
            #GameWorld.DebugLog("¶àµãÔ¤¾¯×ø±ê %s-%s-%s"%(curNPC.GetPosX(), curNPC.GetPosY(), warnPosList))
        else:
            # Õ½¶·Î»ÒƼ¼ÄÜ
            if curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_AtkMovePosX) != 0:
                warnPosList = [[curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_AtkMovePosX), curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_AtkMovePosY)]]
            else:
                #·ÇÎ»ÒÆÔ¤¾¯
                posX = curTag.GetPosX() if curTag else curNPC.GetPosX()
                posY = curTag.GetPosY() if curTag else curNPC.GetPosY()
                warnPosList = [[posX, posY]]
                
    if not warnPosList:
        GameWorld.ErrLog("ûÓÐÔ¤¾¯×ø±êÐÅÏ¢£¡npcID=%s,skillID=%s" % (curNPC.GetNPCID(), curSkill.GetSkillID()))
        return False
    
    skillID = curSkill.GetSkillID()
    curNPC.SetDict(ChConfig.Def_NPC_Dict_SkillWarnSkillID, skillID)
    curNPC.SetDict(ChConfig.Def_NPC_Dict_SkillWarnTime, warnTime)
    curNPC.SetDict(ChConfig.Def_NPC_Dict_SkillWarnPosCnt, len(warnPosList))
    for i, posInfo in enumerate(warnPosList):
        curNPC.SetDict(ChConfig.Def_NPC_Dict_SkillWarnPosX % i, posInfo[0])
        curNPC.SetDict(ChConfig.Def_NPC_Dict_SkillWarnPosY % i, posInfo[1])
    curNPC.SetCurAction(IPY_GameWorld.laNPCSkillWarning)
    #GameWorld.DebugLog("½øÈë¼¼ÄÜÔ¤¾¯×´Ì¬: npcID=%s,skillID=%s,warnPosList=%s,curTag=%s" 
    #                   % (curNPC.GetNPCID(), skillID, warnPosList, 0 if not curTag else curTag.GetID()))
    # ¹ã²¥Ô¤¾¯
    NotifyNPCSkillWarn(curNPC, tick)
    return True
def NotifyNPCSkillWarn(curNPC, tick):
    # ¹ã²¥NPCÊͷż¼ÄÜÔ¤¾¯
    if curNPC.GetCurAction() != IPY_GameWorld.laNPCSkillWarning:
        return
    
    warnSkillID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_SkillWarnSkillID)
    warnTime = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_SkillWarnTime)
    remainTime = warnTime - (tick - curNPC.GetActionTick()) 
    if remainTime <= 0:
        return
    
    sendPack = ChPyNetSendPack.tagMCNPCSkillWarn()
    sendPack.Clear()
    sendPack.ObjID = curNPC.GetID()
    sendPack.NPCID = curNPC.GetNPCID()
    sendPack.SkillID = warnSkillID
    sendPack.WarnTime = warnTime
    sendPack.RemainTime = remainTime
    sendPack.WarnPosList = []
    posCnt = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_SkillWarnPosCnt)
    for i in xrange(posCnt):
        pos = ChPyNetSendPack.tagMCNPCSkillWarnPos()
        pos.PosX = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_SkillWarnPosX % i)
        pos.PosY = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_SkillWarnPosY % i)
        sendPack.WarnPosList.append(pos)
    sendPack.WarnPosCnt = len(sendPack.WarnPosList)
    curNPC.NotifyAll(sendPack.GetBuffer(), sendPack.GetLength())
    return
##¼ì²éNPCʹÓÃÓжÔÏó¼¼ÄÜ
# @param curNPC NPCʵÀý
# @param curTag ¶ÔÏóʵÀý
# @param curSkill ¼¼ÄÜʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÕæ, ¼ì²éͨ¹ý
def NPCCanUseSkillTag(curNPC, curTag, curSkill, tick):
    skillTag = GetSkillAffectTag(curSkill)
    if skillTag == ChConfig.Def_UseSkillTag_AppointNPC:
        return True
    
    #---¶ÔÏóÅж¨---
    if IsToPetOwnerSkill(curNPC, skillTag):
        return True
    
    #---ÕÙ»½ÊÞ¶ÔÖ÷ÈË---
    if IsSummomToOwnerSkill(curNPC, skillTag, curTag):
        return True
    
    curSkillUseTag = SkillShell.GetSkillAffectTag(curSkill)
    if curSkillUseTag == ChConfig.Def_UseSkillTag_CanAttackPlayer:
        if curTag.GetGameObjType() != IPY_GameWorld.gotPlayer:
            return False
    
    #---¹ØÏµÅж¨---
    relation = BaseAttack.GetTagRelation(curNPC, curTag, curSkill, tick)[0]
    if skillTag == ChConfig.Def_UseSkillTag_FriendNPC and relation == ChConfig.Type_Relation_Friend:
        return True
    if relation != ChConfig.Type_Relation_Enemy:
        return False
    
    return True
def IsNPCSkillResist(curNPC):
    ## NPCÊÇ·ñ¼¼Äֿܵ¹£¬¶ÔÓ¦¼¼ÄܱíÖÐÉ˺¦ÀàÐÍHurtTypeΪ3µÄ¼¼ÄÜ£¬¼´¶ÔbossÎÞЧµÄ¼¼ÄÜ
    
    if curNPC.GetCurAction() == IPY_GameWorld.laNPCSkillWarning:
        #GameWorld.DebugLog("Ô¤¾¯×´Ì¬ÏÂĬÈϵֿ¹")
        return True
    
    bossIpyData = IpyGameDataPY.GetIpyGameDataNotLog("BOSSInfo", curNPC.GetNPCID())
    if bossIpyData and bossIpyData.GetSkillResist():
        return True
    
    return False
##ÊÇ·ñÕÙ»½ÊÞ¶ÔÖ÷ÈËʹÓü¼ÄÜ
# @param curNPC NPCʵÀý
# @param skillTag ¼¼ÄÜЧ¹û¶ÔÏó
# @param curTag ¶ÔÏóʵÀý
# @return ·µ»ØÖµÕæ, ¼ì²éͨ¹ý
def IsSummomToOwnerSkill(curNPC, skillTag, curTag):
    # ·ÇÓѺÃÄ¿±ê
    if skillTag not in [ChConfig.Def_UseSkillTag_Friend, ChConfig.Def_UseSkillTag_SummonMaster]:
        return False
    
    # ²»ÊÇÕÙ»½ÊÞ
    if curNPC.GetGameNPCObjType() != IPY_GameWorld.gnotSummon:
        return False
    
    owner = NPCCommon.GetSummonNPCOwner(IPY_GameWorld.gotNPC, curNPC)
    if not owner:
        owner = NPCCommon.GetSummonNPCOwner(IPY_GameWorld.gotPlayer, curNPC)
    if not owner:
        return False
    
    return GameWorld.IsSameObj(curTag, owner)
    
##ÊÇ·ñ³èÎï¶ÔÖ÷ÈËʹÓü¼ÄÜ
# @param curNPC NPCʵÀý
# @param skillTag ¼¼ÄÜЧ¹û¶ÔÏó
# @return ·µ»ØÖµÕæ, ¼ì²éͨ¹ý
def IsToPetOwnerSkill(curNPC, skillTag):
    if skillTag != ChConfig.Def_UseSkillTag_PetMaster:
        return False
    if not PetControl.IsPet(curNPC):
        GameWorld.ErrLog("NPCID %s AI %s ·Ç³èÎÎÞ·¨»ñµÃÖ÷ÈËÊͷż¼ÄÜ"%(curNPC.GetNPCID(), curNPC.GetAIType()))
        return False
    
    petOwner = PetControl.GetPetOwner(curNPC)
    
    if petOwner == None:
        GameWorld.ErrLog("³èÎ%s£©¶ÔÖ÷ÈËÊͷż¼ÄÜ£¬ÕÒ²»µ½Ö÷ÈË"%curNPC.GetRolePet().PetID)
        return False
        
    return True
##¹ºÍåóÆÕ¹¥¼¼ÄÜ
# @param curPlayer Íæ¼ÒʵÀý
# @param skillID ¼¼ÄÜID
# @return ÌØ±ðµÄÆÕ¹¥ID
#===============================================================================
# def GetBowNormalAttackID(curPlayer, skillID):
#    #Ë¢ÐÂÈËÎï¹¥»÷¾àÀë
#    playerEquip = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptEquip)
#    #»ñµÃµ±Ç°ÈËÎïʹÓõÄÎäÆ÷
#    curUseWeapon = playerEquip.GetAt(ShareDefine.retWeapon)
#    curUseWeapon2 = playerEquip.GetAt(ShareDefine.retWeapon2)
#    #¿ÕÊÖ
#    if curUseWeapon.IsEmpty() and curUseWeapon2.IsEmpty():
#        return skillID
#    
#    if curUseWeapon.GetType() in [ChConfig.Def_ItemType_Crossbow, ChConfig.Def_ItemType_Bow]:
#        curEffect = ItemCommon.GetItemEffectByEffectID(curUseWeapon, ChConfig.Def_Effect_WeaponAttack)
#        if curEffect == None:
#            GameWorld.DebugAnswer(curPlayer, 'ûÓÐÎïÆ·Ð§¹ûID %s'%ChConfig.Def_Effect_WeaponAttack)
#            return skillID
#        
#        return curEffect.GetEffectValue(0)
#    
#    if curUseWeapon2.GetType() in [ChConfig.Def_ItemType_Crossbow, ChConfig.Def_ItemType_Bow]:
#        curEffect = ItemCommon.GetItemEffectByEffectID(curUseWeapon2, ChConfig.Def_Effect_WeaponAttack)
#        if curEffect == None:
#            GameWorld.DebugAnswer(curPlayer, 'ûÓÐÎïÆ·Ð§¹ûID %s'%ChConfig.Def_Effect_WeaponAttack)
#            return skillID
#        
#        return curEffect.GetEffectValue(0)
#    
#    return skillID
#===============================================================================
#===============================================================================
# //B4 02 ¶ÔÏó»÷ÍË #tagCMNPCBeatBack
# 
# struct    tagCMNPCPos
# {
#    DWORD        ObjID;
#    WORD        PosX;
#    WORD        PosY;
# };
# 
# struct    tagCMNPCBeatBack
# {
#    tagHead        Head;
#    BYTE        Count;
#    BYTE        ObjType;
#    tagCMNPCPos    NPCPosList[Count];
# 
# };
#===============================================================================
def NPCBeatBack(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    mapType = GameWorld.GetMap().GetMapFBType()
    # Íæ¼Ò±»NPC»÷ÍË£¬´Ë´¦Ó¦¸Ã¿ØÖÆÏÂCDºÍ¾àÀë
    if clientData.ObjType == IPY_GameWorld.gotPlayer and clientData.Count == 1:
        pos = clientData.NPCPosList[0]
        if pos.ObjID != curPlayer.GetID():
            return
        
        if GameObj.GetHP(curPlayer) <= 0:
            return
        
        #=======================================================================
        # if mapType == IPY_GameWorld.fbtNull:
        #    return
        #=======================================================================
        if not GameWorld.GetMap().CanMove(pos.PosX, pos.PosY):
            return
        
        curPlayer.StopMove()
        curPlayer.ChangePos(pos.PosX, pos.PosY)
        #Êä³ö±ãÓÚ²éÎ»ÒÆÍâ¹Ò
        GameWorld.Log("---Íæ¼Ò±»»÷ÍË %s"%curPlayer.GetID())
        return
    
    
    '''
    NPC»÷ÍËÂß¼£¬ÊÊÓÃÓÚС¹ÖºÍ¹¥»÷ÓиöÊýÏÞÖÆµÄÓÎÏ·Éè¼Æ
    '''
    count = min(clientData.Count, 10)
    for i in range(count):
        npcPos = clientData.NPCPosList[i]
        npcObj = GameWorld.GetObj(npcPos.ObjID, IPY_GameWorld.gotNPC)
        if not npcObj:
            continue
        if npcObj.GetIsBoss() > ChConfig.Def_NPCType_Ogre_Super and mapType == IPY_GameWorld.fbtNull:
            # Ò°ÍâBOSS²»±»ÍÆ
            continue
        
        if GameObj.GetHP(npcObj) <= 0:
            continue
        
        if not GameWorld.GetMap().CanMove(npcPos.PosX, npcPos.PosY):
            continue
        
        if GameWorld.GetDist(npcObj.GetPosX(), npcObj.GetPosY(), npcPos.PosX, npcPos.PosY) > 6:
            # µ¥´ÎÎ»ÒÆ²»³¬¹ý3Ã×
            continue
        
        if npcObj.GetCurAction() == IPY_GameWorld.laNPCSkillWarning:
            #GameWorld.DebugLog("NPCÔ¤¾¯Öв»¿É±»»÷ÍË!")
            continue
        npcObj.StopMove()
        npcObj.ChangePos(npcPos.PosX, npcPos.PosY)
        BeatBackMove(curPlayer, npcObj)
    return
# Õë¶ÔNPC±»ÍƳöÔ¶¾àÀëÒ»Ö±¿¨Ç½½ÇÎÊÌ⣬·¨±¦ÌôÕ½¸±±¾ÌØÊâ´¦ÀíΪ³¬¹ý4Ã× NPC×Ô¶¯»ØÍËһЩ
def BeatBackMove(curPlayer, npcObj):
    if GameWorld.GetMap().GetMapID() != ChConfig.Def_FBMapID_MagicWeapon:
        return
    if npcObj.GetCurAction() == IPY_GameWorld.laNPCSkillWarning:
        return
    
    posMap = npcObj.GetRefreshPosAt(npcObj.GetCurRefreshPointIndex())
    if not posMap:
        return
    #·¶Î§Ð£Ñé
    posMapX = posMap.GetPosX()
    posMapY = posMap.GetPosY()
    if GameWorld.GetDist(npcObj.GetPosX(), npcObj.GetPosY(), posMapX, posMapY) < 8:
        # µ¥´ÎÎ»ÒÆ²»³¬¹ý5Ã×
        return
    npcControl = NPCCommon.NPCControl(npcObj)
    moveDestX, moveDestY = npcControl.GetMoveNearPosEx(posMapX, posMapY, 5)
    npcObj.Move(moveDestX, moveDestY)
    return
#===============================================================================
# //B4 03 ÎüÒýNPC³ðºÞ #tagNPCAttention
# 
# struct    tagCMNPCInfo
# {
#    DWORD        ObjID;
# };
# 
# struct    tagNPCAttention
# {
#    tagHead        Head;
#    BYTE        Count;
#    tagCMNPCInfo    NPCs[Count];
# 
# };
#===============================================================================
def NPCAttention(index, clientData, tick):
    return
    #===========================================================================
    # '''
    # NPC³ðºÞÎüÒý£¬Óɿͻ§¶Ë¾ö¶¨£¬ÊÊÓÃÓÚС¹Ö
    # '''
    # curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    # if GameObj.GetHP(curPlayer) <= 0:
    #    return
    # 
    # if not curPlayer.GetVisible():
    #    return
    # 
    # playerID = curPlayer.GetID()
    # count = min(clientData.Count, 8)
    # for i in range(count):
    #    objID = clientData.NPCs[i]
    #    npcObj = GameWorld.GetObj(objID, IPY_GameWorld.gotNPC)
    #    if not npcObj:
    #        continue
    #    if npcObj.GetIsBoss() > ChConfig.Def_NPCType_Ogre_Super:
    #        continue
    #    
    #    npcAngry = npcObj.GetNPCAngry()
    #    angryValue = npcAngry.FindNPCAngry(playerID, IPY_GameWorld.gotPlayer)
    #    
    #    if angryValue != None and GameObj.GetAngryValue(angryValue) != 0 :
    #        #¸Ã¶ÔÏóÒѾÔÚ³ðºÞÁбíÖÐ,²»Öظ´Ìí¼Ó
    #        continue
    #    
    #    if not AttackCommon.CheckCanAttackTag(npcObj, curPlayer):
    #        continue
    #    
    #    relation = BaseAttack.GetTagRelation(npcObj, curPlayer, None, tick)[0]
    #    if relation != ChConfig.Type_Relation_Enemy:
    #        continue
    #    
    #    npcControl = NPCCommon.NPCControl(npcObj)
    #    npcControl.AddObjToAngryList(curPlayer, ChConfig.Def_NPC_SeePlayerAddAngry)
    #    npcObj.GetNPCAngry().Resort(tick)
    #    GameWorld.DebugLog("NPCAttention ³É¹¦À³ðºÞ %s"%objID)
    #        
    # return
    #===========================================================================
#===============================================================================
# //B4 01 ´øÓжÔÏó¶ÓÁкÍ×ø±êµÄ¼¼ÄÜ #tagCMUseSkillEx ¸Ä¿Í»§¶Ë¼ÆËãѪÁ¿ºÏ²¢°ü
# 
# struct    tagCMUseSkillEx
# {
#    tagHead        Head;
#    WORD        SkillID;
#    WORD        PosX;    //¹¥»÷Æðµã
#    WORD        PosY;    
#    WORD        TagPosX;        //Ä¿±êµã
#    WORD        TagPosY;
#    BYTE        TagType;        //OBJÀàÐÍ
#    DWORD        TagID;
# };
#===============================================================================
# ·ÏÆúʹÓÃB4 05
#===============================================================================
# def UseSkillExEx(index, clientData, tick):
#    '''
#        Pos ¹¥»÷ÆðµãΪ¿Í»§¶ËµÄ½Çɫ׸±ê£¬ÒÔÐÅÈοͻ§¶ËÅжϹ¥»÷¾àÀ룬¼æÈÝ´¦Àí
#        TagPos ΪĿ±êµã£¬ÒԴ˾ö¶¨¼¼Äܹ¥»÷·½Ïò£¬Í¨Öª¹¥»÷³É¹¦
#        TagID Ö÷Ä¿±ê£¬Èº¹¥ÉèÖÃÖ÷Ä¿±êΪÓÅÏȹ¥»÷¶ÔÏó£¬ÈÃÄ¿±ê¸üÈÝÒ×±»»÷ÖÐ
#    '''
#    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
#    curPlayerID = curPlayer.GetID()
#     
#    #-----------»ñÈ¡·â°üÊý¾Ý
#    pack_SkillID = clientData.SkillID
#    pack_PosX = clientData.PosX
#    pack_PosY = clientData.PosY
#    tagPosX = clientData.TagPosX
#    tagPosY = clientData.TagPosY
#    tagType = clientData.TagType
#    tagID = clientData.TagID
#    
#    curSkill = curPlayer.GetSkillManager().FindSkillBySkillID(pack_SkillID)
#    if not curSkill:
#        #GameWorld.ErrLog('UseSkill findSkillErr = %s'%(pack_SkillID), curPlayerID)
#        return
# 
#    if not __CheckPlayerUseSkill_ClientPack(curPlayer, pack_PosX, pack_PosY, curSkill):
#        return
# 
#    #ʹÓü¼ÄÜÐÐΪ״̬, ¿Í»§¶ËÏÞÖÆ
#    if not OperControlManager.IsObjCanDoAction(curPlayer, 
#                                               ChConfig.Def_Obj_ActState_ClientSkill, 
#                                               curSkill.GetSkillOfSeries()):
#        return    
# 
# 
# 
#    #¼¤»îÍæ¼Ò,½â³ý´ôÖÍ
#    PlayerControl.SetIsNeedProcess(curPlayer, True)
#    
#    #´Ë´¦²»¼ì²éºÏ·¨ÐÔ, ÔÚÕæÕýÒªÓõÄʱºòÔÙ¼ì²é
#    curPlayer.ClearUseSkillRec()
#    curPlayer.SetUseSkill(curSkill.GetSkillData())
#    curPlayer.SetUseSkillPosX(tagPosX)
#    curPlayer.SetUseSkillPosY(tagPosY)
#    curPlayer.SetUseSkillTagType(tagType)
#    curPlayer.SetUseSkillTagID(tagID)
#    #ÉèÖù¥»÷ÆðµãÎªÍæ¼Ò×ÔÉí×ø±ê
#    curPlayer.SetAttackTargetPos(pack_PosX, pack_PosY)
#    
#    #ÒѾÔÚ¹¥»÷ÖÐ
#    if curPlayer.GetPlayerAction() == IPY_GameWorld.paAttack:
#        return
#    
#    # ÐèҪǰ×àÒ÷³ªÊͷż¼ÄÜÀ½ø¶ÈÌõ
#    if curSkill.GetCastTime() > 0:
#        GameWorld.DebugLog("----½ø¶ÈÌõ%s"%curSkill.GetCastTime())
#        PlayerControl.Sync_PrepareBegin(curPlayer, curSkill.GetCastTime(), IPY_GameWorld.pstSkill, pack_SkillID)
#        return
#    
#    #ÉèÖù¥»÷±ê־λ
#    PlayerControl.ChangePlayerAction(curPlayer, IPY_GameWorld.paAttack)
#    #Ö´ÐÐÕ½¶·Âß¼
#    PlayerState.ProcessFight(curPlayer, tick)
#    return
#===============================================================================
# ÌØÊâ˵Ã÷ChangePlayerAction -> SetPlayerAction ÖÐ ÔÚÀÌõ״̬»á֪ͨ Sync_PrepareEnd£¬Ä¬ÈϽø¶ÈÌõÀàÐÍ
# Sync_PrepareEnd ֪ͨ0²ÅËã½ø¶ÈÌõ³É¹¦£¬ÆäËûΪʧ°Ü£¬×Ôµ÷ÓÃÂ߼ʱÇë×¢Òâ
def SkillPrepareEnd(curPlayer, tick):
    curSkill = curPlayer.GetUseSkill()
    hasEffect = SkillCommon.GetSkillEffectByEffectID(curSkill, ChConfig.Def_Skill_Effect_PowerPart)
    if hasEffect:
        # ÐîÁ¦¼¼ÄÜÐè¼Ç¼´ÎÊý
        if curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_PowerPartCount) == 0:
            curPlayer.SetDict(ChConfig.Def_PlayerKey_PowerPartCount, hasEffect.GetEffectValue(0))
            
    #Sync_PrepareEnd() °üº¬ÔÚSetPlayerActionÖÐ֪ͨ
    curPlayer.SetPrepareState(0)  
    #ÉèÖù¥»÷±ê־λ
    PlayerControl.ChangePlayerAction(curPlayer, IPY_GameWorld.paAttack)
    #Ö´ÐÐÕ½¶·Âß¼
    PlayerState.ProcessFight(curPlayer, tick)
    return
def CheckClientAttackTick(curPlayer, clientTick, tick):
    Def_Attack_DelayTick = 5000
    # tick Îó²î¹ý´óÔò¹ýÂË
    if abs(clientTick - tick) > Def_Attack_DelayTick:
        curPlayer.Sync_ClientTick()
        GameWorld.DebugLog("tick Îó²î¹ý´óÔò¹ýÂË > 5000")
        return False
    
    if tick - curPlayer.GetDictByKey("CheckTick") > 60000:
        # 1·ÖÖÓ¾ÀÕýÒ»´Îtick,ͬʱÓÃÓÚÕ½¶·ºÍÒÆ¶¯µÄ¼ì²é
        curPlayer.SetMoveCount(0)
        curPlayer.SetDict("CheckTick", tick)
    
    
    # GetPlayerAttackTickΪ¼Ç¼µÄ¿Í»§¶Ëtick£¬Ð¡ÓڼǼÔòΪÒì³£
    if clientTick < curPlayer.GetPlayerAttackTick():
        GameWorld.DebugLog("¿Í»§¶Ëtick£¬Ð¡ÓڼǼÔòΪÒì³£")
        errCnt = curPlayer.GetMoveCount()
        curPlayer.SetMoveCount(errCnt + 1)
        if errCnt > 5:
            return False
    
    # ¹¥»÷¼ä¸ô¹ý¿ì
    if clientTick - curPlayer.GetPlayerAttackTick() < PlayerControl.GetAtkInterval(curPlayer)*0.7:
        GameWorld.DebugLog(" # ¹¥»÷¼ä¸ô¹ý¿ì %s - %s < %s"%(clientTick, curPlayer.GetPlayerAttackTick(), PlayerControl.GetAtkInterval(curPlayer)*0.75))
        errCnt = curPlayer.GetMoveCount()
        curPlayer.SetMoveCount(errCnt + 1)
        if errCnt > 5:
            return False
    
    #¼Ç¼¿Í»§¶ËµÄtick
    curPlayer.SetAttackTick(clientTick)
    return True
#===============================================================================
# //B4 05 ´øÉ˺¦¶ÓÁеĹ¥»÷ #tagCMSuperAtk
# 
# struct    tagSkillPosHurtObj
# {
#    BYTE        ObjType;
#    DWORD        ObjID;
#    BYTE        AttackType;        //±¬»÷, miss
#    DWORD        HurtHP;
#    DWORD        HurtHPEx;
# };
# 
# struct    tagCMSuperAtk
# {
#    tagHead        Head;
#    WORD        SkillID;
#    WORD        PosX;    //¹¥»÷Æðµã
#    WORD        PosY;    
#    WORD        TagPosX;        //Ä¿±êµã
#    WORD        TagPosY;
#    DWORD        WorldTick;
#    WORD        HurtCount;        //É˺¦ÊýÄ¿
#    tagSkillPosHurtObj        HurtList[HurtCount];        //size = HurtCount
# };
#===============================================================================
def UseSkillEx(index, clientData, tick):
    '''
        Óɿͻ§¶ËËÑË÷¶ÔÏó£¬Ð¡¹ÖÓɿͻ§¶Ë¼ÆËãÉ˺¦£¬·þÎñ¶Ë¿ØÖÆÉ˺¦Öµ·¶Î§
        ÆäËû¶ÔÏóÂß¼ÓÉ·þÎñ¶Ë´¦Àí
    '''
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    curPlayerID = curPlayer.GetID()
    
    #-----------»ñÈ¡·â°üÊý¾Ý
    pack_SkillID = clientData.SkillID
    pack_PosX = clientData.PosX
    pack_PosY = clientData.PosY
    tagPosX = clientData.TagPosX
    tagPosY = clientData.TagPosY
    clientTick = clientData.WorldTick
    hurtList = clientData.HurtList
    
    curSkill = curPlayer.GetSkillManager().FindSkillBySkillID(pack_SkillID)
    if not curSkill:
        #GameWorld.ErrLog('UseSkill findSkillErr = %s'%(pack_SkillID), curPlayerID)
        return
    if pack_SkillID != ChConfig.Def_SkillID_Somersault:
        # ·¹öÌØÊâ´¦Àí£¬ÊµÊ±ÏìÓ¦, ÓÉCD ×Ü¿ØÖÆ
        if not CheckClientAttackTick(curPlayer, clientTick, tick):
            AttackFailNotify(curPlayer, curSkill, ChConfig.SkillFail_AtkInterval)  
            curPlayer.Sync_ClientTick() 
            return
    #ÒѾÔÚ¹¥»÷ÖÐ
    if curPlayer.GetPlayerAction() == IPY_GameWorld.paAttack:
        AttackFailNotify(curPlayer, curSkill)
        return
    #ʹÓü¼ÄÜÐÐΪ״̬, ¿Í»§¶ËÏÞÖÆ    
    if not OperControlManager.IsObjCanDoAction(curPlayer, 
                                               ChConfig.Def_Obj_ActState_ClientSkill, 
                                               curSkill.GetSkillOfSeries(), curSkill):
        AttackFailNotify(curPlayer, curSkill)
        return    
    if not InitClientHurtDict(curPlayer, curSkill, hurtList):
        #GameWorld.ErrLog("InitClientHurtDict ǰ¶Ë¹¥»÷´íÎó£¡")
        AttackFailNotify(curPlayer, curSkill)
        return
    if not __CheckPlayerUseSkill_ClientPack(curPlayer, pack_PosX, pack_PosY, curSkill):
        AttackFailNotify(curPlayer, curSkill)
        return
    #¼¤»îÍæ¼Ò,½â³ý´ôÖÍ
    PlayerControl.SetIsNeedProcess(curPlayer, True)
    
    #´Ë´¦²»¼ì²éºÏ·¨ÐÔ, ÔÚÕæÕýÒªÓõÄʱºòÔÙ¼ì²é
    curPlayer.ClearUseSkillRec()
    curPlayer.SetUseSkill(curSkill.GetSkillData())
    curPlayer.SetUseSkillPosX(tagPosX)
    curPlayer.SetUseSkillPosY(tagPosY)
    if len(hurtList) != 0:
        curPlayer.SetUseSkillTagType(hurtList[0].ObjType)
        curPlayer.SetUseSkillTagID(hurtList[0].ObjID)
        # ÉèÖÿͻ§¶ËÉËѪ£¬¾ßÌåÅж¨ÔÚÉËѪʱ´¦Àí
    
    #ÉèÖù¥»÷ÆðµãÎªÍæ¼Ò×ÔÉí×ø±ê
    curPlayer.SetAttackTargetPos(pack_PosX, pack_PosY)
    # ÐèҪǰ×àÒ÷³ªÊͷż¼ÄÜÀ½ø¶ÈÌõ, ÓÉ·þÎñ¶Ë¾ö¶¨É˺¦
    # ÐîÁ¦¼¼ÄÜÐè¼Ç¼ÐîÁ¦Öµ
    if curSkill.GetCastTime() > 0:
        OnPrepareSkill(curPlayer, curSkill, tick)
        return
    
    #ÉèÖù¥»÷±ê־λ
    PlayerControl.ChangePlayerAction(curPlayer, IPY_GameWorld.paAttack)
    #Ö´ÐÐÕ½¶·Âß¼
    PlayerState.ProcessFight(curPlayer, tick)
    return
# ÐîÁ¦»òÕßÒ÷³ªÀ༼ÄÜ
# Ò÷³ªÀ༼ÄÜÔÚ½ø¶ÈÌõ½áÊø²ÅÄÜÊͷż¼ÄÜ
# ÐîÁ¦¼¼Äܰ´½ø¶ÈÌõ½ø¶È³äÄÜÊÍ·Å£¬¿Í»§¶ËÔٴη¢°üÔòÁ¢¼´ÊÍ·Å»ò³äÄÜÂúÔòÊͷż¼ÄÜ£¬Åä±íÊýֵΪcurSkill.GetCastTime()µ¥´Î³äÄÜʱ¼ä
def OnPrepareSkill(curPlayer, curSkill, tick):
    
    #»¹ÔÚÀäȴʱ¼äÄÚÎÞ·¨ÊÍ·Å
    if SkillCommon.RefreshSkillRemainTime(curSkill, tick) != 0:
        return False
    
    # ÐîÁ¦´ÎÊý£¬Ä¬ÈÏ1ÎÞÐîÁ¦
    count = 1
    hasEffect = SkillCommon.GetSkillEffectByEffectID(curSkill, ChConfig.Def_Skill_Effect_PowerPart)
    
    if curPlayer.GetPlayerAction() == IPY_GameWorld.paPreparing and curPlayer.GetPrepareState() == IPY_GameWorld.pstSkill:
        if not hasEffect:
            # ·ÇÐîÁ¦¼¼ÄÜ
            return
        if curPlayer.GetPrepareID() != curSkill.GetSkillID():
            # ·Çµ±Ç°ÐîÁ¦¼¼ÄÜ
            return
        ## ¶þ´Î·¢°ü¿Í»§¶ËÒªÇóÁ¢¼´ÊÍ·Å
        
        count = hasEffect.GetEffectValue(0)     
        # ĬÈÏ´¥·¢ËãÒ»´ÎÄÜÁ¿
        cnt = min(count, (tick - curPlayer.GetPlayerActionTick()) / curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_PowerPartTime) + 1)
        curPlayer.SetDict(ChConfig.Def_PlayerKey_PowerPartCount, cnt)
        SkillPrepareEnd(curPlayer, tick)
    else:
        curPlayer.SetDict(ChConfig.Def_PlayerKey_PowerPartTime, 0)
        curPlayer.SetDict(ChConfig.Def_PlayerKey_PowerPartCount, 0)
        # ¹¥»÷ËÙ¶È»áÓ°ÏìÀ½ø¶ÈÌõµÄËÙ¶È
        castTime = int(curPlayer.GetAtkInterval()/ChConfig.Def_AtkSpeedBase*curSkill.GetCastTime())
        if hasEffect:
            # ¼Ç¼Òò¹¥ËÙÓ°Ïìÿ´Î½ø¶Èµ÷Öµ
            curPlayer.SetDict(ChConfig.Def_PlayerKey_PowerPartTime, castTime)
            count = hasEffect.GetEffectValue(0)
        
        PlayerControl.Sync_PrepareBegin(curPlayer, castTime*count, IPY_GameWorld.pstSkill, curSkill.GetSkillID())
        
    return True
#¼¼ÄÜÊÍ·Åʧ°Ü֪ͨ£¬Ä¿Ç°ÓÃÓÚ½ø¶ÈÌõ¼¼ÄÜ»¹Ã»¿ªÊ¼Ç°ÑéÖ¤²»Í¨¹ýÇé¿ö
def AttackFailNotify(curPlayer, curSkill, reason=0):
    sendPack = ChPyNetSendPack.tagMCAttackFail()
    sendPack.SkillID = curSkill.GetSkillID()
    sendPack.Reason = reason
    NetPackCommon.SendFakePack(curPlayer, sendPack)
#--------------------------Íæ¼ÒʹÓü¼ÄÜ
#===============================================================================
# //06 02 ÈËÎïʹÓü¼ÄÜ#tagRoleUseSkill
# tagRoleUseSkill       *   GettagRoleUseSkill();
# 
# class   IPY_RoleUseSkill
# {
# public:
# 
#    int      GetSkillID();
# 
#    int      GetPosX();
# 
#    int      GetPosY();
# };
#===============================================================================
##¿Í»§¶Ë·â°üÏìÓ¦ //06 02 ÈËÎïʹÓü¼ÄÜ#tagRoleUseSkill
# @param index Íæ¼ÒË÷Òý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¿Í»§¶Ë·â°üÏìÓ¦ //06 02 ÈËÎïʹÓü¼ÄÜ#tagRoleUseSkill
def UseSkill(index, tick):
    GameWorld.GetPsycoFunc(__Func_UseSkill)(index, tick)
    return
##¿Í»§¶Ë·â°üÏìÓ¦ //06 02 ÈËÎïʹÓü¼ÄÜ#tagRoleUseSkill
# @param index Íæ¼ÒË÷Òý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¿Í»§¶Ë·â°üÏìÓ¦ //06 02 ÈËÎïʹÓü¼ÄÜ#tagRoleUseSkill
def __Func_UseSkill(index, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    curPlayerID = curPlayer.GetID()
     
    #-----------»ñÈ¡·â°üÊý¾Ý
    sendPack = IPY_GameWorld.IPY_RoleUseSkill() 
    pack_SkillID = sendPack.GetSkillID()
    pack_PosX = sendPack.GetPosX()
    pack_PosY = sendPack.GetPosY()
    curSkill = curPlayer.GetSkillManager().FindSkillBySkillID(pack_SkillID)
    if not curSkill:
        GameWorld.ErrLog('UseSkill findSkillErr = %s'%(pack_SkillID), curPlayerID)
        return
    if not __CheckPlayerUseSkill_ClientPack(curPlayer, pack_PosX, pack_PosY, curSkill):
        return
    #ʹÓü¼ÄÜÐÐΪ״̬, ¿Í»§¶ËÏÞÖÆ
    if not OperControlManager.IsObjCanDoAction(curPlayer, 
                                               ChConfig.Def_Obj_ActState_ClientSkill, 
                                               curSkill.GetSkillOfSeries()):
        return    
    #¼¤»îÍæ¼Ò,½â³ý´ôÖÍ
    PlayerControl.SetIsNeedProcess(curPlayer, True)
    
    #´Ë´¦²»¼ì²éºÏ·¨ÐÔ, ÔÚÕæÕýÒªÓõÄʱºòÔÙ¼ì²é
    curPlayer.ClearUseSkillRec()
    curPlayer.SetUseSkill(curSkill.GetSkillData())
    #ÉèÖù¥»÷ÆðµãÎªÍæ¼Ò×ÔÉí×ø±ê
    curPlayer.SetAttackTargetPos(curPlayer.GetPosX(), curPlayer.GetPosY())
    
    #ÒѾÔÚ¹¥»÷ÖÐ
    if curPlayer.GetPlayerAction() == IPY_GameWorld.paAttack:
        return
     
    #ÉèÖù¥»÷±ê־λ
    PlayerControl.ChangePlayerAction(curPlayer, IPY_GameWorld.paAttack)
    #Ö´ÐÐÕ½¶·Âß¼
    PlayerState.ProcessFight(curPlayer, tick)
#===============================================================================
#    if playerLastAction != IPY_GameWorld.paAttack:
#        #Íæ¼ÒÓɷǹ¥»÷״̬½øÈë¹¥»÷״̬, ´¥·¢Ò»´ÎÍæ¼Ò״̬ˢÐÂ
#        PlayerState.ProcessPlayerState(curPlayer, tick)
#        return
#===============================================================================
    return
#---------------------------------------------------------------------    
#===============================================================================
# //06 03 ÓжÔÏóµÄʹÓü¼ÄÜ#tagCUseSkillTag
# tagCUseSkillTag       *   GettagCUseSkillTag();
# 
# class   IPY_CUseSkillTag
# {
# public:
# 
#    int      GetSkillID();
#    //OBJÀàÐÍ
#    int      GetTagType();
# 
#    int      GetTagID();
# 
#    int      GetPosX();
# 
#    int      GetPosY();
# };
#===============================================================================
##¿Í»§¶Ë·â°üÏìÓ¦ //06 03 ÓжÔÏóµÄʹÓü¼ÄÜ#tagCUseSkillTag
# @param index Íæ¼ÒË÷Òý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¿Í»§¶Ë·â°üÏìÓ¦ //06 03 ÓжÔÏóµÄʹÓü¼ÄÜ#tagCUseSkillTag
def UseSkillTag(index, tick):
    GameWorld.GetPsycoFunc(__Func_UseSkillTag)(index, tick)
    return
##¿Í»§¶Ë·â°üÏìÓ¦ //06 03 ÓжÔÏóµÄʹÓü¼ÄÜ#tagCUseSkillTag
# @param index Íæ¼ÒË÷Òý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¿Í»§¶Ë·â°üÏìÓ¦ //06 03 ÓжÔÏóµÄʹÓü¼ÄÜ#tagCUseSkillTag
def __Func_UseSkillTag(index, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    curPlayerID = curPlayer.GetID()
    #----------»ñÈ¡·â°üÊý¾Ý
    sendPack = IPY_GameWorld.IPY_CUseSkillTag() 
    pack_SkillID = sendPack.GetSkillID()
    pack_TagType = sendPack.GetTagType()
    pack_TagID = sendPack.GetTagID()
    pack_PosX = sendPack.GetPosX()
    pack_PosY = sendPack.GetPosY()
    
    curSkill = curPlayer.GetSkillManager().FindSkillBySkillID(pack_SkillID)
    if not curSkill:
        #GameWorld.ErrLog(' UseSkillTag FindSkillerr = %s '%(pack_SkillID), curPlayerID)
        return
    
    #ʹÓü¼ÄÜÐÐΪ״̬, ¿Í»§¶ËÏÞÖÆ
    if not OperControlManager.IsObjCanDoAction(curPlayer, 
                                               ChConfig.Def_Obj_ActState_ClientSkill, 
                                               curSkill.GetSkillOfSeries()):
        return    
    
    if not __CheckPlayerUseSkill_ClientPack(curPlayer, pack_PosX, pack_PosY, curSkill):
        return
    
    #¼¤»îÍæ¼Ò,½â³ý´ôÖÍ
    PlayerControl.SetIsNeedProcess(curPlayer, True)
        
    #´Ë´¦²»¼ì²éºÏ·¨ÐÔ, ÔÚÕæÕýÒªÓõÄʱºòÔÙ¼ì²é
    curPlayer.ClearUseSkillRec()
    curPlayer.SetUseSkill(curSkill.GetSkillData())
    curPlayer.SetUseSkillTagType(pack_TagType)
    curPlayer.SetUseSkillTagID(pack_TagID)
    #@warning: ÉèÖù¥»÷ÆðµãΪ¿Í»§¶Ë·¢Ë͵Ä×ø±ê(´Ë´¦½«»á±»Íâ¹ÒÀûÓÃ)
    curPlayer.SetAttackTargetPos(pack_PosX, pack_PosY)
    
    #ÒѾÔÚ¹¥»÷ÖÐ
    if curPlayer.GetPlayerAction() == IPY_GameWorld.paAttack:
        return
     
    #ÉèÖù¥»÷±ê־λ
    PlayerControl.ChangePlayerAction(curPlayer, IPY_GameWorld.paAttack)
    #Ö´ÐÐÕ½¶·Âß¼
    PlayerState.ProcessFight(curPlayer, tick)
#===============================================================================
#    if playerLastAction != IPY_GameWorld.paAttack:
#        #Íæ¼ÒÓɷǹ¥»÷״̬½øÈë¹¥»÷״̬, ´¥·¢Ò»´ÎÍæ¼Ò״̬ˢÐÂ
#        PlayerState.ProcessPlayerState(curPlayer, tick)
#        return
#===============================================================================
    return
#---------------------------------------------------------------------
#===============================================================================
# //06 07 ¶ÔµØÃæÊ¹Óü¼ÄÜ#tagCUseSkillGround
# tagCUseSkillGround       *   GettagCUseSkillGround();
# 
# class   IPY_CUseSkillGround
# {
# public:
# 
#    int      GetSkillID();
# 
#    int      GetPosX();
# 
#    int      GetPosY();
# 
#    int      GetTagPosX();
# 
#    int      GetTagPosY();
# };
#===============================================================================
##¿Í»§¶Ë·â°üÏìÓ¦ //06 07 ¶ÔµØÃæÊ¹Óü¼ÄÜ#tagCUseSkillGround
# @param index Íæ¼ÒË÷Òý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¿Í»§¶Ë·â°üÏìÓ¦ //06 07 ¶ÔµØÃæÊ¹Óü¼ÄÜ#tagCUseSkillGround
def UseSkillGround(index, tick):
    GameWorld.GetPsycoFunc(__Func_UseSkillGround)(index, tick)
    return
##¿Í»§¶Ë·â°üÏìÓ¦ //06 07 ¶ÔµØÃæÊ¹Óü¼ÄÜ#tagCUseSkillGround
# @param index Íæ¼ÒË÷Òý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¿Í»§¶Ë·â°üÏìÓ¦ //06 07 ¶ÔµØÃæÊ¹Óü¼ÄÜ#tagCUseSkillGround
def __Func_UseSkillGround(index, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    curPlayerID = curPlayer.GetID()
    
    #----------------»ñÈ¡·â°üÊý¾Ý
    sendPack = IPY_GameWorld.IPY_CUseSkillGround() 
    pack_SkillID = sendPack.GetSkillID()
    pack_PosX = sendPack.GetPosX()
    pack_PosY = sendPack.GetPosY()
    pack_TagPosX = sendPack.GetTagPosX()
    pack_TagPosY = sendPack.GetTagPosY()
    
    curSkill = curPlayer.GetSkillManager().FindSkillBySkillID(pack_SkillID)
    if not curSkill:
        GameWorld.ErrLog('UseSkillGround findSkillErr = %s'%(pack_SkillID), curPlayerID)
        return
    
    #ʹÓü¼ÄÜÐÐΪ״̬, ¿Í»§¶ËÏÞÖÆ
    if not OperControlManager.IsObjCanDoAction(curPlayer, 
                                               ChConfig.Def_Obj_ActState_ClientSkill, 
                                               curSkill.GetSkillOfSeries()):
        return    
    if not __CheckPlayerUseSkill_ClientPack(curPlayer, pack_PosX, pack_PosY, curSkill):
        return
    
#===============================================================================
#    #ÅжÏ2µã¼äÊÇ·ñÓÐÕϰ
#    curMap = GameWorld.GetMap()
#    
#    if ( not curMap.CanLineTo(skillPosX,skillPosY,skillTagPosX, skillTagPosY) and
#            not curMap.CanLineTo(skillTagPosX,skillTagPosY,skillPosX,skillPosY) ):
#        GameWorld.Log("ÊÍ·¨ÖмäÓÐÕϰ")
#        return
#===============================================================================
    #¼¤»îÍæ¼Ò,½â³ý´ôÖÍ
    PlayerControl.SetIsNeedProcess(curPlayer, True)
    #playerLastAction = curPlayer.GetPlayerAction()
    #´Ë´¦²»¼ì²éºÏ·¨ÐÔ, ÔÚÕæÕýÒªÓõÄʱºòÔÙ¼ì²é
    curPlayer.ClearUseSkillRec()
    curPlayer.SetUseSkill(curSkill.GetSkillData())
    curPlayer.SetUseSkillPosX(pack_TagPosX)
    curPlayer.SetUseSkillPosY(pack_TagPosY)
    #@warning: ÉèÖù¥»÷ÆðµãΪ¿Í»§¶Ë·¢Ë͵Ä×ø±ê(´Ë´¦½«»á±»Íâ¹ÒÀûÓÃ)
    curPlayer.SetAttackTargetPos(pack_PosX, pack_PosY)
    
    #ÒѾÔÚ¹¥»÷ÖÐ
    if curPlayer.GetPlayerAction() == IPY_GameWorld.paAttack:
        return
    #ÉèÖù¥»÷±ê־λ
    PlayerControl.ChangePlayerAction(curPlayer, IPY_GameWorld.paAttack)
    #Ö´ÐÐÕ½¶·Âß¼
    PlayerState.ProcessFight(curPlayer, tick)
#===============================================================================
#    if playerLastAction != IPY_GameWorld.paAttack:
#        #Íæ¼ÒÓɷǹ¥»÷״̬½øÈë¹¥»÷״̬, ´¥·¢Ò»´ÎÍæ¼Ò״̬ˢÐÂ
#        PlayerState.ProcessPlayerState(curPlayer, tick)
#        return
#===============================================================================
    return
#---------------------------------------------------------------------
##¼ì²é¿Í»§¶Ë·¢Ëͼ¼ÄÜ·â°ü, ÕâÀïÖ»¼òµ¥¼ì²éÒ»ÏÂ
# @param curPlayer Íæ¼ÒʵÀý
# @param posX ·â°üÊ©·¨Õß×ø±êX
# @param posY ·â°üÊ©·¨Õß×ø±êY
# @return ·µ»ØÖµÕæ, ¼ì²éͨ¹ý
# @remarks ¼ì²é¿Í»§¶Ë·¢Ëͼ¼ÄÜ·â°ü, ÕâÀïÖ»¼òµ¥¼ì²éÒ»ÏÂ
def __CheckPlayerUseSkill_ClientPack(curPlayer, posX, posY, curSkill):
    if GameObj.GetHP(curPlayer) <= 0:
        return
    
    if curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomScene):
        #GameWorld.DebugLog("×Ô¶¨Ò峡¾°ÖУ¬²»¼ì²é!")
        return True
    
    #===========================================================================
    # if curPlayer.IsMoving():
    #    GameWorld.DebugLog("ÒÆ¶¯Öв»¿ÉʹÓü¼ÄÜ")
    #    return False
    #===========================================================================
    if curPlayer.GetPlayerVehicle() == IPY_GameWorld.pvHorse:
        #GameWorld.DebugLog("ÆïÂíÖв»ÔÊÐíÊͷż¼ÄÜ", curPlayerID)
        PlayerHorse.PlayerRideHorseDown(curPlayer)
    
    if not PlayerControl.PlayerCanStateTransfer(curPlayer):
        #GameWorld.DebugLog('CheckUseSkill, PlayerStateErr = %s '%( curPlayer.GetPlayerAction() ), curPlayerID )
        return False
    
    # ×Ë̬¼¼Äܰ²È«Çø¿ÉʹÓÃ
    if GameMap.GetAreaTypeByMapPos(curPlayer.GetPosX(), curPlayer.GetPosY()) == IPY_GameWorld.gatSafe:
        if curSkill.GetSkillID() != ChConfig.Def_SkillID_Somersault:
            #GameWorld.DebugLog("°²È«Çø")
            return False
    
    # ·Å¼¼ÄÜǰÏȸüÐÂÍæ¼ÒµÄ×ø±ê updateposÓÐʱºò»áÂýµ¼ÖÂ×ø±êÎó²î£¬changepos»áÌáǰµ½´ïÉÏÒ»¸öÒÆ¶¯µã
    #===========================================================================
    # if curPlayer.IsMoving() and GameWorld.GetDist(curPlayer.GetPosX(), curPlayer.GetPosY(), curPlayer.GetDestPosX(), curPlayer.GetDestPosY()) <= 3:             
    #    #GameWorld.DebugLog("¹¥»÷Ìáǰµ½´ïÉÏÒ»¸öÒÆ¶¯µã--- -%s  %s"%(curPlayer.GetDestPosX(), curPlayer.GetDestPosY()))
    #    curPlayer.ChangePos(curPlayer.GetDestPosX(), curPlayer.GetDestPosY())
    #===========================================================================
        
    if not PlayerControl.PlayerRefreshPos(curPlayer, curPlayer, posX, posY, False):
        #Íæ¼Òµ±Ç°Î»ÖÃË¢ÐÂʧ°Ü
        #GameWorld.DebugLog(' CheckUseSkill RefreshPosErr packPos = ( %s, %s ), playerPos = ( %s, %s )'%( posX, posY, curPlayer.GetPosX(), curPlayer.GetPosY() ), curPlayerID )
        return False
    
    return True
#------------------------------------·â°ü´«µÝÍê±Ï,¿ªÊ¼Âß¼´¦Àí---------------------------------
##Íæ¼ÒÊÍ·ÅÎÞÄ¿±ê¼¼ÄÜ
# @param curPlayer Íæ¼ÒʵÀý
# @param curSkill ¼¼ÄÜʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÕæ, Ê©·¨³É¹¦
# @remarks ×Ô¶¨Ò庯Êý, Íæ¼ÒÊÍ·ÅÎÞÄ¿±ê¼¼ÄÜ
def DoPlayerUseSkill(curPlayer, curSkill, tick):
    if not CheckSkillCondition(curPlayer, curSkill, tick):
        return
    if GetSkillFireAim(curSkill) != ChConfig.Def_UseSkillAim_None:
        return
    
    if curSkill.GetSkillType() in ChConfig.Def_CanAttackSkill_List:
        return DoLogic_UseSkill(curPlayer, None, curSkill, tick, curPlayer.GetPosX(), curPlayer.GetPosY())
    else:
        return DoLogic_UseSkill(curPlayer, curPlayer, curSkill, tick)
#---------------------------------------------------------------------
##Íæ¼ÒÊÍ·ÅÓÐÄ¿±ê¼¼ÄÜ
# @param curPlayer Íæ¼ÒʵÀý
# @param curSkill ¼¼ÄÜʵÀý
# @param curTag Ä¿±êʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÕæ, Ê©·¨³É¹¦
# @remarks ×Ô¶¨Ò庯Êý, Íæ¼ÒÊÍ·ÅÓÐÄ¿±ê¼¼ÄÜ
def DoPlayerUseSkillTag(curPlayer, curSkill, curTag, tick):
    #¹«Óüì²é
    if not CheckSkillCondition(curPlayer, curSkill, tick):
        GameWorld.DebugLog("DoPlayerUseSkillTag, ²»Âú×ãʹÓÃÌõ¼þ")
        return
    
    #¼ì²éÄ¿±ê
    if not CheckTag_DoPlayerUseSkillTag(curPlayer, curSkill, curTag, tick):
        #GameWorld.Log("DoPlayerUseSkillTag = %s, ¼ì²éÄ¿±êÊÇ·ñ¿ÉÒÔ¹¥»÷ʧ°Ü = %s"%( curSkill.GetTag(), curTag.GetName() ) )
        return
        
    #Êͷż¼ÄÜ
    return DoLogic_UseSkill(curPlayer, curTag, curSkill, tick)
#---------------------------------------------------------------------
##Íæ¼ÒÊÍ·ÅÓÐÄ¿±ê¼¼ÄÜ, ¼ì²éÄ¿±ê¶ÔÏóÊÇ·ñ·ûºÏÒªÇó
# @param curPlayer Íæ¼ÒʵÀý
# @param curSkill ¼¼ÄÜʵÀý
# @param curTag Ä¿±êʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÕæ, ¼ì²éͨ¹ý
# @remarks ×Ô¶¨Ò庯Êý, Íæ¼ÒÊÍ·ÅÓÐÄ¿±ê¼¼ÄÜ, ¼ì²éÄ¿±ê¶ÔÏóÊÇ·ñ·ûºÏÒªÇó
def CheckTag_DoPlayerUseSkillTag(curPlayer, curSkill, curTag, tick):
    curSkillUseTag = GetSkillAffectTag(curSkill)
    
    #¶ÔÍæ¼ÒʬÌåÊÍ·Å
    if curSkillUseTag == ChConfig.Def_UseSkillTag_PlayerAshes:
        return __DoPlayerUseSkillTag_PlayerAshes(curPlayer, curTag)
    
    #---ÒÔϼ¼ÄÜ, ²»¿É¶ÔËÀÍöÄ¿±êÊÍ·Å---
    if GameObj.GetHP(curTag) <= 0:
        return
    
    #×Ô¼º¼°ÓѺÃ
    if curSkillUseTag == ChConfig.Def_UseSkillTag_SelfAndFriend:
        return __DoPlayerUseSkillTag_SelfAndFriend(curPlayer, curTag, curSkill, tick)
    
    #¶Ô»îµÄÍæ¼ÒÊÍ·Å
    if curSkillUseTag == ChConfig.Def_UseSkillTag_PlayerHasHP:
        return __DoPlayerUseSkillTag_PlayerHasHP(curPlayer, curTag)
    
    #¶ÓÓÑÊÍ·Å
    if curSkillUseTag == ChConfig.Def_UseSkillTag_Team:
        return __DoPlayerUseSkillTag_Team(curPlayer, curTag)
    
    #¶Ô×Ô¼º¡¢ÓѺü°¿É¹¥»÷µ¥Î»ÊÍ·Å
    if curSkillUseTag == ChConfig.Def_UseSkillTag_SelfFriendAttack:
        return __DoPlayerUseSkillTag_SelfFriendAttack(curPlayer, curTag, curSkill, tick)
    
    #---ÒÔϼ¼ÄÜ, ²»¿É¶ÔËÀÍöÄ¿±êÊÍ·Å ¼° ²»¿É¶Ô×Ô¼ºÊÍ·Å---
    if GameWorld.IsSameObj(curPlayer, curTag):
        return
    
    #ÓѺÃÄ¿±êÊÍ·Å
    if curSkillUseTag == ChConfig.Def_UseSkillTag_Friend:
        return __DoPlayerUseSkillTag_Friend(curPlayer, curTag, curSkill, tick)
    
    #¿É¹¥»÷Ä¿±êÊÍ·Å
    if curSkillUseTag == ChConfig.Def_UseSkillTag_CanAttack:
        return __DoPlayerUseSkillTag_CanAttack(curPlayer, curTag, curSkill, tick)
    
    #¿É¹¥»÷¹ÖÎï
    if curSkillUseTag == ChConfig.Def_UseSkillTag_CanAttackNPC:
        return __DoPlayerUseSkillTag_CanAttackEx(curPlayer, curTag, 
                                                 curSkill, IPY_GameWorld.gotNPC, tick)
    
    #¿É¹¥»÷Íæ¼Ò
    if curSkillUseTag == ChConfig.Def_UseSkillTag_CanAttackPlayer:
        return __DoPlayerUseSkillTag_CanAttackEx(curPlayer, curTag, 
                                                 curSkill, IPY_GameWorld.gotPlayer, tick)
    
    #¿É¹¥»÷µÄÒ°ÍâС¹Ö£¨º¬¾«Ó¢£©¹ÖÎï
    if curSkillUseTag == ChConfig.Def_UseSkillTag_CanAttackBaseNPC:
        if curTag.GetGameObjType() != IPY_GameWorld.gotNPC:
            return False
        if GameWorld.GetMap().GetMapFBType() != IPY_GameWorld.fbtNull:
            return False
        if curTag.GetIsBoss() > ChConfig.Def_NPCType_Ogre_Super:
            return False
        return __DoPlayerUseSkillTag_CanAttackEx(curPlayer, curTag, 
                                                 curSkill, IPY_GameWorld.gotNPC, tick)
    
    GameWorld.ErrLog('curSkillUseTag noFind = %s'%(curSkillUseTag))
    return False
#---------------------------------------------------------------------
##Íæ¼ÒÊÍ·ÅÓÐÄ¿±ê¼¼ÄÜ, ¼ì²éÄ¿±ê¶ÔÏóÊÇ·ñ·ûºÏÒªÇó, ×Ô¼º¼°ÓѺÃÄ¿±ê
# @param curPlayer Íæ¼ÒʵÀý
# @param curSkill ¼¼ÄÜʵÀý
# @param curTag Ä¿±êʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÕæ, ¼ì²éͨ¹ý
# @remarks ×Ô¶¨Ò庯Êý, Íæ¼ÒÊÍ·ÅÓÐÄ¿±ê¼¼ÄÜ, ¼ì²éÄ¿±ê¶ÔÏóÊÇ·ñ·ûºÏÒªÇó, ×Ô¼º¼°ÓѺÃÄ¿±ê
def __DoPlayerUseSkillTag_SelfAndFriend(curPlayer, curTag, curSkill, tick):
    if GameWorld.IsSameObj(curPlayer, curTag):
        return True
    
    return __DoPlayerUseSkillTag_Friend(curPlayer, curTag, curSkill, tick)
#---------------------------------------------------------------------
##Íæ¼ÒÊÍ·ÅÓÐÄ¿±ê¼¼ÄÜ
# @param curPlayer Íæ¼ÒʵÀý
# @param curSkill ¼¼ÄÜʵÀý
# @param curTag Ä¿±êʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÕæ, ¼ì²éͨ¹ý
# @remarks Íæ¼ÒÊÍ·ÅÓÐÄ¿±ê¼¼ÄÜ, ¼ì²éÄ¿±ê¶ÔÏóÊÇ·ñ·ûºÏÒªÇó, ×Ô¼º¡¢ÓѺü°¿É¹¥»÷µ¥Î»
def __DoPlayerUseSkillTag_SelfFriendAttack(curPlayer, curTag, curSkill, tick):
    
    #×Ô¼º£¬·µ»ØÕæ
    if GameWorld.IsSameObj(curPlayer, curTag):
        return True
    
    #¹ØÏµ
    relation = BaseAttack.GetTagRelation(curPlayer, curTag, curSkill, tick)
    
    #ÓѺùØÏµ£¬·µ»ØÕæ    
    if relation[0] == ChConfig.Type_Relation_Friend :
        return True
    
    return __DoPlayerUseSkillTag_CanAttack(curPlayer, curTag, curSkill, tick)
#---------------------------------------------------------------------
##Íæ¼ÒÊÍ·ÅÓÐÄ¿±ê¼¼ÄÜ, ¼ì²éÄ¿±ê¶ÔÏóÊÇ·ñ·ûºÏÒªÇó, ¿É¹¥»÷Ä¿±ê
# @param curPlayer Íæ¼ÒʵÀý
# @param curSkill ¼¼ÄÜʵÀý
# @param curTag Ä¿±êʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÕæ, ¼ì²éͨ¹ý
# @remarks ×Ô¶¨Ò庯Êý, Íæ¼ÒÊÍ·ÅÓÐÄ¿±ê¼¼ÄÜ, ¼ì²éÄ¿±ê¶ÔÏóÊÇ·ñ·ûºÏÒªÇó, ¿É¹¥»÷Ä¿±ê
def __DoPlayerUseSkillTag_CanAttack(curPlayer, curTag, curSkill, tick):
    #²»¿É¹¥»÷Ä¿±ê·µ»Ø
    if not BaseAttack.GetCanAttack(curPlayer, curTag, curSkill, tick):
        return False
    
    #¹ØÏµ·ÇµÐ¶Ô·µ»Ø
    relation = BaseAttack.GetTagRelation(curPlayer, curTag, curSkill, tick)
    if relation[0] == ChConfig.Type_Relation_Enemy :
        return True
    
    if curSkill.GetFuncType() == ChConfig.Def_SkillFuncType_FbSkill:
        AttackCommon.PlayerAttackFailSysMessanage(curPlayer, relation[1])
    return False
##Íæ¼ÒÊÍ·ÅÓÐÄ¿±ê¼¼ÄÜ, ¼ì²éÄ¿±ê¶ÔÏóÊÇ·ñ·ûºÏÒªÇó, ¿É¹¥»÷¹ÖÎï
# @param curPlayer Íæ¼ÒʵÀý
# @param curSkill ¼¼ÄÜʵÀý
# @param curTag Ä¿±êʵÀý
# @param objType Íæ¼ÒÀàÐÍ
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÕæ, ¼ì²éͨ¹ý
# @remarks Íæ¼ÒÊÍ·ÅÓÐÄ¿±ê¼¼ÄÜ, ¼ì²éÄ¿±ê¶ÔÏóÊÇ·ñ·ûºÏÒªÇó, ¿É¹¥»÷¹ÖÎï
def __DoPlayerUseSkillTag_CanAttackEx(curPlayer, curTag, curSkill, objType, tick):
    #²»ÊÇNPC²»¹¥»÷
    if curTag.GetGameObjType() != objType:
        return False
    
    return __DoPlayerUseSkillTag_CanAttack(curPlayer, curTag, curSkill, tick)
    
#---------------------------------------------------------------------
##Íæ¼ÒÊÍ·ÅÓÐÄ¿±ê¼¼ÄÜ, ¼ì²éÄ¿±ê¶ÔÏóÊÇ·ñ·ûºÏÒªÇó, ÓѺÃÄ¿±êÊÍ·Å
# @param curPlayer Íæ¼ÒʵÀý
# @param curSkill ¼¼ÄÜʵÀý
# @param curTag Ä¿±êʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÕæ, ¼ì²éͨ¹ý
# @remarks ×Ô¶¨Ò庯Êý, Íæ¼ÒÊÍ·ÅÓÐÄ¿±ê¼¼ÄÜ, ¼ì²éÄ¿±ê¶ÔÏóÊÇ·ñ·ûºÏÒªÇó, ÓѺÃÄ¿±êÊÍ·Å
def __DoPlayerUseSkillTag_Friend(curPlayer, curTag, curSkill, tick):
    #¹ØÏµ
    relation = BaseAttack.GetTagRelation(curPlayer, curTag, curSkill, tick)
        
    if relation[0] == ChConfig.Type_Relation_Friend :
        return True
    
    if curSkill.GetFuncType() == ChConfig.Def_SkillFuncType_FbSkill:
        AttackCommon.PlayerAttackFailSysMessanage(curPlayer, relation[1])
    return False
#---------------------------------------------------------------------
##Íæ¼ÒÊÍ·ÅÓÐÄ¿±ê¼¼ÄÜ, ¼ì²éÄ¿±ê¶ÔÏóÊÇ·ñ·ûºÏÒªÇó, ¶ÓÔ±ÊÍ·Å
# @param curPlayer Íæ¼ÒʵÀý
# @param curSkill ¼¼ÄÜʵÀý
# @param curTag Ä¿±êʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÕæ, ¼ì²éͨ¹ý
# @remarks ×Ô¶¨Ò庯Êý, Íæ¼ÒÊÍ·ÅÓÐÄ¿±ê¼¼ÄÜ, ¼ì²éÄ¿±ê¶ÔÏóÊÇ·ñ·ûºÏÒªÇó, ¶ÓÔ±ÊÍ·Å
def __DoPlayerUseSkillTag_Team(curPlayer, curTag):
    if curTag.GetGameObjType() != IPY_GameWorld.gotPlayer:
        return False
    
    #ÎÞ×é¶ÓµÄʱºòÒª¸ø×Ô¼º´¦Àí
    if GameWorld.IsSameObj(curPlayer, curTag):
        return True
    
    curPlayerTeamID = curPlayer.GetTeamID()
    curTagTeamID = curTag.GetTeamID()
    
    if not curPlayerTeamID or not curTagTeamID:
        return False
    
    return (curPlayerTeamID == curTagTeamID)
#---------------------------------------------------------------------
##Íæ¼ÒÊÍ·ÅÓÐÄ¿±ê¼¼ÄÜ, ¶ÔʬÌåÊÍ·Å
# @param curPlayer Íæ¼ÒʵÀý
# @param curTag Ä¿±êʵÀý
# @return ·µ»ØÖµÕæ, ¼ì²éͨ¹ý
# @remarks ×Ô¶¨Ò庯Êý, Íæ¼ÒÊÍ·ÅÓÐÄ¿±ê¼¼ÄÜ, ¶ÔʬÌåÊÍ·Å
def __DoPlayerUseSkillTag_PlayerAshes(curPlayer, curTag):
    if curTag.GetGameObjType() != IPY_GameWorld.gotPlayer:
        return
    
    return (GameObj.GetHP(curTag) <= 0)
#---------------------------------------------------------------------
##Íæ¼ÒÊÍ·ÅÓÐÄ¿±ê¼¼ÄÜ, ¶Ô»îµÄÍæ¼ÒÊÍ·Å
# @param curPlayer Íæ¼ÒʵÀý
# @param curTag Ä¿±êʵÀý
# @return ·µ»ØÖµÕæ, ¼ì²éͨ¹ý
# @remarks ×Ô¶¨Ò庯Êý, Íæ¼ÒÊÍ·ÅÓÐÄ¿±ê¼¼ÄÜ, ¶Ô»îµÄÍæ¼ÒÊÍ·Å
def __DoPlayerUseSkillTag_PlayerHasHP(curPlayer, curTag):
    if curTag.GetGameObjType() != IPY_GameWorld.gotPlayer:
        return
    
    return (GameObj.GetHP(curTag) > 0)
#---------------------------------------------------------------------
##Íæ¼ÒÊͷŶԵØÃæ¼¼ÄÜ
# @param curPlayer Íæ¼ÒʵÀý
# @param curSkill ¼¼ÄÜʵÀý
# @param destX Ä¿±ê×ø±êX
# @param destY Ä¿±ê×ø±êY
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÕæ, Êͷųɹ¦
# @remarks ×Ô¶¨Ò庯Êý, Íæ¼ÒÊͷŶԵØÃæ¼¼ÄÜ
def DoPlayerUseSkillGround(curPlayer, curSkill, destX, destY, tick):
    #ͨÓÃÌõ¼þ¼ì²é    
    if not CheckSkillCondition(curPlayer, curSkill, tick):
        #GameWorld.Log("DoPlayerUseSkillGround, ²»Âú×ãʹÓÃÌõ¼þ")
        return
    
    #רÓм¼ÄÜÀàÐͼì²é
    if GetSkillFireAim(curSkill) != ChConfig.Def_UseSkillAim_Ground:
        #GameWorld.Log("²»ÊǶԵØÊÍ·ÅÀ༼ÄÜ")
        return
    
    #ÐèÒª¼ì²é¿Í»§¶Ë·¢µÄ¾àÀë
#    dist = GameWorld.GetDist(curPlayer.GetPosX(), curPlayer.GetPosY(), destX, destY)
#    
#    #ÕâÀïÖ»ÅжÏÓÐÅäÖù¥»÷¾àÀëÏÞÖÆµÄÇé¿ö; ·ÀÖ¹ÒÆ¶¯Ê©·¨Ê±£¬¹¥»÷¾àÀëΪ0µÄÔµØÊͷż¼ÄÜÀàÐÍż·¢ÎÞ·¨ÊͷŵÄÎÊÌâ
#    if curSkill.GetAtkDist() > 0 and dist > curSkill.GetAtkDist():
#        #GameWorld.Log('###¿Í»§¶Ë·¢°ü, ȺÌå¹¥»÷ = %s , ¾àÀë¹ýÔ¶( %s , %s) , Æðµã(%s , %s), Ä¿±ê(%s, %s)'%(curSkill.GetSkillName() , dist , curSkill.GetAtkDist() , curPlayer.GetPosX(), curPlayer.GetPosY(), destX, destY  ))
#        return
    
    #ÊÇÕϰµã,²»ÄÜÊÍ·Å£¬Ìø³ö
    #if not GameWorld.GetMap().CanMove(destX, destY):
    #    #GameWorld.Log("Ä¿±êΪÕϰµã %s"%([destX, destY]))
    #    return
    
    #---Óпͻ§¶ËÄ¿±êÓÅÏÈÒÔµÚһĿ±êΪÖÐÐÄ  
    defender = None 
    useSkillTagID = curPlayer.GetUseSkillTagID()
    useSkillTagType = curPlayer.GetUseSkillTagType()
    if useSkillTagID:
        defender = GameWorld.GetObj(useSkillTagID, useSkillTagType)
    return DoLogic_UseSkill(curPlayer, defender, curSkill, tick, tagRoundPosX = destX, tagRoundPosY = destY)
#---------------------------------------------------------------------
## ¶ÔÏóʹÓü¼ÄÜͨÓÃ(°üº¬ÓÐÄ¿±êºÍÎÞÄ¿±ê)
# @param attacker ¹¥»÷ÕßʵÀý
# @param defender ·ÀÊØÕßʵÀý
# @param curSkill ¼¼ÄÜʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎªÕæ, Êͷųɹ¦
# @remarks ¡°´ò³ö×ÔÉíÉ˺¦µÄX%¸½¼ÓYÖµ¡±ÕâÒ»ÀàÆÕͨ¹¥»÷¼¼ÄÜÀàÐÍʵÏÖÂß¼
def ObjAutoUseSkill(attacker, defender, curSkill, tick):
    curTag = defender
    
    attackerObjType = attacker.GetGameObjType()
    skillAffectTag = GetSkillAffectTag(curSkill)
    skillAim = GetSkillFireAim(curSkill)
    # Íæ¼Ò
    if attackerObjType == IPY_GameWorld.gotPlayer:
        #ÎÞÄ¿±ê¼¼ÄÜ
        if skillAim == ChConfig.Def_UseSkillAim_None:
            return DoPlayerUseSkill(attacker, curSkill, tick)
        
        #¶Ô×Ô¼ºÊͷż¼ÄÜ
        elif skillAffectTag in ChConfig.Def_ST_CanPlayerUseSkill:
            return DoPlayerUseSkillTag(attacker, curSkill, attacker, tick)
        
        #ÆäËü¶ÔÏó¼¼ÄÜ    
        else:
            return DoPlayerUseSkillTag(attacker, curSkill, curTag, tick)
            
    elif attackerObjType == IPY_GameWorld.gotNPC:
        # ¶Ô×ÔÉíÊÍ·Å»òÕßÎÞÄ¿±ê¼¼ÄÜ
        if skillAffectTag in ChConfig.Def_ST_CanNPCUseSkill or skillAim == ChConfig.Def_UseSkillAim_None:
            #ÊÍ·Å×ÔÉíÀ༼ÄÜ
            return NPCUseSkill(attacker, curSkill, tick)  
                  
        # ³èÎï¶ÔÖ÷ÈËÊͷż¼ÄÜ
        elif skillAffectTag == ChConfig.Def_UseSkillTag_PetMaster:
            if not PetControl.IsPet(attacker):
                GameWorld.ErrLog("¸ÃNPC·Ç³èÎÎÞ·¨»ñµÃÖ÷ÈËÊͷż¼ÄÜ")
                return False
            
            petOwner = PetControl.GetPetOwner(attacker)
            
            if petOwner == None:
                GameWorld.ErrLog("³èÎ%s£©¶ÔÖ÷ÈËÊͷż¼ÄÜ£¬ÕÒ²»µ½Ö÷ÈË"%attacker.GetRolePet().PetID)
                return False
        
            curTag = petOwner            
                  
        # ÕÙ»½ÊÞ¶ÔÖ÷ÈËÊͷż¼ÄÜ
        elif skillAffectTag == ChConfig.Def_UseSkillTag_SummonMaster:
            if not NPCCommon.IsSummonNPC(attacker):
                GameWorld.ErrLog("¸ÃNPC·ÇÕÙ»½ÊÞ£¬ÎÞ·¨»ñµÃÖ÷ÈËÊͷż¼ÄÜ")
                return False
            
            curSummonOwner =  NPCCommon.GetSummonNPCOwner(IPY_GameWorld.gotPlayer, attacker)    
            if curSummonOwner == None:
                curSummonOwner = NPCCommon.GetSummonNPCOwner(IPY_GameWorld.gotNPC, attacker)
            
            if curSummonOwner == None:
                GameWorld.ErrLog("ÕÙ»½ÊÞ£¨%s£©¶ÔÖ÷ÈËÊͷż¼ÄÜ£¬ÕÒ²»µ½Ö÷ÈË" % attacker.GetNPCID())
                return
        
            curTag = curSummonOwner
            
        return NPCUseSkillTag(attacker, curTag, curSkill, tick)  
    
    return False
#---------------------------------------------------------------------
##ÅжÏÍæ¼ÒÊÇ·ñÓµÓÐÕâ¸öÀàÐͼ¼ÄÜ
# @param curPlayer Íæ¼ÒʵÀý
# @param skill ¼¼ÄÜʵÀý
# @return ·µ»ØÖµÕæ, ¼ì²éͨ¹ý
# @remarks ÅжÏÍæ¼ÒÊÇ·ñÓµÓÐÕâ¸öÀàÐͼ¼ÄÜ
def CheckPlayerHasSkill(curPlayer , skill):
    skillTypeID = skill.GetSkillTypeID()
    skillManager = curPlayer.GetSkillManager()
    for i in range(0 , skillManager.GetSkillCount()):
        curPlayerSkill = skillManager.GetSkillByIndex(i)
        if curPlayerSkill.GetSkillTypeID() == skillTypeID:
            return True
        
    return False
#---------------------------------------------------------------------
#===============================================================================
# //03 04 Íæ¼Òѧϰ¼¼ÄÜ#tagCAddSkillPoint
# tagCAddSkillPoint       *   GettagCAddSkillPoint();
# 
# class   IPY_CAddSkillPoint
# {
# public:
# 
#    int      GetSkillID();
# };
#===============================================================================
##¿Í»§¶Ë·â°üÏìÓ¦ //03 04 Íæ¼Òѧϰ¼¼ÄÜ#tagCAddSkillPoint
# @param index Íæ¼ÒË÷Òý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Íæ¼ÒÉý¼¶¼¼ÄÜ
def PlayerSkillLvUp(index, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    
    if curPlayer.GetPlayerAction() in ChConfig.Def_Player_Cannot_LearnLvSkill_State:
        return
    
    #»ñµÃ·â°ü
    pack = IPY_GameWorld.IPY_CAddSkillPoint()
    #Éý¼¶¼¼ÄÜID
    skillTypeID = pack.GetSkillID()
    #»ñµÃÍæ¼Ò¼¼ÄܹÜÀíÆ÷
    skillManager = curPlayer.GetSkillManager()
    #»ñµÃ¼¼ÄÜ
    curSkill = skillManager.FindSkillBySkillTypeID(skillTypeID)
    if curSkill == None:
        curSkillLV = 0
        beforeFightPower = 0
    else:
        curSkillLV = curSkill.GetSkillLV()
        beforeFightPower = curSkill.GetFightPower()
        if curSkillLV == curSkill.GetSkillMaxLV():
            #ÒѾÊÇ×î¸ßµÈ¼¶
            PlayerControl.NotifyCode(curPlayer, "UseMagicLost16")
            return
    
    upSkillLv = curSkillLV + 1
    curSkillID = skillTypeID if not curSkill else curSkill.GetSkillID()
    upSkill = GameWorld.GetGameData().FindSkillByType(skillTypeID, upSkillLv)
    if not upSkill:
        return
    #Éý¼¶¼¼ÄÜÏûºÄ
    if not DoLogic_PlayerSkillLvUpCost(curPlayer, skillTypeID, curSkillID, upSkillLv, curSkill):
        return
    
    #Éý¼¶Õâ¸ö¼¼ÄÜ
    skillManager.LVUPSkillByID(curSkillID)
#    curPlayer.SetFreeSkillPoint(curPlayer.GetFreeSkillPoint() - 1 )
    curSkill = skillManager.FindSkillBySkillTypeID(skillTypeID)
        
    #ÊDZ»¶¯¼¼ÄÜÒªÖØË¢ÊôÐÔ£¬ÐèÇø·Ö×°±¸²ÅÉúЧµÄ±»¶¯¼¼ÄÜ
    #===========================================================================
    # if SkillCommon.isPassiveSkill(curSkill) and \
    # curSkill.GetFuncType() not in [ChConfig.Def_SkillFuncType_FbPassiveSkill, ChConfig.Def_SkillFuncType_FbSPSkill]:
    #    BuffSkill.AddBuffNoRefreshState(curPlayer, IPY_GameWorld.btPassiveBuf, curSkill, 
    #                                    0, [], buffOwner = curPlayer)
    #===========================================================================
        
    if curSkill.GetFuncType() == ChConfig.Def_SkillFuncType_HorseSkill and SkillCommon.isPassiveAttr(curSkill):
        PlayerHorse.RefreshHorseAttr(curPlayer)
    else:
        if SkillCommon.isPassiveAttr(curSkill):
            curControl = PlayerControl.PlayerControl(curPlayer)
            curControl.RefreshPlayerAttrState()
        else:
            PassiveBuffEffMng.GetPassiveEffManager().RegistPassiveEff(curPlayer, curSkill.GetSkillID())
        #curControl = PlayerControl.PlayerControl(curPlayer)
        #curControl.CalcPassiveBuffAttr()
        #curControl.RefreshAllState()
            
    PlayerControl.PlayerControl(curPlayer).RefreshSkillFightPowerEx(curSkill.GetSkillID(), beforeFightPower)
    
    #Éý¼¶¼¼ÄÜCDÖ±½ÓÀäÈ´
    curSkill.SetRemainTime(0)
    if curSkill.GetFuncType() == ChConfig.Def_SkillFuncType_HorseSkill:
        PlayerControl.WorldNotify(0, 'GetMountSkill', [curPlayer.GetName(), curSkillID])
    else:
        #֪ͨ¼¼ÄÜÒÑÉý¼¶³É¹¦ GeRen_admin_31379
        PlayerControl.NotifyCode(curPlayer, "GeRen_admin_31379", [curSkillID, curSkill.GetSkillLV()])
    
    #»ñµÃ¼¼Äܵȼ¶
    curSkillLV = curSkill.GetSkillLV()
    DataRecordPack.DR_LearnORUPSkill(curPlayer, curSkillID, curSkillLV)
    EventShell.EventRespons_SkillUp(curPlayer, curSkill.GetFuncType(), curSkillLV)
    GameWorld.Log("Éý¼¶¼¼ÄÜÃû = %s ³É¹¦, µ±Ç°µÈ¼¶ = %s"%(curSkill.GetSkillName(), curSkill.GetSkillLV()), curPlayer.GetPlayerID())
    return True
#---------------------------------------------------------------------
##ѧϰ¼¼ÄÜÏûºÄÂß¼
# @param curPlayer Íæ¼ÒʵÀý
# @param curSkillTypeID ¼¼ÄÜÀàÐÍID
# @param curSkillID ¼¼ÄÜID
# @param upSkillLv ÏÂÒ»µÈ¼¶
# @return BOOL ÊÇ·ñ¿Û³ýÏûºÄ³É¹¦
def DoLogic_PlayerSkillLvUpCost(curPlayer, curSkillTypeID, curSkillID, upSkillLv, curSkill=None):
    upSkill = GameWorld.GetGameData().FindSkillByType(curSkillTypeID, upSkillLv)
    
    if upSkill == None:
        #ÎÞ´ËÉý¼¶¼¼ÄÜ
        GameWorld.ErrLog("ÎÞ´ËÉý¼¶¼¼ÄÜ = %s,%s"%(curSkillTypeID, upSkillLv), curPlayer.GetID())
        return False
    
    #ѧϰÌõ¼þ¼ì²é
    if not CheckLearnSkillCondition(curPlayer, upSkill):
        return False
    
#    #×øÆï¼¼ÄÜѧϰÅжÏ
#    if upSkill.GetFuncType() == ChConfig.Def_SkillFuncType_HorseSkill:
#        if not PlayerHorse.CheckLearnHorseSkill(curPlayer, curSkillTypeID):
#            return False
    #Ì츳¼¼Ñ§Ï°µãÊýÅжÏ
    if upSkill.GetFuncType() == ChConfig.Def_SkillFuncType_GiftSkill:
        if not PlayerGreatMaster.GetGreatMasterFreeSkillPoint(curPlayer):
            return False
        
    #¾Ñé¼ì²â
    skillLvUpNeedExp = upSkill.GetLVUpCostExp()
    
    curExp = PlayerControl.GetPlayerTotalExp(curPlayer)
    #GameWorld.Log("skillLvUpNeedExp=%s  curExp=%s"%(skillLvUpNeedExp, curExp))
    if curExp < skillLvUpNeedExp:
        #¶Ô²»Æð£¬ÄúµÄ¾Ñé²»×㣡GeRen_jin_671654 
        PlayerControl.NotifyCode(curPlayer, "GeRen_jin_671654")
        return False
    
    #ËùÐè½ðÇ®ÀàÐÍ¡¢½ðÇ®ÊýÁ¿
    skillLvUpNeedMoneyType = upSkill.GetLVUpCostMoneyType()
    skillLvUpNeedMoneyCount = upSkill.GetLVUpCostMoney()
    #GameWorld.Log("skillLvUpNeedMoneyType=%s  skillLvUpNeedMoneyCount=%s"%(skillLvUpNeedMoneyType, skillLvUpNeedMoneyCount))
    #realNeedZhenQi = GetLVUpCostZhenQi(upSkill)
    #playerZhenQi = PlayerControl.GetZhenQi(curPlayer)
    
#    if curSkill != None:
#        skillProf = curSkill.GetProficiency() # µ±Ç°¼¼ÄÜÊìÁ·¶È
#        maxSkillProf = GetSkillLVUpCostZhenQi(curSkill) # ×î´ó¼¼ÄÜÊìÁ·¶È
#        proRedFormalZQ, proRedFormalMoney = ReadChConfig.GetEvalChConfig("UpSkillLVReduceCost")
#        realNeedZhenQi = max(realNeedZhenQi - eval(proRedFormalZQ), 0) # ÕæÕýÐèÒª¿Û³ýµÄÕæÆø
#        skillLvUpNeedMoneyCount = max(skillLvUpNeedMoneyCount - eval(proRedFormalMoney), 0) # ÕæÕýÐèÒª¿Û³ýµÄ½ðÇ®
    
    #ÅжÏÕæÆøÏûºÄ
    #if realNeedZhenQi > 0 and playerZhenQi < realNeedZhenQi:
    #    PlayerControl.NotifyCode(curPlayer, "GeRen_pan_367906")  # ÄãµÄÕæÆø²»×ã
    #    return False
    
    #ÅжÏÎïÆ·ÏûºÄ
    itemIndexList = []
    costItemId = GetUpLVCostItemId(upSkill)
    costItemNum = GetUpLVCostItemNum(upSkill)
    if costItemId > 0 and costItemNum > 0:
        itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
        isEnough, itemIndexList = ItemCommon.GetItem_FromPack_ByID(costItemId, itemPack, costItemNum)
        if not isEnough:
            GameWorld.DebugLog("DoLogic_PlayerSkillLvUpCost() up skill(%s) item(%s) no enough" \
                               % (upSkill.GetSkillID(), costItemId))
            return
    #¸¶Ç®
    infoDict = {"SkillID":curSkillID, "SkillLV":upSkillLv, ChConfig.Def_Cost_Reason_SonKey:curSkillTypeID}
    
    if skillLvUpNeedMoneyCount and not PlayerControl.PayMoney(curPlayer, skillLvUpNeedMoneyType, skillLvUpNeedMoneyCount, ChConfig.Def_Cost_SkillLvUp, infoDict):
        return False
    #¿ÛÎïÆ·
    if itemIndexList:
        ItemCommon.ReduceItem(curPlayer, itemPack, itemIndexList, costItemNum, False)
        
    #¿ÛÕæÆø
    #if realNeedZhenQi > 0:
    #    PlayerControl.PlayerLostZhenQi(curPlayer, realNeedZhenQi, "SkillLvUp", {"SkillTypeID":curSkillTypeID, "UpSkillLv":upSkillLv})
    #    DataRecordPack.DR_ChangeZhenQi(curPlayer, "SkillLvUp", realNeedZhenQi, 
    #                                   {"skillID":curSkillTypeID, "LV":upSkillLv})
    
    if skillLvUpNeedExp > 0:
        #¿Û¾Ñé
        PlayerControl.SetPlayerTotalExp(curPlayer, curExp - skillLvUpNeedExp)
        #GeRen_jin_474794  ÄúÏûºÄÁ˾ÑéÖµ:{%S1%}
        PlayerControl.NotifyCode(curPlayer, "GeRen_jin_474794", [skillLvUpNeedExp])
    
    if upSkill.GetFuncType() == ChConfig.Def_SkillFuncType_GiftSkill:
        PlayerGreatMaster.AddGreatMasterSkillPointByLV(curPlayer, -1)
    return True
#---------------------------------------------------------------------
##¼ì²âѧϰ¼¼ÄÜÐèÇóÌõ¼þ
# @param curPlayer Íæ¼ÒʵÀý
# @param curSkill ʱ¼ä´Á
# @return ·µ»ØÖµÕæ, ¼ì²éͨ¹ý
# @remarks ¼ì²âѧϰ¼¼ÄÜÐèÇóÌõ¼þ
def CheckLearnSkillCondition(curPlayer, curSkill):
#    #²»¼ì²é×Ë̬¼¼ÄÜ
#    return True
        
    #Íæ¼ÒµÈ¼¶ÑéÖ¤Ö»Ñé֤δתÉúǰ
    if curPlayer.GetLV() < curSkill.GetLVReq():
        # Íæ¼ÒµÈ¼¶²»¹»Éý¼¶
        GameWorld.DebugLog('Íæ¼ÒµÈ¼¶²»¹»Éý¼¶ curSkill.GetLVReq()=%s'%curSkill.GetLVReq())
        #PlayerControl.NotifyCode(curPlayer, "UseMagicLost12", [upSkillLv])
        return False
    
    skillManager = curPlayer.GetSkillManager()
    #ǰÖü¼ÄÜÐèÇó
    hasLearnSkillReq = False
    #·ÖÖ§µã×ܺÍ
    numLearnSkillPoint = 0
    #µ±Ç°¼¼ÄÜǰÖü¼ÄÜÐèÇó,ǰÖü¼Äܵȼ¶ÐèÇó
    curSkillLearnReq = curSkill.GetLearnSkillReq()
    lvCurSkillLearnReq = curSkill.GetLearnSkillLV()
    #ÐèÒª¶ÔÓ¦Ì츳ϵ±ðµãÊý
    learnSkillPointReq = curSkill.GetLearnSkillPointReq() #ϵ±ð*10000+ÐèÒªµãÊý
    needSeries, needSeriesPoint= learnSkillPointReq/10000, learnSkillPointReq%10000
    curSkillTypeID = curSkill.GetSkillTypeID()
    ipyData = IpyGameDataPY.GetIpyGameDataNotLog('TalentSkill', curSkillTypeID)
    curTalentType = ipyData.GetTalentType() if ipyData else 0
    #»ñÈ¡Íæ¼ÒĿǰËùÓм¼ÄÜ
    for i in xrange(skillManager.GetSkillCount()):
        skill = skillManager.GetSkillByIndex(i)
        if skill == None:
            continue
        
        skillTypeID = skill.GetSkillTypeID()
        lvSkill = skill.GetSkillLV()
        
        #Âú×ãǰÖü¼ÄÜÐèÇó
        if skillTypeID == curSkillLearnReq and lvSkill >= lvCurSkillLearnReq and not hasLearnSkillReq:
            hasLearnSkillReq = True
        ipyData = IpyGameDataPY.GetIpyGameDataNotLog('TalentSkill', skillTypeID)
        if ipyData and ipyData.GetTalentType() is curTalentType and ipyData.GetSeries() is needSeries:
            #ͶÈë·ÖÖ§µã×ܺÍ
            numLearnSkillPoint += skill.GetSkillLV()
    
    #ÓÐǰÖü¼ÄÜIDÐèÒª
    if curSkillLearnReq != 0 and not hasLearnSkillReq:
        PlayerControl.NotifyCode(curPlayer, "GeRen_wjr_717982", [curSkillLearnReq, lvCurSkillLearnReq])
        return False
             
    #ÓзÖÖ§µã×ܺÍÒªÇó
    if learnSkillPointReq != 0 and numLearnSkillPoint < needSeriesPoint:
        PlayerControl.NotifyCode( curPlayer, "UseMagicLost13",[ needSeriesPoint ] ) 
        return False
    
    #Íæ¼ÒÊôÐÔµãÒªÇó
    if not CheckLearnSkillNeedAttr(curPlayer, curSkill):
        return False
        
    return True
def CheckLearnSkillNeedAttr(curPlayer, curSkill):
    #Íæ¼ÒÊôÐÔµãÒªÇó
    curSkillTypeID = curSkill.GetSkillTypeID()
    stateSkillLV = curSkill.GetStateSkillLV() #ÐèÒª»ù´¡ÊôÐÔID*100000+ÐèÒªÊôÐÔµã
    needBaseAttrID, needBaseAttrValue = GetSkillUpNeedAttr(stateSkillLV)
    if needBaseAttrID and needBaseAttrValue:
        baseAttrDict = {
                            ShareDefine.Def_Effect_Metal:PlayerControl.GetMetal(curPlayer),
                            ShareDefine.Def_Effect_Wood:PlayerControl.GetWood(curPlayer),
                            ShareDefine.Def_Effect_Water:PlayerControl.GetWater(curPlayer),
                            ShareDefine.Def_Effect_Fire:PlayerControl.GetFire(curPlayer),
                            ShareDefine.Def_Effect_Earth:PlayerControl.GetEarth(curPlayer),
                         }
        if needBaseAttrID not in baseAttrDict:
            GameWorld.ErrLog('    ¼¼ÄÜÉý¼¶ÊôÐÔµãÌõ¼þÅäÖôíÎó£¬curSkillTypeID=%s,needBaseAttrID=%s'%(curSkillTypeID, needBaseAttrID))
            return False
        curBaseAttrValue = baseAttrDict.get(needBaseAttrID, 0)
        if curBaseAttrValue < needBaseAttrValue:
            #GameWorld.DebugLog('Éý¼¶¼¼ÄÜ%sÐèÒªÊôÐÔµã %s´ïµ½%s, µ±Ç°µãÊý=%s!'%(curSkillTypeID, needBaseAttrID, needBaseAttrValue, curBaseAttrValue))
            return False
    return True
## »ñÈ¡¼¼ÄÜÉý¼¶ÊôÐÔÐèÇó rutrun attrID, attrvalue
def GetSkillUpNeedAttr(stateSkillLV):return stateSkillLV /100000, stateSkillLV%100000
## »ñÈ¡¼¼ÄÜר¾«ÀàÐÍ
def GetSkillElementType(curSkill): return curSkill.GetStateSkillLV() /100000
#// A5 16 Ñ¡Ôñ¼¼ÄÜÎåÐÐר¾« #tagCMSelectSkillElement
#
#struct    tagCMSelectSkillElement
#{
#    tagHead        Head;
#    DWORD    SkillTypeID;    // ר¾«¼¼ÄÜID
#    BYTE    DoType;    // 0-¼¤»îÉý¼¶ 1-ʹÓÃ
#};
def OnSelectSkillElement(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    selectSkillID = clientData.SkillTypeID
    ipyData = IpyGameDataPY.GetIpyGameData('SkillElement', selectSkillID)
    if not ipyData:
        return
    mainSkillID = ipyData.GetMainSkillID()
    if curPlayer.GetLV() < ipyData.GetNeedLV():
        GameWorld.DebugLog('Ñ¡Ôñ¼¼ÄÜÎåÐÐר¾«µÈ¼¶²»×㣡')
        return
    
    skillManager = curPlayer.GetSkillManager()
    mainSkill = skillManager.FindSkillBySkillTypeID(mainSkillID)
    if not mainSkill:
        GameWorld.DebugLog('Ö÷¼¼ÄÜδѧϰ£¬ÎÞ·¨Ñ¡×¨¾«mainSkillID=%s'%mainSkillID)
        return
    doType = clientData.DoType
    curElementSkillID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_SkillElementID % mainSkillID)
    activeSkillLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_SkillElementLV % selectSkillID)
    isChangeSkill = False #ÊÇ·ñ±ä¸üÉúЧµÄ¼¼ÄÜ
    updSelectSkillLV = activeSkillLV
    #ÏÈÅжÏÊÇ·ñ¿ÉÉý¼¶
    if doType is 0:
        nextSkill = GameWorld.GetGameData().FindSkillByType(selectSkillID, activeSkillLV + 1)
        if not nextSkill:
            return
        if not CheckLearnSkillNeedAttr(curPlayer, nextSkill):
            return
        updSelectSkillLV = activeSkillLV + 1
        skillElementType = GetSkillElementType(nextSkill)
        #¿ÉÉý¼¶Ôò¼¤»îÉýÒ»¼¶
        EventShell.EventRespons_ElementSkill(curPlayer, mainSkillID, skillElementType, updSelectSkillLV)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_SkillElementLV % selectSkillID, updSelectSkillLV)
        if curElementSkillID == selectSkillID:
            #ÕýÔÚʹÓõÄר¾«¼¼ÄÜ£¬ÔòÁ¢¼´ÉúЧ
            isChangeSkill = True
    else: # ʹÓÃ
        if not activeSkillLV:
            #δ¼¤»î²»ÄÜʹÓÃ
            return
        if selectSkillID == curElementSkillID:
            return
        isChangeSkill = True
    
    if isChangeSkill:
        #¸ü»»×¨¾«
        if not RefreshElementSkill(curPlayer, selectSkillID)[1]:
            GameWorld.DebugLog('¸ü»»×¨¾« ²»³É¹¦ selectSkillID=%s'%selectSkillID)
            return
        
        UpdateElementSkillSelect(curPlayer, mainSkillID, selectSkillID)
        #ChEquip.ChangeEquipfacadeByLingGen(curPlayer)
        if curElementSkillID and curElementSkillID != selectSkillID:
            #Ô¼¼ÄÜɾ³ý
            skillManager.DeleteSkillBySkillTypeID(curElementSkillID)
        
    
        # ÖØË¢±»¶¯¼¼ÄÜ
        PassiveBuffEffMng.GetPassiveEffManager().RegistPassiveEff(curPlayer)
        # ÖØË¢¼¼ÄÜÕ½Á¦
        curControl = PlayerControl.PlayerControl(curPlayer)
        curControl.RefreshAllSkill()
        curControl.RefreshPlayerAttrState()
       
    NotifyElementSkillInfo(curPlayer, mainSkillID, selectSkillID if updSelectSkillLV != activeSkillLV else 0)
    return
def UpdateElementSkillSelect(curPlayer, mainSkillID, selectSkillID):
    ## ¸üÐÂר¾«¼¼ÄÜÑ¡Ôñ, selectSkillID ¿ÉÄܱ»ÖØÖÃΪ0
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_SkillElementID % mainSkillID, selectSkillID)
    #GameWorld.DebugLog("¸üÐÂר¾«¼¼ÄÜÑ¡Ôñ  mainSkillID=%s, selectSkillID=%s" % (mainSkillID, selectSkillID))
    
    # ÒÔ϶îÍâ¸üÐÂÑ¡ÔñµÄר¾«¼¼ÄܶÔÓ¦±àºÅ£¬ÓÃÓÚ±íÏÖÆäËûÍæ¼Ò²»Í¬×¨¾«¼¼ÄÜÌØÐ§ÓÃ
    mainSkillList = IpyGameDataPY.GetFuncEvalCfg("SkillActTypeIdSort", curPlayer.GetJob())
    if mainSkillID not in mainSkillList:
        return
    mainSkillIndex = mainSkillList.index(mainSkillID)
    if mainSkillIndex < ShareDefine.Def_PDictDigitCnt:
        exAttrValue = curPlayer.GetExAttr7()
        exAttrIndex = mainSkillIndex
    else:
        exAttrValue = curPlayer.GetExAttr8()
        exAttrIndex = mainSkillIndex - ShareDefine.Def_PDictDigitCnt
    
    elementSkillNum = 0
    if selectSkillID:
        ipyData = IpyGameDataPY.GetIpyGameData('SkillElement', selectSkillID)
        if ipyData:
            elementSkillNum = ipyData.GetElementSkillNum()
            
    updExAttrValue = GameWorld.ChangeDataByDigitPlace(exAttrValue, exAttrIndex, elementSkillNum)
    #GameWorld.DebugLog("    exAttrValue=%s,exAttrIndex=%s,elementSkillNum=%s,updExAttrValue=%s" 
    #                   % (exAttrValue, exAttrIndex, elementSkillNum, updExAttrValue))
    
    # ÐèÒª¹ã²¥ÖÜÎ§Íæ¼Ò
    if mainSkillIndex < ShareDefine.Def_PDictDigitCnt:
        curPlayer.SetExAttr7(updExAttrValue, True)
    else:
        curPlayer.SetExAttr8(updExAttrValue, True)
    return
def RefreshElementSkill(curPlayer, skillTypeID, isChangeLV=True):
    ##¸üÐÂר¾«¼¼ÄÜÉúЧµÄµÈ¼¶
    isNotify, hasChangeLV = False, False
    __InitElementSkillInfo()
    if skillTypeID not in PyGameData.g_elemntSkillDict:
        return isNotify, hasChangeLV
    baseAttrDict = {
                            ShareDefine.Def_Effect_Metal:PlayerControl.GetMetal(curPlayer),
                            ShareDefine.Def_Effect_Wood:PlayerControl.GetWood(curPlayer),
                            ShareDefine.Def_Effect_Water:PlayerControl.GetWater(curPlayer),
                            ShareDefine.Def_Effect_Fire:PlayerControl.GetFire(curPlayer),
                            ShareDefine.Def_Effect_Earth:PlayerControl.GetEarth(curPlayer),
                         }
    activeSkillLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_SkillElementLV % skillTypeID)
    limitInfoList = PyGameData.g_elemntSkillDict[skillTypeID]
    maxSkillLV = len(limitInfoList)
    updSkillLV = 0
    for i, limitInfo in enumerate(limitInfoList):
        needAttrID, needAttrValue = GetSkillUpNeedAttr(limitInfo)
        curAttrValue = baseAttrDict.get(needAttrID, 0)
        if curAttrValue >= needAttrValue:
            updSkillLV = maxSkillLV - i
            break
    if activeSkillLV > updSkillLV:
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_SkillElementLV % skillTypeID, updSkillLV)
        isNotify = True
    updSkillLV = min(updSkillLV, activeSkillLV) #²»¿É³¬¹ý¼¤»îµÄµÈ¼¶
    skillManager = curPlayer.GetSkillManager()
    curSkill = skillManager.FindSkillBySkillTypeID(skillTypeID)
    curSkillLV = curSkill.GetSkillLV() if curSkill else 0
    #GameWorld.DebugLog('¸üÐÂר¾«¼¼ÄÜÉúЧµÄµÈ¼¶ skillTypeID=%s,curSkillLV=%s,activeSkillLV=%s,updSkillLV=%s'%(skillTypeID, curSkillLV, activeSkillLV, updSkillLV))
    if not isChangeLV:
        return isNotify, hasChangeLV
    if updSkillLV == curSkillLV:
        return isNotify, hasChangeLV
    elif updSkillLV < curSkillLV:
        skillManager.DeleteSkillBySkillTypeID(skillTypeID)
        for _ in xrange(updSkillLV):
            skillManager.LVUpSkillBySkillTypeID(skillTypeID)
        if updSkillLV == 0:#ÖØÖÃΪδѡ״̬
            ipyData = IpyGameDataPY.GetIpyGameData('SkillElement', skillTypeID)
            mainSkillID = ipyData.GetMainSkillID()
            UpdateElementSkillSelect(curPlayer, mainSkillID, 0)
            #ChEquip.ChangeEquipfacadeByLingGen(curPlayer)
            isNotify = True
    else:
        for _ in xrange(updSkillLV-curSkillLV):
            skillManager.LVUpSkillBySkillTypeID(skillTypeID)
    return isNotify, True
def RefreshElementSkillByAttr(curPlayer, attrIDList):
    #¼Óµã¡¢µ¤Ò©¡¢¾³½ç¡¢Ï´µã »áÓ°ÏìÁé¸ùµã
    __InitElementSkillInfo()
    
    needRefreshSkillIDDict = {} #{skillid:ÊÇ·ñ±ä¸ü¼¼Äܵȼ¶}
    skillManager = curPlayer.GetSkillManager()
    for i in xrange(skillManager.GetSkillCount()):
        hasSkill = skillManager.GetSkillByIndex(i)
        hasSkillID = hasSkill.GetSkillTypeID()
        ipyDataList = IpyGameDataPY.GetIpyGameDataByCondition('SkillElement', {'MainSkillID':hasSkillID}, True, False)
        if not ipyDataList:
            continue
        curSelectSkillID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_SkillElementID % hasSkillID)
        for ipyData in ipyDataList:
            curElementSkillID = ipyData.GetElementSkillID()
            if curElementSkillID not in PyGameData.g_elemntSkillDict:
                continue
            attrID = GetSkillUpNeedAttr(PyGameData.g_elemntSkillDict[curElementSkillID][0])[0]
            if attrID not in attrIDList:
                continue
            needRefreshSkillIDDict[curElementSkillID] = curSelectSkillID == curElementSkillID
    
    #GameWorld.DebugLog('ÊôÐÔµã±ä¸ü Ë¢ÐÂר¾«attrIDList=%s,needRefreshSkillIDList=%s'%(attrIDList,needRefreshSkillIDList))
    needNotify, isRefresh = False, False
    for skillID, isChangeLV in needRefreshSkillIDDict.items():
        isNotify, hasChangeLV = RefreshElementSkill(curPlayer, skillID, isChangeLV)
        if isNotify:
            needNotify = True
        if hasChangeLV:
            isRefresh = True
    if isRefresh:
        # ÖØË¢±»¶¯¼¼ÄÜ
        PassiveBuffEffMng.GetPassiveEffManager().RegistPassiveEff(curPlayer)    
        # ÖØË¢¼¼ÄÜÕ½Á¦
        curControl = PlayerControl.PlayerControl(curPlayer)
        curControl.RefreshAllSkill()
        curControl.RefreshPlayerAttrState()
    if needNotify:
        NotifyElementSkillInfo(curPlayer)
    return
def GetElementSkillCnt(curPlayer, mainSkillIDList, activeLV, elementType=0):
    ##»ñÈ¡ÒÑÑ¡ÔñµÄר¾«¼¼ÄÜÊýÁ¿
    # @param elementType: ר¾«ÀàÐÍ£¬¶ÔÓ¦Áé¸ùID
    gameData = GameWorld.GetGameData()
    cnt = 0
    skillManager = curPlayer.GetSkillManager()
    for i in xrange(skillManager.GetSkillCount()):
        hasSkill = skillManager.GetSkillByIndex(i)
        hasSkillID = hasSkill.GetSkillTypeID()
        if hasSkillID not in mainSkillIDList:
            continue
        ipyDataList = IpyGameDataPY.GetIpyGameDataByCondition('SkillElement', {'MainSkillID':hasSkillID}, True, False)
        if not ipyDataList:
            continue
        for ipyData in ipyDataList:
            elementSkillID = ipyData.GetElementSkillID()
            if elementType:
                elementSkillData = gameData.GetSkillBySkillID(elementSkillID)
                if GetSkillElementType(elementSkillData) != elementType:
                    continue
            curActiveLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_SkillElementLV % elementSkillID)
            if curActiveLV >= activeLV:
                cnt += 1
    return cnt
def __InitElementSkillInfo():
    #»º´æ¼¼ÄÜר¾«ÐÅÏ¢{skillID:[attrID*100000+needValue,..]}
    if not PyGameData.g_elemntSkillDict:
        ipyMgr = IpyGameDataPY.IPY_Data()
        for i in xrange(ipyMgr.GetSkillElementCount()):
            ipyData = ipyMgr.GetSkillElementByIndex(i)
            elementSkillID = ipyData.GetElementSkillID()
            skill = GameWorld.GetGameData().FindSkillByType(elementSkillID, 1)
            if not skill:
                continue
            skillMaxLV = skill.GetSkillMaxLV() # ×î¸ß¼¼Äܵȼ¶
            for skillLV in xrange(skillMaxLV, 0, -1):
                curSkill = GameWorld.GetGameData().FindSkillByType(elementSkillID, skillLV)
                if not curSkill:
                    continue
                if elementSkillID not in PyGameData.g_elemntSkillDict:
                    PyGameData.g_elemntSkillDict[elementSkillID] = []
                PyGameData.g_elemntSkillDict[elementSkillID].append(curSkill.GetStateSkillLV())
    return
def NotifyElementSkillInfo(curPlayer, mainSkillID=0, changeSkillID=0):
    ##֪ͨÎåÐÐר¾«ÐÅÏ¢
    if not mainSkillID:
        syncMainSkillDict = {}
        skillManager = curPlayer.GetSkillManager()
        for i in xrange(skillManager.GetSkillCount()):
            hasSkill = skillManager.GetSkillByIndex(i)
            hasSkillID = hasSkill.GetSkillTypeID()
            ipyDataList = IpyGameDataPY.GetIpyGameDataByCondition('SkillElement', {'MainSkillID':hasSkillID}, True, False)
            if not ipyDataList:
                continue
            syncMainSkillDict[hasSkillID] = []
            for ipyData in ipyDataList:
                syncMainSkillDict[hasSkillID].append(ipyData.GetElementSkillID())
    else:
        syncMainSkillDict = {mainSkillID:[changeSkillID]} if changeSkillID else {mainSkillID:[]}
    sendPack = ChPyNetSendPack.tagMCSkillElementInfo()
    sendPack.InfoList = []
    for mSkillID, elementList in syncMainSkillDict.items():
        curElementSkillID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_SkillElementID % mSkillID)
        elementData = ChPyNetSendPack.tagMCSkillElementData()
        elementData.MainSkillID = mSkillID
        elementData.ElementSkillID = curElementSkillID
        elementData.ActiveSkill = []
        for elementSkillID in elementList:
            activeData = ChPyNetSendPack.tagMCSkillElementActiveData()
            activeData.SkillID = elementSkillID
            activeData.ActiveLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_SkillElementLV % elementSkillID)
            elementData.ActiveSkill.append(activeData)
        elementData.SkillCnt = len(elementData.ActiveSkill)
        sendPack.InfoList.append(elementData)
    sendPack.Cnt = len(sendPack.InfoList)
    NetPackCommon.SendFakePack(curPlayer, sendPack)
    return
    
#---------------------------------------------------------------------
##µ±Ç°buffÊÇ·ñÄܹ»´¥·¢BuffProcess_%d µÄ½Å±¾
# @param curObj ¶ÔÏó
# @param curBuffSkill ¼¼ÄÜʵÀý
# @return ·µ»ØÖµÕæ, ͨ¹ý
# @remarks µ±Ç°buffÊÇ·ñÄܹ»´¥·¢BuffProcess_%d µÄ½Å±¾
def __BuffCanProcess(curObj, curBuffSkill):
    buffSkillType = curBuffSkill.GetSkillType()
    
    if buffSkillType in ChConfig.Def_LstBuff_List:
        #ÊǼä¸ô´¦ÀíµÄ¼¼ÄÜ
        return True
#===============================================================================
#    #¹â»·´¦Àí, Èç¹û¹âÔ´ÊÇ×Ô¼º, ÔòÈ¥BuffProcess´¦Àí( //Èç¹â»·, ïÚ³µ¼ÓËÙ )
#    if (buffSkillType == 11 and curObj.GetID() == curBuff.GetOwnerID() and
#            curObj.GetGameObjType() == curBuff.GetOwnerType()):
#        return True 
#===============================================================================
    return False
#---------------------------------------------------------------------
##È¡µÃ³ÖÐøBUFFµÄ´¥·¢¼ä¸ô
# @param curBuffSkill BUFF¼¼ÄÜ
# @return ³ÖÐøÊ±¼ä¼ä¸ô
# @remarks È¡µÃ³ÖÐøBUFFµÄ´¥·¢¼ä¸ô
def GetProcessBuffTick(curBuffSkill, curObj):
    buffTick = ChConfig.Def_ProcessPersistBuff
    
    curEffect = SkillCommon.GetSkillEffectByEffectID(curBuffSkill, ChConfig.Def_Skill_Effect_BuffTick)
    
    if curEffect != None:
        buffTick = curEffect.GetEffectValue(0)
        if curEffect.GetEffectValue(1):
            # ¼ÓËÙ
            buffTick = int(curObj.GetAtkInterval()/ChConfig.Def_AtkSpeedBase*buffTick)
    return buffTick
##¼ÆËã³ÖÐøbuffЧ¹û
# @param curObj ¶ÔÏó
# @param buffState Buff¹ÜÀíÆ÷
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¼ÆËã³ÖÐøbuffЧ¹û
def __ProcessCurPersistBuff(curObj, buffState, tick):
    buffStateCount = buffState.GetBuffCount()
    
    if not buffStateCount:
        return
    
    #buff³ÖÐøÐ§¹û
    for i in range(0, buffStateCount):
        curBuff = buffState.GetBuff(i)
        
        if not curBuff:
            #ÔÚÒÔÏ´¦Àí¹ý³ÌÖÐ, ¶Ô·½ÓпÉÄÜËÀÍö, Èç¹ûËÀÍö, »áÇå¿Õbuff, µ¼ÖÂÕâÀïÈ¡µÃNone
            #ËùÒÔÒ»¶¨Òªcontinue 
            continue
        
        curBuffSkill = curBuff.GetSkill()
        
        if not __BuffCanProcess(curObj, curBuffSkill):
            continue
        processBuffTick = GetProcessBuffTick(curBuffSkill, curObj)
        
        #---ÑéÖ¤´¥·¢¼ä¸ôTICK---
        if tick - curBuff.GetProcessInterval() <= processBuffTick:
            continue
        curBuff.SetProcessInterval(tick)
        
        
        #µÃµ½µ±Ç°buff
        for effIndex in range(0, curBuffSkill.GetEffectCount()):
            #µÃµ½µ±Ç°Ð§¹û
            curEffect = curBuffSkill.GetEffect(effIndex)
            curEffectID = curEffect.GetEffectID()
            
            if not curEffectID:
                continue
            
            processStr = "BuffProcess_%d.%s"%(curEffectID, "ProcessBuff")
            
            callBuffProcessFunc = GameWorld.GetExecFunc(GameBuffs, processStr)
            
            if not callBuffProcessFunc:
                continue
            
            callBuffProcessFunc(curObj, curBuff, curEffect, processBuffTick, tick)
    
    #Ö´ÐÐProcessBuffÖÐÉ趨µÄÍæ¼Ò×Öµä
    __DoProcessBuff_PlayerKey(curObj, tick)
#---------------------------------------------------------------------
##Ö´ÐÐProcessBuffÖÐÉ趨µÄÍæ¼Ò×Öµä
# @param curObj ¶ÔÏó
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Ö´ÐÐProcessBuffÖÐÉ趨µÄÍæ¼Ò×Öµä
def __DoProcessBuff_PlayerKey(curObj, tick):
#===============================================================================
#    if curObj.GetDictByKey(ChConfig.Def_Player_ProBuff_TruckSpeedUp):
#        skillID = curObj.GetDictByKey(ChConfig.Def_Player_ProBuff_TruckSpeedUp)
#        #±¾À´buffÀàÐÍÊÇ11, µ«ÊÇæô³µÃ»ÓÐÎïÆ·buff, ËùÒÔ¸ÄΪ8
#        buffType = IPY_GameWorld.bfAura       
#        #¸ø×Ô¼ºµÄïÚ³µ¼Óbuff
#        curSkill = GameWorld.GetGameData().GetSkillBySkillID(skillID)
#        if not curSkill:
#            GameWorld.Log('###ïÚ³µBuff¼¼ÄÜIDÒì³£ = %s'%(skillID))
#            return
#        
#        BuffSkill.DoAddBuff(curObj.GetTruck() , buffType, curSkill, tick, 0, curObj)
#        curObj.SetDict(ChConfig.Def_Player_ProBuff_TruckSpeedUp , 0)
#===============================================================================
    return
#---------------------------------------------------------------------
##³ÖÐøÐÔbuffµÄÉ˺¦Ð§¹û
# @param curObj ¶ÔÏó
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ³ÖÐøÐÔbuffµÄÉ˺¦Ð§¹û
def ProcessPersistBuff(curObj, tick):
    #³ÖÐøÔöÒæ
    __ProcessCurPersistBuff(curObj, curObj.GetProcessBuffState(), tick)
    
    #³ÖÐø¼õÒæ
    __ProcessCurPersistBuff(curObj, curObj.GetProcessDeBuffState(), tick)
    
    #Íæ¼Ò¶ÀÓÐ
    if curObj.GetGameObjType() == IPY_GameWorld.gotPlayer:
        #Íæ¼Ò×°±¸¹â»·
        __ProcessCurPersistBuff(curObj, curObj.GetEquipBuff(), tick)
        #³¡¾°É˺¦
        __ProcessCurPersistBuff(curObj, curObj.GetMapBuff(), tick)
    
    return
#---------------------------------------------------------------------
##´¦Àí³¡¾°Buff
# @param curPlayer Íæ¼ÒʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ³¡¾°BuffÔö¼ÓºÍɾ³ý
def ProcessMapBuff(curPlayer, tick):
    #³¡¾°BUFFˢмä¸ô
    if tick - curPlayer.GetTickByType(ChConfig.TYPE_Player_Tick_MapBuff) \
        < ChConfig.TYPE_Player_Tick_Time[ChConfig.TYPE_Player_Tick_MapBuff]:
        return
    
    curPlayer.SetTickByType(ChConfig.TYPE_Player_Tick_MapBuff, tick)
    
    #³¡¾°BuffÊÇ·ñÓбä¸ü
    if __ProcessMapEffect(curPlayer, tick):
        #³¡¾°buff´¦Àí³É¹¦, ˢг¡¾°×´Ì¬
        ProcessPlayerAreaState(curPlayer)
        
    return
#---------------------------------------------------------------------
##ˢеØÍ¼BuffЧ¹û
# @param curPlayer Íæ¼ÒʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµ, ÊÇ·ñÖØË¢ÊôÐÔ
# @remarks ˢеØÍ¼BuffЧ¹û
def __ProcessMapEffect(curPlayer, tick):
    gameMap = GameWorld.GetMap()
    # Ôö¼Ó³¡¾°ÑéÖ¤, ÈôÖ»ÓÐÇøÓòÀàÐÍÅж¨¿É²»½øÈë´ËÂß¼£¬È簲ȫ¡¢PK¡¢¼Ò×åÇø£¬Ö±½ÓÈ¡×ø±êµôÅж¨¼´¿ÉGetAreaTypeByMapPos
    # ÈôÊdz¡¾°É˺¦»òÕß¶¯Ì¬±ä»¯µÄÇøÓò£¬¿É½øÈë´ËÂß¼
    # GetAreaType()Ö»ÓÐbuffÉèÖúó²ÅÄÜ»ñÈ¡µ½
    if curPlayer.GetMapID() not in []:
        #ÌØÊâÇøÓò´ý¹¦Äܰ²ÅÅ
        return
    
    curPosObj = gameMap.GetPosObj(curPlayer.GetPosX(), curPlayer.GetPosY())
    
    mapBuffManager = curPlayer.GetMapBuff()
    if curPosObj == None :
        GameWorld.ErrLog("###´¦Àí³¡¾°buff²éÕÒÍæ¼Òʧ°Ü" , curPlayer.GetID())
        mapBuffManager.Clear()
        return True
    
    effectCount = curPosObj.GetEffectCount()
    if effectCount == 0 or not curPlayer.IsAlive():
        #Íæ¼ÒÀ뿪³¡¾°, »òÕßËÀÍöÈ¡Ïûbuff
        DoMapBuffClear(curPlayer)
        #GameWorld.Log("Íæ¼ÒÀ뿪³¡¾°buff")
        return True
    
    #ËÀÍö²»Ìí¼Ó
    #ÊÇ·ñÐèÒªÖØË¢³¡¾°Buff
    processResult = False
    index = 0
    
    # ¸ù¾ÝÍæ¼ÒÏÖÓеĵØÍ¼buff¸öÊý´¦ÀíÏûʧÂß¼
    while index < mapBuffManager.GetBuffCount():
        curRoleBuff = mapBuffManager.GetBuff(index)
        ownerID, ownerType = curRoleBuff.GetOwnerID(), curRoleBuff.GetOwnerType()
        skillID = curRoleBuff.GetSkill().GetSkillID()
        #MapPosµÄkeyΪskillID
        if not curPosObj.HaveEffect(skillID):
            
            curSkill = curRoleBuff.GetSkill()
            for effectIndex in range(0, curSkill.GetEffectCount()):
                curEffect = curSkill.GetEffect(effectIndex)
                effectID = curEffect.GetEffectID()
                if effectID == 0:
                    continue
    
                callFunc = GameWorld.GetExecFunc(GameBuffs, "MapBuff_%d.%s"%(effectID, "OnMapBuffDel"))
    
                if callFunc == None:
                    continue
    
                #µ÷ÓÃË¢ÐÂbuff
                callFunc(curPlayer, curEffect)
                
            mapBuffManager.DeleteBuffByIndex(index)
            ClearBuffEffectBySkillID(curPlayer, skillID, ownerID, ownerType)
            #GameWorld.Log("ɾ³ý³¡¾°Buff %d"%skillID)
            processResult = True
            continue
        
        index += 1
        
    gameData = GameWorld.GetGameData()
    
    for i in range(0, effectCount):
        effectID = curPosObj.GetEffectID(i)
        if effectID == 0:
            continue
        
        curSkill = gameData.GetSkillBySkillID(effectID)
        
        if curSkill == None:
            GameWorld.ErrLog("ProcessMapEffect skill = %s ²»´æÔÚ"%(effectID) , curPlayer.GetID())
            break
        
        #BuffµÄkeyΪskillTypeID
        skillTypeID = curSkill.GetSkillTypeID()
        findBuff = mapBuffManager.FindBuff(skillTypeID)
        if findBuff:
            # ¼¼ÄÜIDÏàͬ£¬»òÕ߲߻®²¿ÊðÁ½¸öµÈ¼¶µÄ²¢ÒÑÓµÓиü¸ßµÈ¼¶µÄ²»´¦Àí
            if findBuff.GetSkill().GetSkillID() == curSkill.GetSkillID():
                continue
            if findBuff.GetSkill().GetSkillLV() > curSkill.GetSkillLV():
                continue
            
        #Ìí¼Ó³¡¾°buff
        isOK = BuffSkill.AddBuffNoRefreshState(curPlayer, IPY_GameWorld.bfMapBuff, curSkill, tick)
        processResult = processResult or isOK
          
    return processResult
def DoMapBuffClear(curPlayer):
    buffManager = curPlayer.GetMapBuff()
    
    for buffIndex in range(0, buffManager.GetBuffCount()):
        curBuff = buffManager.GetBuff(buffIndex)
        curSkill = curBuff.GetSkill()
        
        if curSkill.GetSkillID() == 0:
            continue
        
        for effectIndex in range(0, curSkill.GetEffectCount()):
            curEffect = curSkill.GetEffect(effectIndex)
            effectID = curEffect.GetEffectID()
            if effectID == 0:
                continue
            callFunc = GameWorld.GetExecFunc(GameBuffs, "MapBuff_%d.%s"%(effectID, "OnMapBuffDel"))
            if callFunc == None:
                continue
            #µ÷ÓÃË¢ÐÂbuff
            callFunc(curPlayer, curEffect)
    buffManager.Clear()
    return
#---------------------------------------------------------------------
##Ë¢ÐÂÍæ¼Ò³¡¾°×´Ì¬
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Ë¢ÐÂÍæ¼Ò³¡¾°×´Ì¬
def ProcessPlayerAreaState(curPlayer):
    #³õʼ»¯ËùÓеij¡¾°buff״̬
    playerControl = PlayerControl.PlayerControl(curPlayer)
    playerControl.InitMapBuffState()
    
    buffManager = curPlayer.GetMapBuff()
    
    for buffIndex in range(0, buffManager.GetBuffCount()):
        curBuff = buffManager.GetBuff(buffIndex)
        curSkill = curBuff.GetSkill()
        
        if curSkill.GetSkillID() == 0:
            continue
        
        for effectIndex in range(0, curSkill.GetEffectCount()):
            curEffect = curSkill.GetEffect(effectIndex)
            effectID = curEffect.GetEffectID()
            if effectID == 0:
                continue
            callFunc = GameWorld.GetExecFunc(GameBuffs, "MapBuff_%d.%s"%(effectID, "OnMapBuff"))
            if callFunc == None:
                continue
            #µ÷ÓÃË¢ÐÂbuff
            callFunc(curPlayer, curEffect)
    return
#---------------------------------------------------------------------
##Ìí¼Ó×°±¸´¥·¢µÄBuff
# @param curPlayer Íæ¼ÒʵÀý
# @param curEquip ×°±¸ÊµÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Ìí¼Ó×°±¸´¥·¢µÄBuff
def RefreshSkillBuffByEquip(curPlayer, curEquip) :
    #Ò»°ã×°±¸ÐÂÔöBuff
    __DoEquip_AddBuff(curPlayer, curEquip)
    return
#---------------------------------------------------------------------
##Ìí¼Ó×°±¸´¥·¢µÄBuff, Ò»°ã×°±¸ÐÂÔöBuff
# @param curPlayer Íæ¼ÒʵÀý
# @param curEquip ×°±¸ÊµÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Ìí¼Ó×°±¸´¥·¢µÄBuff, Ò»°ã×°±¸ÐÂÔöBuff
def __DoEquip_AddBuff(curPlayer, curEquip):
    gameData = GameWorld.GetGameData()
    playerVehicle = curPlayer.GetPlayerVehicle()
    houseState = curPlayer.GetPlayerRidehorseState()
    
    for index in range(0 , curEquip.GetAddSkillCount()):
        curSkillID = curEquip.GetAddSkill(index)
        
        if curSkillID == 0:
            continue
        
        #ͨ¹ý¼¼ÄÜID»ñµÃʹÓü¼ÄÜ
        curSkill = gameData.GetSkillBySkillID(curSkillID)
        
        if curSkill == None :
            GameWorld.Log("×°±¸´¥·¢¼¼ÄÜ,ÎïÆ·±í´íÎó curSkillID = %s"%(curSkillID) , curPlayer.GetPlayerID())
            continue
        
        #ÆïÂí´¥·¢¼¼ÄÜ
        houseSkill = ChConfig.Def_Skill_TypeID_Speed
        curSkillType = curSkill.GetSkillTypeID()
        
        if not SkillCommon.IsBuff(curSkill):
            continue
        
        if curSkillType in houseSkill:
            #²»Ê¹ÓÃ,²»Ìí¼Óbuff
            if playerVehicle != IPY_GameWorld.pvHorse :
                continue
            
            if curSkillType == houseSkill[0] and houseState != IPY_GameWorld.prsNormal :
                continue
            
            if curSkillType == houseSkill[1] and houseState != IPY_GameWorld.prsRun :
                continue
            
        #Ìí¼ÓBuff
        BuffSkill.AddBuffNoRefreshState(curPlayer, IPY_GameWorld.bfEquipBuff, curSkill, 0, [], buffOwner = curPlayer)
        
    return
#---------------------------------------------------------------------
##Ë¢ÐÂbuffµÄЧ¹û
# @param buffState Buff¹ÜÀíÆ÷
# @param sameEffectCanWork ÊÇ·ñ¿ÉÒÔµþ¼ÓÏàͬЧ¹û,  : Ч¹ûÊÇ·ñ¿ÉÒÔµþ¼Ó, ĬÈÏΪ·ñ
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks Ë¢ÐÂbuffµÄЧ¹û (²ÎÊý -> buff¹ÜÀíÆ÷,ÊÇ·ñµþ¼Ó)
def __RefreshSkillBuffEffect(buffState, sameEffectCanWork = False):
    return
    #===========================================================================
    # buffState.ClearEffects()
    # for buffIndex in range(0, buffState.GetBuffCount()):
    #    curBuff = buffState.GetBuff(buffIndex)
    #    buffValue = curBuff.GetValue()
    #    curSkill = curBuff.GetSkill()
    #    skillID = curSkill.GetSkillID()
    #    if skillID == 0:
    #        continue
    #    
    #    for effectIndex in range(0, curSkill.GetEffectCount()):
    #        curEffect = curSkill.GetEffect(effectIndex)
    #        effectID = curEffect.GetEffectID()
    #        if effectID == 0:
    #            continue
    #        
    #        buffState.AddEffect(curEffect, buffValue, skillID, curBuff.GetOwnerID(), curBuff.GetOwnerType())
    #===========================================================================
#---------------------------------------------------------------------
##¼ÆËãЧ¹ûÖµ
# @param buffState Buff¹ÜÀíÆ÷
# @param curObjDetail ¶ÔÏóʵÀý
# @param allAttrList Ч¹ûÁбí
# @param calcEffectIDList Ö¸¶¨¼ÆËãЧ¹û
# @param calcLevel ¼ÆËã²ã¼¶£¨Ä¿Ç°ÊǰٷֱÈÓÐÄÚÍâ²ãÖ®·Ö£©
# @return ·µ»ØÖµÎÞÒâÒå
def CalcCurBuffer_Effect(buffState, curObjDetail, allAttrList, calcEffectIDList = [], calcLevel = 0):    
    __CallBuffFunc(buffState, curObjDetail, allAttrList, calcEffectIDList, calcLevel)
    return
#---------------------------------------------------------------------
##¼ÆËãBuffЧ¹û.ͨ¹ýÌî±í¼ÆËã
# @param buffState Buff¹ÜÀíÆ÷
# @param objDetel ¶ÔÏóʵÀý(Íæ¼Ò, NPC, ³èÎï)
# @param allAttrList Ч¹ûÁбí
# @return ·µ»ØÖµÎÞÒâÒå
def __CallBuffFunc(buffState, objDetel, allAttrList, calcEffectIDList = [], calcLevel = 0):
    for i in xrange(0, buffState.GetBuffCount()):
        curBuff = buffState.GetBuff(i)
        buffSkill = curBuff.GetSkill()
        
        attrMapID = GetAttrMapID(buffSkill) # Ö»ÓÐÔÚÖ¸¶¨µØÍ¼²ÅÄÜÉúЧµÄbuffЧ¹û
        if attrMapID and objDetel.GetGameObjType() == IPY_GameWorld.gotPlayer \
        and attrMapID != FBCommon.GetRecordMapID(objDetel.GetMapID()):
            continue
        
        for i in xrange(buffSkill.GetEffectCount()):
            curEffect = buffSkill.GetEffect(i)
            curEffectID = curEffect.GetEffectID()
            if curEffectID == 0:
                continue
            
            if calcEffectIDList and curEffectID not in calcEffectIDList:
                continue
            
            CalcBuffEffAttr(objDetel, curEffect, allAttrList, calcLevel, curBuff.GetValue(), curBuff)
        
    return
# plusValueΪbuffµÄµÚÒ»¸övalue
def CalcBuffEffAttr(objDetel, curEffect, allAttrList, calcLevel=0, plusValue=0, curBuff=None):
    # ¼ÆËãbuffЧ¹ûÊôÐÔ
    
    curEffectID = curEffect.GetEffectID()
    if curEffectID == 0:
        return
    
    # »ñµÃbuffЧ¹ûµÄ¼ÆËãÄ£¿éÎļþºó׺
    moduleSuffix = GetBuffModuleSuffix(curEffect, calcLevel) 
    
    skillTypeFunc = GameWorld.GetExecFunc(GameBuffs, "Buff_%s.%s"%(moduleSuffix, "GetCalcType"))
    if not skillTypeFunc:
        return
    index = GetAttrListIndex(SkillCommon.IsBaseEffect(curEffect), skillTypeFunc())
    if index == -1:
        return
    
    # ¼æÈÝÁ½ÖÖ¼ÆËã
    callFunc = GameWorld.GetExecFunc(GameBuffs, "Buff_%s.%s"%(moduleSuffix, "OnCalcBuff"))
    if callFunc:
        # BUFF¼ÆËãÖ»Ö§³ÖÒ»ÖÖÔöÇ¿Èë¿Ú£¬Í¨¹ýGetEffectPlusValue´¦Àí
        callFunc(objDetel, curEffect, allAttrList[index], plusValue)
    else:
        callFunc = GameWorld.GetExecFunc(GameBuffs, "Buff_%s.%s"%(moduleSuffix, "OnCalcBuffEx"))
        if callFunc:
            callFunc(objDetel, curEffect, allAttrList[index], curBuff)
    
    #ÊÇ·ñ³ÖÐøÐÔ¼¼ÄÜ
    if curBuff and curBuff.GetSkill().GetSkillType() in ChConfig.Def_LstBuff_List:
        # ³ÖÐøÐÔÊôÐԱ仯µÄbuff£¬Ä¿Ç°Ö»ÓгÖÐø¼õÒæ
        callFunc = GameWorld.GetExecFunc(GameBuffs, "BuffProcess_%s.%s"%(moduleSuffix, "OnCalcBuffEx"))
        if callFunc:
            callFunc(objDetel, curEffect, allAttrList[index], curBuff)
    return
## »ñµÃbuffЧ¹ûµÄ¼ÆËãÄ£¿éÎļþºó׺
#  @param curEffectID Ч¹ûid
#  @return ÁбíË÷Òý  
def GetBuffModuleSuffix(curEffect, calcLevel = 0):
    curEffectID = curEffect.GetEffectID()
    if calcLevel == ChConfig.CalcBuffLevel_1:
        # Íâ²ã¼ÆËãÂß¼´¦Àí
        return ChConfig.Def_Skill_BuffEffectOutside.get(curEffectID, ["", []])[0]
    
    suffixName, attrList = BuffSkill.FindBuffAttrByEffectID(curEffect)
    
    return suffixName if suffixName else curEffectID
##»ñµÃÊôÐÔÁбíË÷Òý, Ö»ÓÃÓÚË¢ÐÔÊôÐÔµÄallAttrList
# @param isBaseEff ÊÇ·ñ»ù´¡ÊôÐÔ
# @param calcType ÏßÐÔÀàÐÍ
# @return ÁбíË÷Òý  
def GetAttrListIndex(isBaseEff, calcType):
    if calcType is None:
        return -1
    
    return ChConfig.Def_CalcAttrIndexDict[(isBaseEff, calcType)]
##Ë¢ÐÂÍæ¼ÒËùÓÐÓ°ÏìÊôÐÔµÄBuff£¬Ìí¼ÓÊ±Ö»ÖØ¼ÆËãͬÀàÐÍBUFF£¬É¾³ýʱˢÐÂËùÓÐÀàÐÍBUFF
# @param curPlayer Íæ¼ÒʵÀý
# @param buffType buffÀàÐÍ -1´ú±íÈ«²¿Ë¢ÐÔ
# @return ·µ»ØÖµÎÞÒâÒå
def RefreshPlayerBuffOnAttrAddEffect(curPlayer, buffType=-1):
    return
#===============================================================================
#    GameWorld.DebugLog("Start RefreshPlayerBuffOnAttrAddEffect!!!")
#    
#    #[[BuffState, CanPileup]]
#    if buffType == -1:
#        buffRefreshList = [
#            [curPlayer.GetBuffState(), False], [curPlayer.GetDeBuffState(), False],
#            [curPlayer.GetAura(), False], [curPlayer.GetIncBuff(), True],
#            [curPlayer.GetPassiveBuf(), True], [curPlayer.GetEquipBuff(), True],
#                       ]
#    else:    
#        #Ö»ÖØ¼ÆËã¸Ä±äµÄBUFF, ÕâÀï²»·À·¶·ÇÊôÐÔÀàÐÍBUFFÍâ²ã¹ýÂË
#        buffManagerInfo = SkillCommon.GetBuffManagerByBuffType(curPlayer, buffType)
#        buffRefreshList = [[buffManagerInfo[0],  buffManagerInfo[2]]]
#        
#    #Ö´ÐÐË¢ÐÂÂß¼
#    __DoRefreshBuff(buffRefreshList)
# 
#    return
#===============================================================================
# ͨ¹ý¼¼ÄÜIDɾ³ýbuff¶ÔÓ¦µÄЧ¹ûID
def ClearBuffEffectBySkillID(curObj, skillID, ownerID, ownerType):
    curSkill = GameWorld.GetGameData().GetSkillBySkillID(skillID)
    buffType = SkillCommon.GetBuffType(curSkill)
    buffTuple = SkillCommon.GetBuffManagerByBuffType(curObj, buffType)
    #ͨ¹ýÀàÐÍ»ñȡĿ±êµÄbuff¹ÜÀíÆ÷Ϊ¿Õ£¬ÔòÌø³ö
    if buffTuple == ():
        return
    
    buffState = buffTuple[0]
    
    effectIndexList = []
    for i in xrange(0, buffState.GetEffectCount()):
        curEffect = buffState.GetEffect(i)
        curEffectID = curEffect.GetEffectID()
        if curEffectID == 0:
            continue
        
        # Ч¹ûÀ´Ô´¼¼ÄÜID
        if buffState.GetEffectFromSkillID(i) != skillID:
            continue
        if buffState.GetEffectOwnerID(i) != ownerID:
            continue
    
        if buffState.GetEffectOwnerType(i) != ownerType:
            continue
        
        effectIndexList.append(i)
    
    # µ¹Ðòɾ³ý
    effectIndexList.sort(reverse=True)
    for i in effectIndexList:
        buffState.DeleteEffectByIndex(i)
# ͨ¹ý¼¼ÄÜtypeIDɾ³ýbuff¶ÔÓ¦µÄЧ¹ûID
def ClearBuffEffectBySkillTypeID(curObj, skillTypeID, ownerID, ownerType):
    curSkill = GameWorld.GetGameData().GetSkillBySkillID(skillTypeID)
    buffType = SkillCommon.GetBuffType(curSkill)
    buffTuple = SkillCommon.GetBuffManagerByBuffType(curObj, buffType)
    #ͨ¹ýÀàÐÍ»ñȡĿ±êµÄbuff¹ÜÀíÆ÷Ϊ¿Õ£¬ÔòÌø³ö
    if buffTuple == ():
        return
    
    buffState = buffTuple[0]
    effectIndexList = []
    for i in xrange(0, buffState.GetEffectCount()):
        curEffect = buffState.GetEffect(i)
        curEffectID = curEffect.GetEffectID()
        if curEffectID == 0:
            continue
        
        if buffState.GetEffectOwnerID(i) != ownerID:
            continue
    
        if buffState.GetEffectOwnerType(i) != ownerType:
            continue
        
        buffSkillID = buffState.GetEffectFromSkillID(i)
        buffSkill = GameWorld.GetGameData().GetSkillBySkillID(buffSkillID)
        if buffSkill.GetSkillTypeID() != skillTypeID:
            continue
        effectIndexList.append(i)
    
    # µ¹Ðòɾ³ý
    effectIndexList.sort(reverse=True)
    for i in effectIndexList:
        buffState.DeleteEffectByIndex(i)
# ͨ¹ý¼¼ÄÜIDÁбíɾ³ýbuff¶ÔÓ¦µÄЧ¹ûID, ËÀÍöµ÷ÓÃ
def ClearBuffEffectBySkillIDList(curObj, buffState, skillIDList):
    
    effectIndexList = []
    for i in xrange(0, buffState.GetEffectCount()):
        curEffect = buffState.GetEffect(i)
        curEffectID = curEffect.GetEffectID()
        if curEffectID == 0:
            continue
        
        #=======================================================================
        # # [¼¼ÄÜID£¬ À´Ô´¶ÔÏóID£¬¶ÔÏóÀàÐÍ]
        # if [buffState.GetEffectFromSkillID(i), 
        #    buffState.GetEffectOwnerID(i), 
        #    buffState.GetEffectOwnerType(i)] not in skillIDList:
        #    continue
        #=======================================================================
        # ¸Ä³ÉÖ»Åжϼ¼ÄÜID
        if buffState.GetEffectFromSkillID(i) not in skillIDList:
            continue
        
        effectIndexList.append(i)
        
    # µ¹Ðòɾ³ý
    effectIndexList.sort(reverse=True)
    for i in effectIndexList:
        buffState.DeleteEffectByIndex(i)
        
       
##ˢйÜÀíÆ÷ÖеÄBuff
# @param buffRefreshList BuffË¢ÐÂÁбí[[BuffState, CanPileup]]
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks °´ÕÕµþ¼Ó¹æÔò, Ë¢ÐÂÖ¸¶¨¹ÜÀíÖеÄBuff
def __DoRefreshBuff(buffRefreshList):
    for buffState, canPileUp in buffRefreshList:
        __RefreshSkillBuffEffect(buffState, canPileUp)
    return
    
##¼ÆËãÐÐΪBUFF¶ÔÈËÎïÐÐΪ״̬µÄ¸Ä±ä
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¼ÆËãÐÐΪBUFF¶ÔÈËÎïÐÐΪ״̬µÄ¸Ä±ä
def CalcBuffer_ActionState(curObj):
    
    #---´ÓBUFFÐÐΪ¹ÜÀíÆ÷ÖÐÈ¡µÃ
    actionBuffManager = curObj.GetActionBuffManager()
    for i in range(actionBuffManager.GetBuffCount()):
        curBuff = actionBuffManager.GetBuff(i)
        
        if not curBuff:
            continue
        
        buffSkill = curBuff.GetSkill()
        
        if not buffSkill:
            continue
        
        #ÐÐΪBUFF¼¼ÄܵÄÀàÐÍIDÀ´Çø·Ö£¬ÔÝʱûÓ㬲ÎÊý䶨
        #GameWorld.GetExecFunc(GameBuffs, "BuffAct_%d.%s"%(buffSkill.GetSkillTypeID(), "OnCalcBuff"))
        
        #ÉèÖöÔÏóµÄÐÐΪ״̬
        OperControlManager.SetObjActState(curObj, buffSkill)
# ¼ÆËãÊôÐÔÀ༼ÄܵÄÊôÐÔ£¬Í¬buff²ã²»ËãÕ½Á¦
def CalcPassiveAttr_Effect(curPlayer, allAttrList):
    skillManager = curPlayer.GetSkillManager()
    for i in xrange(skillManager.GetSkillCount()):
        curPlayerSkill = skillManager.GetSkillByIndex(i)
        if curPlayerSkill == None:
            continue
        
        if not SkillCommon.isPassiveAttr(curPlayerSkill):
            continue
        
        if curPlayerSkill.GetFuncType() not in [ChConfig.Def_SkillFuncType_FbSkill,
                                            ChConfig.Def_SkillFuncType_FbSPSkill,
                                            ChConfig.Def_SkillFuncType_GiftSkill,
                                            ChConfig.Def_SkillFuncType_GWSkill,
                                            ChConfig.Def_SkillFuncType_ZhuXian]:
            # ¸ù¾Ý¼¼ÄÜÇé¿öµ÷Õû
            continue
        
        for i in xrange(curPlayerSkill.GetEffectCount()):
            curEffect = curPlayerSkill.GetEffect(i)
            curEffectID = curEffect.GetEffectID()
            if curEffectID == 0:
                continue
            
            CalcBuffEffAttr(curPlayer, curEffect, allAttrList)
    skills = PassiveBuffEffMng.FindUsePassiveSkills(curPlayer)
    for skillID in skills:
        curPlayerSkill = skillManager.FindSkillBySkillID(skillID)
        if curPlayerSkill == None:
            continue
        
        if not SkillCommon.isPassiveAttr(curPlayerSkill):
            continue
        
        for i in xrange(curPlayerSkill.GetEffectCount()):
            curEffect = curPlayerSkill.GetEffect(i)
            curEffectID = curEffect.GetEffectID()
            if curEffectID == 0:
                continue
            
            CalcBuffEffAttr(curPlayer, curEffect, allAttrList)
            
            
##¼ÆËãbuffÌí¼ÓµÄÊôÐÔÁбí, ×°±¸BUFF ²»Ëã´ËÁÐ
# @param curPlayer Íæ¼ÒʵÀý
# @return None
def CalcBuffers_Effect(curPlayer, allAttrList, calcEffectIDList=[]):
    
    for buffType in range(IPY_GameWorld.bfBuff, IPY_GameWorld.btBufMax):
        #ÕâЩÀàÐͲ»Ó°ÏìÍæ¼Ò¼ÆËãÊôÐÔ
        if buffType in [IPY_GameWorld.bfProcessBuff, #IPY_GameWorld.bfProcessDeBuff, 
                        IPY_GameWorld.bfMapBuff,
                        IPY_GameWorld.bfEquipBuff]:
            continue
        
        buffTuple = SkillCommon.GetBuffManagerByBuffType(curPlayer, buffType)
        #ͨ¹ýÀàÐÍ»ñȡĿ±êµÄbuff¹ÜÀíÆ÷Ϊ¿Õ£¬ÔòÌø³ö
        if buffTuple == ():
            continue
        
        buffManager = buffTuple[0]
        
        #Ò»´ÎÑ»·ÖмÆËã³öÏßÐԺͷÇÏßÐÔ½á¹û
        CalcCurBuffer_Effect(buffManager, curPlayer, allAttrList, calcEffectIDList)
##¼ÆËã»ù±¾ÊôÐÔ¶ÔÈËÎï״̬µÄ¸Ä±ä(·ÇÏßÐÔ)
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¼ÆËã»ù±¾ÊôÐÔ¶ÔÈËÎï״̬µÄ¸Ä±ä
#===============================================================================
# def CalcBuffer_BaseEffect_OutLine(curPlayer):
#    effectList = list()
#    for i in range(0, ChConfig.TYPE_Max_Attr):
#        effectList.append(0)
#        
#    #·ÇÏßÐÔ
#    for buffType in range(IPY_GameWorld.bfBuff, IPY_GameWorld.btBufMax):
#        buffTuple = SkillCommon.GetBuffManagerByBuffType(curPlayer, buffType)
#        #ͨ¹ýÀàÐÍ»ñȡĿ±êµÄbuff¹ÜÀíÆ÷Ϊ¿Õ£¬ÔòÌø³ö
#        if buffTuple == ():
#            continue
#        
#        buffManager = buffTuple[0]
#        CalcCurBuffer_BaseEffect(buffManager, curPlayer, ChConfig.TYPE_NoLinear, effectList)
#    
#    return effectList
# #    #×îÖÕ¼ÆËã½á¹û
#===============================================================================
#    CalcNoLineEffect.ChangePlayerAttrInNoLineEffectList(curPlayer, effectList)
#---------------------------------------------------------------------
##¼ÆËãÕ½¶·ÊôÐÔ¶ÔÈËÎï״̬µÄ¸Ä±ä(·ÇÏßÐÔ)
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¼ÆËãÕ½¶·ÊôÐÔ¶ÔÈËÎï״̬µÄ¸Ä±ä
#===============================================================================
# def CalcBuffer_BattleEffect_OutLine(curPlayer):
#    effectList = [0 for x in xrange(ChConfig.TYPE_Max_Attr)]
#        
#    #·ÇÏßÐÔ
#    for buffType in range(IPY_GameWorld.bfBuff, IPY_GameWorld.btBufMax):
#        buffTuple = SkillCommon.GetBuffManagerByBuffType(curPlayer, buffType)
#        #ͨ¹ýÀàÐÍ»ñȡĿ±êµÄbuff¹ÜÀíÆ÷Ϊ¿Õ£¬ÔòÌø³ö
#        if buffTuple == ():
#            continue
#        
#        #³ÖÐøÐÔBUFFºÍ¿ØÖÆBUFFÌø³ö
#        if buffType in [IPY_GameWorld.bfActionBuff, IPY_GameWorld.bfProcessBuff,
#                        IPY_GameWorld.bfProcessDeBuff]:
#            continue
#        
#        buffManager = buffTuple[0]
#        
#        #Ò»´ÎÑ»·ÖмÆËã³öÏßÐԺͷÇÏßÐÔ½á¹û
#        CalcCurBuffer_BattleEffect(buffManager, curPlayer, ChConfig.TYPE_Linear, effectList)
#        
#        CalcCurBuffer_BattleEffect(buffManager, curPlayer, ChConfig.TYPE_NoLinear, effectList)
#    
#    CalcLineEffect.ChangePlayerAttrInLineEffectList(curPlayer, effectList)
#    
#    return effectList
#===============================================================================
    #×îÖÕ¼ÆËã½á¹û
    #CalcNoLineEffect.ChangePlayerAttrInNoLineEffectList(curPlayer, effectList)
##¼ÆËãÕ½¶·ÊôÐÔ¶ÔÈËÎï״̬µÄ¸Ä±ä(ÏßÐÔ)
# @param curPlayer Íæ¼ÒʵÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¼ÆËãÕ½¶·ÊôÐÔ¶ÔÈËÎï״̬µÄ¸Ä±ä
#===============================================================================
# def CalcBuffer_BattleEffect_InLine(curPlayer):
#    effectList = [0 for x in xrange(ChConfig.TYPE_Max_Attr)]
#        
#    #ÏßÐÔ
#    for buffType in range(IPY_GameWorld.bfBuff, IPY_GameWorld.btBufMax):
#        buffTuple = SkillCommon.GetBuffManagerByBuffType(curPlayer, buffType)
#        #ͨ¹ýÀàÐÍ»ñȡĿ±êµÄbuff¹ÜÀíÆ÷Ϊ¿Õ£¬ÔòÌø³ö
#        if buffTuple == ():
#            continue
#        
#        buffManager = buffTuple[0]
#        CalcCurBuffer_BattleEffect(buffManager, curPlayer, ChConfig.TYPE_Linear, effectList)
# 
#    #×îÖÕ¼ÆËãЧ¹û
#    CalcLineEffect.ChangePlayerAttrInLineEffectList(curPlayer, effectList)
#===============================================================================
#---------------------------------------------------------------------
##¼ÆËãNPCÕ½¶·ÊôÐÔ
# @param curNPC NPCʵÀý
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¼ÆËãNPCÕ½¶·ÊôÐÔ
def CalcBuffer_NPCBattleEffect(curNPC):
    #@warning:Õ½¶·ÊôÐÔÏÈËã·ÇÏßÐÔÔÚËãÏßÐÔ
    buffRefreshList = NPCCommon.GetNPCBuffRefreshList(curNPC, True)
    
    #ÏßÐÔ»ù´¡ÊôÐÔ£¬·ÇÏßÐÔ»ù´¡ÊôÐÔ£¬ÏßÐÔÕ½¶·ÊôÐÔ£¬·ÇÏßÐÔÕ½¶·ÊôÐÔ
    allAttrList = [{} for i in range(4)]
    
    for buffState, canPileup in buffRefreshList:
        CalcCurBuffer_Effect(buffState, curNPC, allAttrList)
    
    #·ÇÏßÐÔ
    CalcNoLineEffect.ChangeNPCAttrInNoLineEffectList(curNPC, allAttrList[ChConfig.CalcAttr_BattleNoline])
    #ÏßÐÔ
    CalcLineEffect.ChangeNPCAttrInLineEffectList(curNPC, allAttrList[ChConfig.CalcAttr_Battle])
    return allAttrList
#---------------------------------------------------------------------
##¼ÆËãNPC»ù´¡ÊôÐÔ
# @param rolePet Íæ¼Ò³èÎï
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¼ÆËãNPC»ù´¡ÊôÐÔ
def CalcBuffer_NPCBaseEffect(curNPC):
    #@warning:»ù´¡ÊôÐÔÏÈËãÏßÐÔÔÚËã·ÇÏßÐÔ
    #===========================================================================
    # effectList = list()
    # buffRefreshList = NPCCommon.GetNPCBuffRefreshList(curNPC)
    # 
    # #---¼ÆËãÏßÐÔЧ¹û---
    # for i in range(0, ChConfig.TYPE_Max_Attr):
    #    effectList.append(0)
    #    
    # for buffState, canPileup in buffRefreshList:
    #    CalcCurBuffer_BaseEffect(buffState, curNPC, ChConfig.TYPE_Linear, effectList)
    # 
    # #×îÖÕ¼ÆËãЧ¹û
    # CalcLineEffect.ChangeNPCAttrInLineEffectList(curNPC, effectList)
    # 
    # #---¼ÆËã·ÇÏßÐÔЧ¹û---
    # for i in range(0, ChConfig.TYPE_Max_Attr):
    #    effectList[i] = 0
    # 
    # for buffState, canPileup in buffRefreshList:
    #    CalcCurBuffer_BaseEffect(buffState, curNPC, ChConfig.TYPE_NoLinear, effectList)
    # 
    # #×îÖÕ¼ÆËã½á¹û
    # CalcNoLineEffect.ChangeNPCAttrInNoLineEffectList(curNPC, effectList)
    #===========================================================================
    return
#---------------------------------------------------------------------
##¼¼ÄÜ´¥·¢¸½¼Ó¼¼ÄÜ
# @param attacker ¹¥»÷·½
# @param defender ·ÀÊØ·½( ÔÊÐíΪ¿Õ )
# @param curSkill ¼¼ÄÜʵÀý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¼¼ÄÜ´¥·¢¸½¼Ó¼¼ÄÜ
def DoLogic_UseEnhanceSkill(attacker, defender, curSkill, tick, destX=-1, destY=-1):
    #δʹÓü¼ÄÜ
    if not curSkill:
        return
    
#===============================================================================
#    È«²¿Ä¬ÈÏ´¦Àí, ²»¿ªÌØÊâ½Ó¿Ú
#    callFunc = GameWorld.GetExecFunc( GameSkills, "SkillAttack_%d.%s"%( curSkill.GetSkillTypeID(), "UseEnhanceSkill" ) )
#    
#    #µ¥¶À´¦Àí¸½¼Ó¼¼ÄÜ
#    if callFunc:
#        callFunc( attacker, defender, curSkill, tick )
#        return
#===============================================================================
    
    #===========================================================================
    # if defender != None and defender.GetGameObjType() == IPY_GameWorld.gotNPC:
    #    if not defender.GetIsBoss() and GameWorld.GetMap().GetMapFBType() == IPY_GameWorld.fbtNull:
    #        #GameWorld.DebugLog("Ò°Íâ³£¹æµØÍ¼Ð¡¹Ö²»´¥·¢¼¼ÄÜ!")
    #        return
    #===========================================================================
    
    #ĬÈÏ´¦Àí
    __SkillTrigSkill(attacker, defender, curSkill, destX, destY, curSkill.GetSkillEnhance1(), tick)
    __SkillTrigSkill(attacker, defender, curSkill, destX, destY, curSkill.GetSkillEnhance2(), tick)
    return
def SkillTrigSkill(attacker, defender, curSkill, skillEnhanceID, tick, destX=-1, destY=-1):
    if not curSkill:
        return
    
    __SkillTrigSkill(attacker, defender, curSkill, destX, destY, skillEnhanceID, tick)
    return
#---------------------------------------------------------------------
##´¥·¢¼¼Äܸ½¼Ó¼¼ÄÜ Ð¼ÓÌõ¼þ¸ù¾ÝѧϰµÄ±»¶¯¼¼ÄÜ´¥·¢
# @param attacker ¹¥»÷Õß
# @param defender ·ÀÊØÕß
# @param useSkill ¼¼ÄÜʵÀý
# @param skillEnhanceID ¸½¼Ó¼¼ÄÜID
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ´¥·¢¼¼Äܸ½¼Ó¼¼ÄÜ£¬Ð¼ÓÌõ¼þ¸ù¾ÝѧϰµÄ±»¶¯¼¼ÄÜ´¥·¢
def __SkillTrigSkill(attacker, defender, useSkill, destX, destY, skillEnhanceID, tick):
    #¸½¼Ó¼¼ÄÜIDΪ0,·µ»Ø
    if not skillEnhanceID:
        return
    skillLV = useSkill.GetSkillLV()
    # ´¥·¢¼¼Äܵȼ¶ÊÇ·ñÐèÒªÌØÊâÈ¡
    #===========================================================================
    # curEffect = SkillCommon.GetSkillEffectByEffectID(useSkill, ChConfig.Def_Skill_Effect_ReEnhance)
    # if curEffect != None:
    #    
    #    if curEffect.GetEffectValue(1) == skillEnhanceID:
    #        # »ñÈ¡¾ö¶¨´¥·¢¼¼Äܵȼ¶µÄÄ¿±ê¼¼ÄÜ
    #        tagSkillID = curEffect.GetEffectValue(0)
    #        tagSkill = attacker.GetSkillManager().FindSkillBySkillTypeID(tagSkillID)
    #        #δѧϰ
    #        if tagSkill == None :
    #            return
    #        
    #        skillLV = tagSkill.GetSkillLV()
    #===========================================================================
    #--- 1. ÏÈÈ¡µÃ´¥·¢¼¼ÄÜ---
    
    #Ïȼì²éÊý¾Ý¿âÓÐû¸ÃÀ༼ÄÜ£¬Èç¹û×î¸ßµÈ¼¶²»Ò»Ñù»áÕÒ²»µ½
    #exSkill = GameWorld.GetGameData().FindSkillByType(skillEnhanceID, skillLV)
    exSkill = GameWorld.GetGameData().GetSkillBySkillID(skillEnhanceID)
    #Òì³£
    if not exSkill:
        GameWorld.ErrLog("¶ÔÏó = %s, ÕÒ²»µ½¸½¼Ó¼¼ÄÜID = %s, skillLv = %s"%(attacker.GetID() , skillEnhanceID , useSkill.GetSkillLV()))
        return
    #---ÒÑѧµÄ±»¶¯¼¼ÄÜ´¥·¢¸½¼Ó¼¼ÄÜ£¬·ñÔò¾ÍÊÇÌîдµÄ¸½¼Ó¼¼ÄÜ
    #===========================================================================
    # if SkillCommon.isPassiveSkill(exSkill):
    #    #---Èç¹û´¥·¢µÄ¼¼ÄÜÊÇÒÑѧϰµÄ¼¼ÄÜ£¬ÄÇô´¥·¢¸Ãѧϰ¼¼ÄܵĴ¥·¢¼¼ÄÜ---
    #    passiveSkill = attacker.GetSkillManager().FindSkillBySkillTypeID(skillEnhanceID)
    #    
    #    #δѧϰ
    #    if passiveSkill == None :
    #        return
    #    
    #    #ÕÒµ½±»¶¯´¥·¢¼¼ÄÜ
    #    exSkillID = passiveSkill.GetSkillEnhance1()
    #    exSkill = GameWorld.GetGameData().FindSkillByType(exSkillID, passiveSkill.GetSkillLV())
    #    #Òì³£
    #    if not exSkill:
    #        GameWorld.ErrLog("¶ÔÏó = %s, ÕÒ²»µ½¸½¼Ó¼¼ÄÜID = %s, skillLv = %s"%(attacker.GetID() , skillEnhanceID , passiveSkill.GetSkillLV()))
    #        return
    #===========================================================================
    
    #--- 2. ¼ì²â¸½¼Ó¼¼ÄÜÊÇ·ñÓ¦¸Ã±»´¥·¢---
    
    #ÔÙ´ÎÑéÖ¤¸½¼Ó¼¼ÄÜÊÇ·ñ¶ÔÄ¿±ê¿ÉÓÃ,²¢·µ»ØÊܼ¼ÄܶÔÏó (Bool, defender)
    resultList = CheeckTrigSkillandTag(attacker, exSkill, defender, tick)
    
    #¼ì²é¼¼ÄÜÊÇ·ñÊͷųɹ¦
    if not resultList[0]:
        return
    
    #È¡µÃ·ÀÊØÕߣ¬ÒѾ¸Ä±äΪ¾ßÌåµÄÊ©·¨¶ÔÏó
    defender = resultList[1]
    #ÓжÔÏóÀ༼ÄÜ, ÐèÒªÅж¨¶ÔÏó״̬
    if defender != None and (GameObj.GetHP(defender) <= 0 or GameWorld.GetNPC_Is_Gate(defender)):
        return
    
    #Ö÷¼¼Äܱ»ÉÁ±Ü Ôò²»´¥·¢¸½¼Ó¼¼ÄÜ, ¶Ô×Ô¼º·Å¼¼ÄÜÎÞÊÓÉÁ±Ü
    if not GameWorld.IsSameObj(attacker, defender) \
    and BaseAttack.GetHurtType(defender) == ChConfig.Def_HurtType_Miss:
        return
    
    #--- 3. ¼ÆËã¸ÅÂÊ´¥·¢¼¼ÄÜ---
    
    #¼¸ÂÊ
    rate = GetSkillOfSeriesHitRate(attacker, defender, exSkill)
    
    if not GameWorld.CanHappen(rate, ChConfig.Def_MaxRateValue):
        #¼¸ÂÊδ´¥·¢
        return False
        
#    #ÌØÊâÈ«¾ÖÐÍÖ÷¶¯ÔöÒæbuff,ÐèÒªÌí¼ÓÌØÊâ¼ä¸ô
#    if attacker.GetGameObjType() == IPY_GameWorld.gotPlayer and useSkill.GetSkillTypeID() in ChConfig.Def_SkillID_Trig:
#        attacker.GetSkillManager().SetTrigBuffSkillTick(tick)
        
    #GameWorld.Log("µ±Ç°¼¼ÄÜ = %s,´¥·¢¸½¼Ó¼¼Äܳɹ¦ = %s,´¥·¢¼¸ÂÊ = %s"%(useSkill.GetSkillName(),exSkill.GetSkillName(),rate))
    #----------------------------´¦Àí¸½¼Ó¼¼ÄÜ
    return DoLogic_UseSkill(attacker, defender, exSkill, tick, destX, destY, True)
##¸½¼Ó¼¼ÄܵÄÔªËØÃüÖиÅÂÊ
# @param attacker ¹¥»÷Õß
# @return ¸ÅÂÊ
def GetSkillOfSeriesHitRate(attacker, defender, exSkill):
    baseRate = exSkill.GetHappenRate()
    return baseRate
##¼ì²é´¥·¢¼¼ÄܵÄʹÓÃÌõ¼þ
# @param attacker ¹¥»÷Õß
# @param exSkill ¼¼ÄÜʵÀý
# @param defender ¸½¼Ó¼¼ÄÜID
# @param tick ʱ¼ä´Á
# @return Ôª×飨ÊÇ·ñͨ¹ý£¬·ÀÊØ·½£©
# @remarks ¼ì²é´¥·¢¼¼ÄܵÄʹÓÃÌõ¼þ
def CheeckTrigSkillandTag(attacker, exSkill, defender, tick):
    #ÔÙ´ÎÑéÖ¤¸½¼Ó¼¼ÄÜÊÇ·ñ¶ÔÄ¿±ê¿ÉÓÃ
    if attacker.GetGameObjType() != IPY_GameWorld.gotPlayer:
        #¸Ã¼¼ÄÜÊǶÔ×Ô¼ºÊ¹ÓÃµÄ ·ÀÊØÕßÓ¦¸Ã¸ÄΪ¹¥»÷Õß
        if GetSkillAffectTag(exSkill) in [ChConfig.Def_UseSkillTag_Self,
                                          ChConfig.Def_UseSkillTag_SelfAndFriend]:
            return True, attacker
        return True, defender
    
    #¸Ã¼¼ÄÜÊǶÔ×Ô¼ºÊ¹ÓÃµÄ ·ÀÊØÕßÓ¦¸Ã¸ÄΪ¹¥»÷Õß
    if GetSkillAffectTag(exSkill) in [ChConfig.Def_UseSkillTag_Self,
                                      ChConfig.Def_UseSkillTag_SelfAndFriend]:
        return True, attacker
    #¸Ã¼¼ÄÜÊǶԵØÊ¹ÓÃ
    if GetSkillFireAim(exSkill) == ChConfig.Def_UseSkillAim_Ground:
        # Íæ¼Ò¶ÔµØÈº¹¥Óпͻ§¶ËÄ¿±êÓÅÏÈÒÔµÚһĿ±êΪÖÐÐÄ
        return True, defender
    
    #===========================================================================
    # -------GetSkillAffectTagÅж¨¼´¿É£¬²»½øÐÐÑϸñÅж¨-----
    # ·ÀÊØÕßΪ¿Õ£¬Ôò¼´Îª¹¥»÷Õß,(Ⱥ¹¥¸ø×Ô¼º¼ÓBUFF)
    # if defender == None:
    #    defender = attacker
    # 
    # #¼ì²éÍæ¼Ò¹¥»÷Ä¿±êµÄ½á¹û
    # result = CheckTag_DoPlayerUseSkillTag(attacker, exSkill, defender, tick)
    #===========================================================================
    return True, defender
##»ñµÃ¼¼Äܵ÷Óú¯Êý
# @param curSkill ¼¼ÄÜʵÀý
# @param pyNameEx ÌØÀýPYÃû
# @param funcName º¯ÊýÃû
# @return º¯ÊýÖ¸Õë
# @remarks »ñµÃ¼¼Äܵ÷Óú¯Êý
def GetSkillCallFuncByName(curSkill, pyNameEx, funcName):
    atkType = curSkill.GetAtkType()
    
    if atkType != 0:
        pyName = "SkillModule_%s"%atkType
    else:
        pyName = "%s_%d"%(pyNameEx, curSkill.GetSkillTypeID())
    
    fuctionName = "%s.%s"%(pyName, funcName)
    callFunc = GameWorld.GetExecFunc(GameSkills, fuctionName)
    #¹¥»÷¼¼ÄÜÈç¹ûʧ°ÜÔòÊä³öÈÕÖ¾
    if callFunc == None and pyNameEx == "SkillAttack":
        #¼¼Äܲ»¿ÉʹÓÃ
        GameWorld.ErrLog('¹¥»÷¼¼ÄÜÎļþ²»¿Éµ÷Óà %s fuctionName: %s'%(pyName, fuctionName))
    
#    if callFunc != None:
#        GameWorld.Log("ʹÓü¼ÄÜ %s"%fuctionName)
    #¼¼Äܲ»¿ÉʹÓÃ
    return callFunc
##¼¼Äܹ¥»÷¶ÔÏóËÀÍöºó´¥·¢¼¼ÄÜ
# @param attacker ¹¥»÷Õß
# @param defender ·ÀÊØÕß
# @param useSkill ʹÓü¼ÄÜ
# @param tick ʱ¼äʵÀý
# @return 
def DoLogic_SkillAttackDie(attacker, defender, useSkill, tick):
    return
#===============================================================================
#    if not useSkill:
#        return False
#    
#    if GameObj.GetHP(defender) > 0:
#        return False
#    
#    # ËÑË÷¼¼Äܹ¥»÷ËÀÍöЧ¹ûID
#    curEffect = SkillCommon.GetSkillEffectByEffectID(useSkill, ChConfig.Def_Skill_Effect_SkillAttackDie)
#    if not curEffect:
#        return False
#    
#    # ´¥·¢¼¼ÄÜID
#    touchSkillID = curEffect.GetEffectValue(0)
#    
#    touchSkill = GameWorld.GetGameData().GetSkillBySkillID(touchSkillID)
# 
#    if not touchSkill:
#        GameWorld.Log("###Òì³£´íÎó£¬ÎÞ·¨ÕÒµ½¼¼Äܹ¥»÷¶ÔÏóËÀÍö´¥·¢¼¼ÄÜ(%s)"%(touchSkillID))
#        return False
#      
#    return ObjAutoUseSkill(attacker, defender, touchSkill, tick)
#===============================================================================
#---------------------------------------------------------------------
##Êͷż¼ÄÜ
# @param attacker ¹¥»÷·½
# @param defender ·ÀÊØ·½
# @param curSkill ¼¼ÄÜʵÀý
# @param tick ʱ¼ä´Á
# @param tagRoundPosX ¶ÔµØÃæÇøÓò¹¥»÷×ø±êX
# @param tagRoundPosY ¶ÔµØÃæÇøÓò¹¥»÷×ø±êY
# @param isEnhanceSkill ÊÇ·ñÊǸ½¼ÓµÄ¼¼ÄÜ
# @return ·µ»ØÖµÕæ, Êͷųɹ¦
# @remarks ×Ô¶¨Ò庯Êý, Êͷż¼ÄÜ
def DoLogic_UseSkill(attacker, defender, curSkill, tick, tagRoundPosX = -1, tagRoundPosY = -1, isEnhanceSkill = False):
    #ʹÓü¼ÄÜÐÐΪ״̬, ·þÎñ¶ËÏÞÖÆ
    if not OperControlManager.IsObjCanDoAction(attacker, 
                                               ChConfig.Def_Obj_ActState_ServerSkill, 
                                               curSkill.GetSkillOfSeries()):
        return  
    
    # Ç¿ÖÆ¶¨ÒåÎÞ¶ÔÏóµÄÆðµã×ø±êÒ»¶¨Êǹ¥»÷Õß×ø±ê
    if curSkill and SkillShell.GetSkillFireAim(curSkill) == ChConfig.Def_UseSkillAim_None:
        tagRoundPosX = attacker.GetPosX()
        tagRoundPosY = attacker.GetPosY()
        
    
    #Õâ¸ö¼¼ÄÜÊÇBuff
    if SkillCommon.IsBuff(curSkill):
        if curSkill.GetSkillType() in [ChConfig.Def_SkillType_LstPlsBuffAtk, ChConfig.Def_SkillType_PassiveLstPlsBuffAtk]:
            defender = attacker
        return __DoLogic_AddBuff(attacker, defender, curSkill, isEnhanceSkill, tick, tagRoundPosX, tagRoundPosY)
    
    return __DoLogic_UseAttackSkill(attacker, defender, curSkill, tick, tagRoundPosX, tagRoundPosY, isEnhanceSkill)
# ²»ÊÜÏÞÖÆºÍÓ°ÏìµÄ¼¼ÄÜ
def Trigger_UseSkill(attacker, defender, curSkill, tick, tagRoundPosX = 0, tagRoundPosY = 0, isEnhanceSkill = False):
    
    #Õâ¸ö¼¼ÄÜÊÇBuff
    if SkillCommon.IsBuff(curSkill):
        if ChConfig.Def_SkillType_LstPlsBuffAtk == curSkill.GetSkillType():
            defender = attacker
        return __DoLogic_AddBuff(attacker, defender, curSkill, isEnhanceSkill, tick, tagRoundPosX, tagRoundPosY)
    
    return __DoLogic_UseAttackSkill(attacker, defender, curSkill, tick, tagRoundPosX, tagRoundPosY, isEnhanceSkill)
#---------------------------------------------------------------------
##ÊÍ·ÅBuff¼¼ÄÜ
# @param attacker ¹¥»÷·½
# @param defender ·ÀÊØ·½
# @param curSkill ¼¼ÄÜʵÀý
# @param isEnhanceSkill ÊÇ·ñÊǸ½¼ÓµÄ¼¼ÄÜ
# @param tick ʱ¼ä´Á
# @param tagRoundPosX ¶ÔµØÃæÇøÓò¹¥»÷×ø±êX
# @param tagRoundPosY ¶ÔµØÃæÇøÓò¹¥»÷×ø±êY
# @return ·µ»ØÖµÕæ, Êͷųɹ¦
# @remarks ×Ô¶¨Ò庯Êý, ÊÍ·ÅBuff¼¼ÄÜ
def __DoLogic_AddBuff(attacker, defender, curSkill, isEnhanceSkill, tick,  tagRoundPosX = 0, tagRoundPosY = 0, addForce=False):
    skillTypeID = curSkill.GetSkillTypeID()
    skillBuffType = SkillCommon.GetBuffType(curSkill)
    
    if defender and not SkillCommon.CheckCanAddBuff(defender, skillBuffType, skillTypeID, curSkill.GetSkillLV()):
        #bug20140314 ²»¿ÉÓÐϵͳÌáʾ attacker²»Ò»¶¨ÊÇÍæ¼Ò, ifÅж¨µÄ¶ÔÏóÓ¦¸ÃÊÇdefender
        #PlayerControl.NotifyCode(attacker, 'XW_ZZ_SkillInvalidation')
        return
    
    if not GameWorld.CanHappen(curSkill.GetHappenRate(), ChConfig.Def_MaxRateValue):
        #¼¸ÂÊδ´¥·¢
        return
    
    if defender and curSkill.GetSkillType() in ChConfig.Def_Debuff_List:
        # debuffÐèÒªÅжÏÊÇ·ñ¿É¹¥»÷£¬ÈçÎÞµÐ
        if not AttackCommon.CheckCanAttackTag(attacker, defender):
            return
    BaseAttack.ClearSkillHurtList()
    #---ÊÍ·ÅBuff¼¼ÄÜ---
    callFunc = GetSkillCallFuncByName(curSkill, "SkillBuff", "UseBuff")
    
    #Ö´ÐÐBuffÂß¼
    if callFunc != None:
        #ÀïÃæÐèÒª×öÒ»´ÎAddBuffOver
        result = callFunc(attacker, defender, curSkill, tick, tagRoundPosX, tagRoundPosY)
        
        if not result:
            return
        
    #ĬÈÏÖ±½ÓÌí¼Ó
    else:  
        #---Ìí¼ÓµÄBuffÖµ---, ½öÖ§³Ö·ÅÔÚЧ¹û1µÄbuff
        addBuffValueList = GetAddBuffValue(attacker, curSkill, defender)
        result = BuffSkill.DoAddBuff(defender, skillBuffType, curSkill, tick, addBuffValueList, attacker, addForce=addForce)
        
        # resultΪ0 ÊǵÖÏûµÄ²»ÐèÒª¶Ôbuff´¦Àí
        if result is not 0:
            #Ìí¼ÓBUFFºó£º´¦Àí¼¼ÄÜЧ¹û£¬´¥·¢¸½¼Ó¼¼ÄÜ£¬¼ÓBUFFºó²úÉúµÄЧ¹û£¬³Í·£ºÍ³ðºÞ
            AddBuffOver(attacker, defender, curSkill, tick, isEnhanceSkill)
    
#    #---Ö´ÐÐ×Ô¶¨ÒåBuffÌí¼Ó³É¹¦Âß¼´¦Àí, µ½ÕâÀïÓ¦¸ÃÒѾ´¦ÀíÍê ´¥·¢¼¼Äܺ͹¥»÷½á¹û---
#    #´Ë´¦ÔÝʱûÓÐÓõ½£¬¿ªÆôʱÐèÈÏÕæ¿¼ÂÇ Ä£°åµÄÇé¿ö
#    callFunc = GetSkillCallFuncByName(curSkill, "SkillBuff", "DoAddBuffOver")
#    
#    if callFunc:
#        callFunc(attacker, defender, curSkill, tick)
#        return True
    
    if isEnhanceSkill:
        BaseAttack.OnHurtTypeTriggerPassiveSkill(attacker, defender, curSkill, tick)
        return True
    
    #ÔÚÕâ±ßµ÷ÓñÜÃâȺ¹¥Ê±¶à´Î¿Û³ýÏûºÄ
    #Èç¹ûûÓвå¼þ DoAddBuffOver, ĬÈÏÖ´Ðй¥»÷³É¹¦¶¯×÷ //Èç¿Ûħ, ֪ͨ¼¼ÄÜÊÍ·Å
    BaseAttack.DoAttackSuccessEx(attacker, GameObj.GetHP(attacker), defender, curSkill, tick)
    return True
#waring: ´ËÖµÓ°ÏìÁËBUFFµÄÌæ»»¹æÔò£¬Öµ´óÌæ»»Ð¡µÄ
##Ìí¼ÓBUFFǰѹÈëBUFFµÄÖµ£¬Õâ±ßÖ»¼ÆËãºÍ¹¥»÷ÕßÏà¹Ø£¬½öÖ§³Ö·ÅÔÚЧ¹û1µÄbuff
# @param attacker ¹¥»÷·½
# @param curSkill ¼¼ÄÜ
# @return ѹÈëÖµ£¬Êµ¼ÊÊý¾Ý¿ÉÄÜ»á¸ù¾ÝÊÜÐ§Òæ·½±ä»¯
def GetAddBuffValue(attacker, curSkill, defender):
    #ÑéÖ¤¸Ã¼¼ÄÜЧ¹û1µÄID£¬ÌáÈ¡¹«Ê½
    curEffect = curSkill.GetEffect(0)
    
    moduleSuffix = GetBuffModuleSuffix(curEffect)
    
    changeBuffValueDict = {}
    
    #ÊÇ·ñÊdzÖÐøÐÔ¼¼ÄÜ
    if curSkill.GetSkillType() in ChConfig.Def_LstBuff_List:
        callFunc = GameWorld.GetExecFunc( GameBuffs, "BuffProcess_%s.%s"%(moduleSuffix, "CalcBuffValue") )
    else:        
        callFunc = GameWorld.GetExecFunc( GameBuffs, "Buff_%s.%s"%(moduleSuffix, "CalcBuffValue") )
    
    if not callFunc:
        return []
    
    return callFunc(attacker, defender, curSkill, changeBuffValueDict)
##Ìí¼ÓBUFFºó£º´¦Àí¼¼ÄÜЧ¹û£¬´¥·¢¸½¼Ó¼¼ÄÜ£¬¼ÓBUFFºó²úÉúµÄЧ¹û£¬³Í·£ºÍ³ðºÞ
# @param attacker ¹¥»÷·½
# @param defender ·ÀÊØ·½
# @param curSkill ¼¼ÄÜʵÀý
# @param tick ʱ¼ä´Á
# @param isEnhanceSkill ÊÇ·ñÊǸ½¼ÓµÄ¼¼ÄÜ
# @return ·µ»ØÖµÕæ, Êͷųɹ¦
# @remarks Ìí¼ÓBUFFºó£º´¦Àí¼¼ÄÜЧ¹û£¬´¥·¢¸½¼Ó¼¼ÄÜ£¬¼ÓBUFFºó²úÉúµÄЧ¹û£¬³Í·£ºÍ³ðºÞ
def AddBuffOver(attacker, defender, curSkill, tick, isEnhanceSkill):
    
    #---Ê×´ÎÌí¼ÓÕâ¸öbuffµÄ´¥·¢, BuffÊÇÿ´ÎÖØËãµÄ, ÈçijЩֵֻÄÜËãÒ»´Î, ¾ÍÔÚÕâ¸ö²å¼þÖÐÌí¼Ó---
    #@bug: һЩ¼¼ÄÜÖ»ÔÚµÚÒ»´ÎÌí¼ÓBuffµÄʱºò¼ÆËãBuffÖµ, ¶øÕý³£Buff¶¼ÊÇÇå¿ÕÖØËãµÄ, µ¼ÖÂBuffÖµ±»ÖØÖÃ
    for effectIndex in range(0, curSkill.GetEffectCount()):
        curEffect = curSkill.GetEffect(effectIndex)
        
        callFunc = GameWorld.GetExecFunc(GameBuffs, "Buff_%d.%s"%(curEffect.GetEffectID(), "OnAddBuff"))
        
        if callFunc == None:
            continue
        
        #@warning: defenderÓпÉÄÜΪNone( ȺÌå¹¥»÷ʱ )
        callFunc(attacker, defender, curEffect, tick)
    
    skillType = curSkill.GetSkillType()
    #---¸øÄ¿±êÉϳÖÐøÐÔBuff¼¤»îÄ¿±êTick---
    if defender != None and skillType in ChConfig.Def_LstBuff_List:
        defender.SetIsNeedProcess(True)
    
    #---Ö´ÐÐĬÈÏBuffÌí¼Ó³É¹¦Âß¼´¦Àí---
    
    if isEnhanceSkill:
        #¸½¼Ó¼¼Äܲ»Í¨Öª¹¥»÷½á¹û
        return
    
    #µ÷Óô¥·¢¸½¼Ó¼¼ÄÜ
    DoLogic_UseEnhanceSkill(attacker, defender, curSkill, tick)
    
    #´¥·¢¹¥»÷½áÊøÂß¼
    if skillType in ChConfig.Def_Debuff_List and \
            defender != None and not GameWorld.IsSameObj(attacker, defender):
        #Èç¹ûÊǸøNPC¼ÓDeBuff, ÐèÒªÌí¼Ó³ðºÞ
        if defender.GetGameObjType() == IPY_GameWorld.gotNPC:
            npcControl = NPCCommon.NPCControl(defender)
            npcControl.AddObjToAngryList(attacker, curSkill.GetSkillAngry() + 1)
        #µ÷Óù¥»÷³Í·£Âß¼
        BaseAttack.DoLogic_AttackResult(attacker, defender, None, tick)
    
    return
#---------------------------------------------------------------------
##ÊÍ·ÅÆÕͨ¼¼ÄÜ
# @param attacker ¹¥»÷·½
# @param defender ·ÀÊØ·½
# @param curSkill ¼¼ÄÜʵÀý
# @param tick ʱ¼ä´Á
# @param tagRoundPosX ÊÍ·ÅÇøÓòX
# @param tagRoundPosY ÊÍ·ÅÇøÓòY
# @return ·µ»ØÖµÕæ, Êͷųɹ¦
# @remarks ×Ô¶¨Ò庯Êý, ÊÍ·ÅÆÕͨ¼¼ÄÜ
def __DoLogic_UseAttackSkill(attacker, defender, curSkill, tick, tagRoundPosX = -1, 
                             tagRoundPosY = -1, isEnhanceSkill = False):
    callFunc = GetSkillCallFuncByName(curSkill, "SkillAttack", "UseSkill")
    #¼¼Äܲ»¿ÉʹÓÃ
    if callFunc == None:
        return False
    #ʹÓü¼ÄÜ
    return callFunc(attacker, defender, curSkill, tagRoundPosX, tagRoundPosY, isEnhanceSkill, tick)
#---------------------------------------------------------------------
#===============================================================================
# //06 0C ÉèÖÃ×Ô¶¯Êͷż¼ÄÜ#tagCSetAutoSkill
# tagCSetAutoSkill       *   GettagCSetAutoSkill();
# 
# class   IPY_CSetAutoSkill
# {
# public:
#    //0±íʾʲô¶¼×ö;1±íʾÆÕ¹¥;2±íʾÉèÖü¼ÄÜID
#    int      GetType();
#    //¼¼ÄÜID,Ö»ÔÚType=2ʱÓÐЧ
#    int      GetSkillID();
# };
#===============================================================================
##¿Í»§¶Ë·â°üÏìÓ¦ 06 0C ÉèÖÃ×Ô¶¯Êͷż¼ÄÜ#tagCSetAutoSkill
# @param index Íæ¼ÒË÷Òý
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¿Í»§¶Ë·â°üÏìÓ¦ 06 0C ÉèÖÃ×Ô¶¯Êͷż¼ÄÜ#tagCSetAutoSkill
def SetAutoSkill(index, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    
    sendPack = IPY_GameWorld.IPY_CSetAutoSkill()
    
    #ÕâÀï²»¼ÓÑéÖ¤,ֻѹÈë,´ýÊͷż¼ÄܵÄʱºòÔÚÑéÖ¤
    curPlayer.SetAutoAtk(sendPack.GetType(), sendPack.GetSkillID())
    return
#---------------------------------------------------------------------
# »ñµÃ¹ØÁª¼¼ÄÜ,0 È«²¿ 1ÊÇÖ÷¶¯Ðͼ¼ÄÜ£¨·¨±¦£¬ÆÕ¹¥£© 2 ΪÈË×å·¨±¦¼¼ÄÜ 3ΪÆÕ¹¥  ÆäËû¼¼ÄÜID
def GetConnectSkillID(curSkill):
    return curSkill.GetExAttr1()
##»ñµÃÉý¼¶¼¼ÄÜÏûºÄµÄÕæÆøÖµ
# @param curSkill Éý¼¶¼¼ÄÜ
# @return »ñµÃÉý¼¶¼¼ÄÜÏûºÄµÄÕæÆøÖµ
def GetLVUpCostZhenQi(curSkill):
    return 0#curSkill.GetExAttr1()
##»ñµÃ¼¼Äܵıط¢Éú״̬:Èç±ØÃüÖУ¬±Ø±©»÷£¬´Ë¼¼ÄܱØÐëΪÖ÷¶¯·½Ö´Ðм¼ÄÜ£¬BUFF״̬ÐÔÅäÖÃÎÞЧ
# @param curSkill ¼¼ÄÜʵÀý
# @return »ñµÃ¼¼Äܵıط¢Éú״̬
def GetHappenState(curSkill):
    if not curSkill:
        return 0
    
    return curSkill.GetExAttr2()
# Ö»ÓÐÔÚÖ¸¶¨µØÍ¼²ÅÄÜÉúЧµÄbuffЧ¹û£¬»òÕßÖ¸¶¨µØÍ¼¿É±»¶¯´¥·¢
def GetAttrMapID(curSkill):
    return curSkill.GetExAttr3()
##¼¼ÄÜÉý¼¶ÏûºÄÎïÆ·ID
# @param curSkill ¼¼ÄÜʵÀý
# @return ¼¼ÄÜÉý¼¶ÏûºÄÎïÆ·ID
def GetUpLVCostItemId(curSkill):
    return curSkill.GetExAttr4()
##¼¼ÄÜÉý¼¶ÏûºÄÎïÆ·ÊýÁ¿
# @param curSkill ¼¼ÄÜʵÀý
# @return ¼¼ÄÜÉý¼¶ÏûºÄÎïÆ·ÊýÁ¿
def GetUpLVCostItemNum(curSkill):
    return curSkill.GetExAttr5()
##»ñµÃµ±Ç°¼¼ÄÜÉý¼¶ÏûºÄµÄÕæÆøÖµ
# @param curSkill µ±Ç°¼¼Äܼ¼ÄÜ
# @return »ñµÃÉý¼¶¼¼ÄÜÏûºÄµÄÕæÆøÖµ
def GetSkillLVUpCostZhenQi(curSkill):
    curSkillTypeID = curSkill.GetSkillTypeID()
    maxSkillLV = curSkill.GetSkillMaxLV() # ×î¸ß¼¼Äܵȼ¶
    upSkillLv = curSkill.GetSkillLV() + 1
    
    skillLv = min(maxSkillLV, upSkillLv)
    
    upSkill = GameWorld.GetGameData().FindSkillByType(curSkillTypeID, skillLv)
    
    if not upSkill:
        GameWorld.Log('»ñÈ¡ÏûºÄÕæÆøÖµ´íÎó£¬skill is None')
        return 0
        
    skillLvUpNeedZhenQi = GetLVUpCostZhenQi(upSkill)
    
    return skillLvUpNeedZhenQi
## Ö´Ðб»¶¯´¥·¢¼¼ÄÜÊÍ·Å
#  @param taget
#  @return None
def UsePassiveTriggerSkill(attacker, curSkill, target, tick, isEnhanceSkill=False):
    result = False    # ¹¥»÷½á¹û
    if curSkill.GetTag() == 0 and not isEnhanceSkill:
        
        # µ±¼¼ÄÜÀàÐÍΪ±»¶¯¼¼Äܲ¢ÇÒtag×Ö¶ÎΪ0£¬Ôò´Ë¼¼ÄÜΪý½éÓÃÓÚ´¥·¢¼¼ÄÜ SkillEnhance1 SkillEnhance2
        skill1 = GameWorld.GetGameData().GetSkillBySkillID(curSkill.GetSkillEnhance1())
        if skill1 and GameWorld.CanHappen(skill1.GetHappenRate(), ChConfig.Def_MaxRateValue):
            result = True if UsePassiveTriggerSkill(attacker, skill1, target, tick, True) else result
            
        skill2 = GameWorld.GetGameData().GetSkillBySkillID(curSkill.GetSkillEnhance2())
        if skill2 and GameWorld.CanHappen(skill2.GetHappenRate(), ChConfig.Def_MaxRateValue):
            result = True if UsePassiveTriggerSkill(attacker, skill2, target, tick, True) else result
        
        SkillCommon.SetSkillRemainTime(curSkill, PlayerControl.GetReduceSkillCDPer(attacker), tick, attacker)
        return result
    
    skillAim = GetSkillFireAim(curSkill)
    affectTag = GetSkillAffectTag(curSkill)
    GameWorld.DebugLog("Êͷű»¶¯´¥·¢¼¼ÄÜ : %s- %s"%(skillAim, curSkill.GetSkillID()))
    if skillAim == ChConfig.Def_UseSkillAim_None:
        if curSkill.GetSkillType() in ChConfig.Def_CanAttackSkill_List and affectTag != ChConfig.Def_UseSkillTag_Self:
            if target and target.GetGameObjType() == IPY_GameWorld.gotNPC and target.GetGameNPCObjType() == IPY_GameWorld.gnotSummon:
                owner = NPCCommon.GetNpcObjOwnerDetail(target)
                if owner and owner.GetID() == attacker.GetID():
                    # Óк¦¼¼ÄÜÌØÊâ´¦Àí£¬²»ÄܶÔ×Ô¼ºµÄÕÙ»½ÎïÊÍ·Å
                    target = None
                
            result = DoLogic_UseSkill(attacker, target, curSkill, tick, attacker.GetPosX(), attacker.GetPosY(), isEnhanceSkill=isEnhanceSkill)
        else:
            result = DoLogic_UseSkill(attacker, attacker, curSkill, tick, isEnhanceSkill=isEnhanceSkill)
    #¶ÔµØÊÍ·ÅÀ༼ÄÜ
    elif skillAim == ChConfig.Def_UseSkillAim_Ground:
        if target:
            posX, posY = target.GetPosX(), target.GetPosY()
        else:
            posX, posY = attacker.GetPosX(), attacker.GetPosY()
        result = DoLogic_UseSkill(attacker, target, curSkill, tick, posX, posY, isEnhanceSkill=isEnhanceSkill)
    
    else:
        if affectTag == ChConfig.Def_UseSkillTag_PetMaster:
            if not PetControl.IsPet(attacker):
                return False
            
            petOwner = PetControl.GetPetOwner(attacker)
            if petOwner == None:
                return False
            
            target = petOwner
            if GameObj.GetHP(target) <= 0:
                return False
        
        if affectTag not in [ChConfig.Def_UseSkillTag_None, ChConfig.Def_UseSkillTag_Self]:
            if not target:
                # ÅäÖÃÁ˿ɹ¥»÷Ä¿±ê£¬µ«Ã»Ä¿±ê¾Í²»Èô¥·¢
                GameWorld.DebugLog("ÅäÖÃÁ˿ɹ¥»÷Ä¿±ê£¬µ«Ã»Ä¿±ê¾Í²»Èô¥·¢")
                result = False
                #result = DoLogic_UseSkill(curPlayer, target, curSkill, tick, curPlayer.GetPosX(), curPlayer.GetPosY(), isEnhanceSkill)
            else:
                #¼ì²éÄ¿±ê
                if attacker.GetGameObjType() == IPY_GameWorld.gotPlayer and \
                not CheckTag_DoPlayerUseSkillTag(attacker, curSkill, target, tick):
                    #GameWorld.Log("UsePassiveTriggerSkill = %s, ¼ì²éÄ¿±êÊÇ·ñ¿ÉÒÔ¹¥»÷ʧ°Ü = %s"%( curSkill.GetTag(), target.GetName() ) )
                    result = False
                else:
                    result = DoLogic_UseSkill(attacker, target, curSkill, tick, isEnhanceSkill=isEnhanceSkill)
        else:
            # Ö¸¶¨Ä¿±êΪ×Ô¼º
            result = DoLogic_UseSkill(attacker, attacker, curSkill, tick, isEnhanceSkill=isEnhanceSkill)
    
    GameWorld.DebugLog("´¥·¢½á¹û-----------%s"%result)
    return result
## »ñȡijÀàÐͼ¼ÄÜ´ïµ½XµÈ¼¶µÄ¸öÊý
#  @param curPlayer
#  @return
def GetSkillCntByFunc(curPlayer, funcType, skilllv=0):
    allSkillCnt = 0
    skillManager = curPlayer.GetSkillManager()
    for i in xrange(skillManager.GetSkillCount()):
        curPlayerSkill = skillManager.GetSkillByIndex(i)
        if curPlayerSkill == None:
            continue
        if curPlayerSkill.GetFuncType() != funcType:
            continue
        if curPlayerSkill.GetSkillLV() >= skilllv:
            allSkillCnt += 1
        
    return allSkillCnt
## »ñÈ¡¼¼ÄÜ×ܵȼ¶
#  @param curPlayer
#  @return allSkillLV:×ܼ¼Äܵȼ¶
def GetAllSkillLV(curPlayer, funcType):
    allSkillLV = 0
    skillManager = curPlayer.GetSkillManager()
    for i in xrange(skillManager.GetSkillCount()):
        curPlayerSkill = skillManager.GetSkillByIndex(i)
        if curPlayerSkill == None:
            continue
        if curPlayerSkill.GetFuncType() != funcType:
            continue
        skillLV = curPlayerSkill.GetSkillLV()
        allSkillLV += skillLV
    return allSkillLV