ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/SkillShell.py
@@ -27,12 +27,10 @@
import FBLogic
import ItemCommon
import OperControlManager
import GameLogic_ManorWar
import PetControl
import ReadChConfig
import DataRecordPack
import ChItem
import PlayerActivity
#import ChItem
import ShareDefine
import PlayerGreatMaster
import PlayerHorse
@@ -43,9 +41,12 @@
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")
@@ -53,6 +54,7 @@
# 记录客户端伤害 {(objID, objType):[HurtHP, AttackType]}
g_ClientHurtDict = collections.OrderedDict()
g_UseSkillPlayerID = 0  # 全服攻击为单线程 记录的是当前使用技能的玩家 用于判断g_ClientHurtDict的归属
#---------------------------------------------------------------------
##C++调用函数, 重新读取所有技能
@@ -90,6 +92,10 @@
def GetSkillFireAim(curSkill):
    return curSkill.GetTag()%10
# 当前释放主动技能的玩家
def GetUseSkillPlayerID():
    global g_UseSkillPlayerID
    return g_UseSkillPlayerID
# 客户端伤血列表,修改了遍历对象和计算血量
def GetClientHurtDict():
@@ -98,10 +104,9 @@
def ClearClientHurtDict(curPlayer):
    global g_ClientHurtDict
    global g_UseSkillPlayerID
    g_ClientHurtDict = collections.OrderedDict()
    # 缓存单次技能攻击的最大伤害, 减少计算量
    curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientMaxHurtValue, 0)
    g_UseSkillPlayerID = 0
    
    
def GetClientHurtByObj(objID, objType):
@@ -123,6 +128,7 @@
# 技能开始初始化客户端伤血列表
def InitClientHurtDict(curPlayer, curSkill, hurtList):
    global g_ClientHurtDict
    global g_UseSkillPlayerID
    ClearClientHurtDict(curPlayer)
    
    #技能攻击最大数量
@@ -158,7 +164,8 @@
            return False
        
        g_ClientHurtDict[(hurobj.ObjID, hurobj.ObjType)] = [hurobj.HurtHP, hurobj.AttackType]
    g_UseSkillPlayerID = curPlayer.GetID()
    return True
#---------------------------------------------------------------------    
# 非客户端玩家释放的技能
@@ -170,11 +177,16 @@
        # 玩家普通也是技能,正常是不会走到这边
        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
@@ -247,7 +259,8 @@
    #还在冷却时间内无法释放
    if SkillCommon.RefreshSkillRemainTime(playerSkill, tick) != 0:
        PlayerControl.NotifyCode(curPlayer, "UseSkillCDLimit")
        AttackFailNotify(curPlayer, curSkill, ChConfig.SkillFail_CD)
        #AttackFailNotify(curPlayer, curSkill, ChConfig.SkillFail_CD)
        playerSkill.Sync_Skill()
        return False
    #5:检查玩家的魔法值是否够用这个技能
@@ -347,6 +360,13 @@
# @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
    
@@ -363,6 +383,29 @@
        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技能位移坐标,预警和非预警都可以用
@@ -511,6 +554,9 @@
# @return 返回值真, 检查通过
def NPCCanUseSkillTag(curNPC, curTag, curSkill, tick):
    skillTag = GetSkillAffectTag(curSkill)
    if skillTag == ChConfig.Def_UseSkillTag_AppointNPC:
        return True
    #---对象判定---
    if IsToPetOwnerSkill(curNPC, skillTag):
        return True
@@ -684,9 +730,27 @@
            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())
    #范围校验
    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
@@ -854,6 +918,7 @@
    Def_Attack_DelayTick = 5000
    # tick 误差过大则过滤
    if abs(clientTick - tick) > Def_Attack_DelayTick:
        curPlayer.Sync_ClientTick()
        GameWorld.DebugLog("tick 误差过大则过滤 > 5000")
        return False
    
@@ -931,10 +996,12 @@
        #GameWorld.ErrLog('UseSkill findSkillErr = %s'%(pack_SkillID), curPlayerID)
        return
    if not CheckClientAttackTick(curPlayer, clientTick, tick):
        AttackFailNotify(curPlayer, curSkill, ChConfig.SkillFail_AtkInterval)
        curPlayer.Sync_ClientTick()
        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:
@@ -944,7 +1011,7 @@
    #使用技能行为状态, 客户端限制    
    if not OperControlManager.IsObjCanDoAction(curPlayer, 
                                               ChConfig.Def_Obj_ActState_ClientSkill, 
                                               curSkill.GetSkillOfSeries()):
                                               curSkill.GetSkillOfSeries(), curSkill):
        AttackFailNotify(curPlayer, curSkill)
        return    
@@ -1030,6 +1097,7 @@
def AttackFailNotify(curPlayer, curSkill, reason=0):
    sendPack = ChPyNetSendPack.tagMCAttackFail()
    sendPack.SkillID = curSkill.GetSkillID()
    sendPack.Reason = reason
    NetPackCommon.SendFakePack(curPlayer, sendPack)
#--------------------------玩家使用技能
#===============================================================================
@@ -1302,6 +1370,10 @@
def __CheckPlayerUseSkill_ClientPack(curPlayer, posX, posY, curSkill):
    if curPlayer.GetHP() <= 0:
        return
    if curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomScene):
        #GameWorld.DebugLog("自定义场景中,不检查!")
        return True
    
    #===========================================================================
    # if curPlayer.IsMoving():
@@ -1807,9 +1879,8 @@
    
    #获得技能等级
    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
@@ -1842,6 +1913,7 @@
    if upSkill.GetFuncType() == ChConfig.Def_SkillFuncType_GiftSkill:
        if not PlayerGreatMaster.GetGreatMasterFreeSkillPoint(curPlayer):
            return False
    #经验检测
    skillLvUpNeedExp = upSkill.GetLVUpCostExp()
    
@@ -1969,25 +2041,287 @@
        return False
    
    #玩家属性点要求
    stateSkillLV = curSkill.GetStateSkillLV() #需要基础属性ID*10000+需要属性点
    needBaseAttrID, needBaseAttrValue = stateSkillLV /10000, stateSkillLV%10000
    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_STR:curPlayer.GetSTR(),
                            ShareDefine.Def_Effect_PHY:curPlayer.GetPHY(),
                            ShareDefine.Def_Effect_CON:curPlayer.GetCON(),
                            ShareDefine.Def_Effect_PNE:curPlayer.GetPNE(),
                            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))
            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))
            #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
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_SkillElementID % 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 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()
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_SkillElementID % 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 对象
@@ -2207,14 +2541,6 @@
            #GameWorld.Log("删除场景Buff %d"%skillID)
            processResult = True
            continue
        else:
            # 非领地战期间, 该区域有领地旗buff, 删除区域buff
            if skillID == ChConfig.Def_SkillID_ManorFlagArea and not GameLogic_ManorWar.CanManorWarAtk():
                mapBuffManager.DeleteBuffByIndex(index)
                ClearBuffEffectBySkillID(curPlayer, skillID, ownerID, ownerType)
                processResult = True
                #GameWorld.DebugLog("非领地战期间, 该区域有领地旗buff, 删除区域buff")
                continue
        
        index += 1
        
@@ -2240,10 +2566,7 @@
                continue
            if findBuff.GetSkill().GetSkillLV() > curSkill.GetSkillLV():
                continue
        if skillTypeID == ChConfig.Def_SkillID_ManorFlagArea and not GameLogic_ManorWar.CanManorWarAtk():
            #GameWorld.DebugLog("    i=%s,effectID=%s,skillID=%s, 该位置有buff, 非领地战期间, 不添加" % (i, effectID, skillTypeID))
            continue
        #添加场景buff
        isOK = BuffSkill.AddBuffNoRefreshState(curPlayer, IPY_GameWorld.bfMapBuff, curSkill, tick)
        processResult = processResult or isOK
@@ -2348,6 +2671,9 @@
        #骑马触发技能
        houseSkill = ChConfig.Def_Skill_TypeID_Speed
        curSkillType = curSkill.GetSkillTypeID()
        if not SkillCommon.IsBuff(curSkill):
            continue
        
        if curSkillType in houseSkill:
            #不使用,不添加buff
@@ -2457,6 +2783,13 @@
        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
@@ -2587,7 +2920,7 @@
        buffState.DeleteEffectByIndex(i)
# 通过技能ID列表删除buff对应的效果ID
# 通过技能ID列表删除buff对应的效果ID, 死亡调用
def ClearBuffEffectBySkillIDList(curObj, buffState, skillIDList):
    
    effectIndexList = []
@@ -2597,11 +2930,17 @@
        if curEffectID == 0:
            continue
        
        # [技能ID, 来源对象ID,对象类型]
        if [buffState.GetEffectFromSkillID(i),
            buffState.GetEffectOwnerID(i),
            buffState.GetEffectOwnerType(i)] not in skillIDList:
        #=======================================================================
        # # [技能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)
        
    # 倒序删除
@@ -2648,6 +2987,7 @@
        OperControlManager.SetObjActState(curObj, buffSkill)
# 计算属性类技能的属性,同buff层不算战力
def CalcPassiveAttr_Effect(curPlayer, allAttrList):
    skillManager = curPlayer.GetSkillManager()
@@ -2662,7 +3002,8 @@
        if curPlayerSkill.GetFuncType() not in [ChConfig.Def_SkillFuncType_FbSkill,
                                            ChConfig.Def_SkillFuncType_FbSPSkill,
                                            ChConfig.Def_SkillFuncType_GiftSkill,
                                            ChConfig.Def_SkillFuncType_GWSkill]:
                                            ChConfig.Def_SkillFuncType_GWSkill,
                                            ChConfig.Def_SkillFuncType_ZhuXian]:
            # 根据技能情况调整
            continue
        
@@ -2698,15 +3039,15 @@
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
        #这些类型不影响玩家计算属性
        if buffType in [IPY_GameWorld.bfProcessBuff,
                        IPY_GameWorld.bfProcessDeBuff, IPY_GameWorld.bfMapBuff,
                        IPY_GameWorld.bfEquipBuff]:
            continue
        
        buffManager = buffTuple[0]
@@ -2929,7 +3270,8 @@
    #--- 1. 先取得触发技能---
    
    #先检查数据库有没该类技能,如果最高等级不一样会找不到
    exSkill = GameWorld.GetGameData().FindSkillByType(skillEnhanceID, skillLV)
    #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()))
@@ -3125,7 +3467,7 @@
    
    #这个技能是Buff
    if SkillCommon.IsBuff(curSkill):
        if ChConfig.Def_SkillType_LstPlsBuffAtk == curSkill.GetSkillType():
        if curSkill.GetSkillType() in [ChConfig.Def_SkillType_LstPlsBuffAtk, ChConfig.Def_SkillType_PassiveLstPlsBuffAtk]:
            defender = attacker
        return __DoLogic_AddBuff(attacker, defender, curSkill, isEnhanceSkill, tick, tagRoundPosX, tagRoundPosY)
    
@@ -3135,7 +3477,6 @@
# 不受限制和影响的技能
def Trigger_UseSkill(attacker, defender, curSkill, tick, tagRoundPosX = 0, tagRoundPosY = 0, isEnhanceSkill = False):
    
    #这个技能是Buff
    if SkillCommon.IsBuff(curSkill):
@@ -3208,6 +3549,7 @@
#        return True
    
    if isEnhanceSkill:
        BaseAttack.OnHurtTypeTriggerPassiveSkill(attacker, defender, curSkill, tick)
        return True
    
    #在这边调用避免群攻时多次扣除消耗
@@ -3215,16 +3557,6 @@
    BaseAttack.DoAttackSuccessEx(attacker, GameObj.GetHP(attacker), defender, curSkill, tick)
    return True
#===============================================================================
# Def_Effect_GoddessAddHP = 1300    # 加血 (压总值血量百分比)
# Def_Effect_AddHPValue_All = 1027    # 持续加血(压总值攻击)
# Def_Effect_LostHPValue_All = 1033    # 持续减血(压总值攻击)
# Def_Effect_LostAndAddHPValue_All = 1050    # 持续吸血(压总值攻击)
# Def_Effect_LostHPValue_Single = 1201    # 持续单次减血计算 攻击
# Def_Effect_AddHPValue_Single = 1202    # 持续单次加血计算 攻击
# Def_Effect_LostHP_MaxHP = 1089    # 持续减血(压总值, 血量百分比)
#===============================================================================
#waring: 此值影响了BUFF的替换规则,值大替换小的
##添加BUFF前压入BUFF的值,这边只计算和攻击者相关,仅支持放在效果1的buff
@@ -3234,7 +3566,6 @@
def GetAddBuffValue(attacker, curSkill, defender):
    #验证该技能效果1的ID,提取公式
    curEffect = curSkill.GetEffect(0)
    effectID = curEffect.GetEffectID()
    
    moduleSuffix = GetBuffModuleSuffix(curEffect)
    
@@ -3351,7 +3682,7 @@
    return
#---------------------------------------------------------------------
# 获得关联技能
# 获得关联技能,0 全部 1是主动型技能(法宝,普攻) 2 为人族法宝技能 3为普攻  其他技能ID
def GetConnectSkillID(curSkill):
    return curSkill.GetExAttr1()
@@ -3371,7 +3702,7 @@
    
    return curSkill.GetExAttr2()
# 只有在指定地图才能生效的buff效果
# 只有在指定地图才能生效的buff效果,或者指定地图可被动触发
def GetAttrMapID(curSkill):
    return curSkill.GetExAttr3()
@@ -3387,6 +3718,7 @@
# @return 技能升级消耗物品数量
def GetUpLVCostItemNum(curSkill):
    return curSkill.GetExAttr5()
##获得当前技能升级消耗的真气值
@@ -3419,11 +3751,11 @@
        
        # 当技能类型为被动技能并且tag字段为0,则此技能为媒介用于触发技能 SkillEnhance1 SkillEnhance2
        skill1 = GameWorld.GetGameData().GetSkillBySkillID(curSkill.GetSkillEnhance1())
        if skill1:
        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:
        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)
@@ -3434,7 +3766,7 @@
    GameWorld.DebugLog("释放被动触发技能 : %s- %s"%(skillAim, curSkill.GetSkillID()))
    if skillAim == ChConfig.Def_UseSkillAim_None:
        if curSkill.GetSkillType() in ChConfig.Def_CanAttackSkill_List:
        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():
@@ -3489,25 +3821,35 @@
## 获取技能总等级
## 获取某类型技能达到X等级的个数
#  @param curPlayer
#  @return allSkillLV:总技能等级
def GetAllSkillLV(curPlayer):
    successSkillIDList = ReadChConfig.GetEvalChConfig("SuccessSkillIDList")
    allSkillLV = 0
#  @return
def GetSkillCntByFunc(curPlayer, funcType, skilllv=0):
    allSkillCnt = 0
    skillManager = curPlayer.GetSkillManager()
    for i in range(0 , skillManager.GetSkillCount()):
    for i in xrange(skillManager.GetSkillCount()):
        curPlayerSkill = skillManager.GetSkillByIndex(i)
        if curPlayerSkill == None:
            continue
        skillTypeID = curPlayerSkill.GetSkillTypeID()
        if skillTypeID not in successSkillIDList:
        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