129 【战斗】战斗系统-服务端(卑弥呼所有技能;技能表增加字段Buff保留-BuffRetain,支持死亡保留、复活保留;增加触发方式42-大回合开始时(死亡后有效);增加属性ID 73复活生命加成、74复活怒气加成;优化效果6014-支持失败次数额外概率;优化死亡、复活时的buff处理;)
10个文件已修改
231 ■■■■ 已修改文件
PySysDB/PySysDBPY.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BattleObj.py 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/TurnFight.py 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_6014.py 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuff.py 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnPassive.py 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py 56 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PySysDB/PySysDBPY.h
@@ -120,6 +120,7 @@
    BYTE        LayerMax;    //最大层数
    DWORD        BuffRepeat;    //Buff叠加规则
    BYTE        DispersedLimit;    //驱散限制
    BYTE        BuffRetain;    //Buff保留规则
    DWORD        FightPower;    //技能战斗力
};
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BattleObj.py
@@ -365,6 +365,7 @@
    def GetLayerMax(self): return self._ipyData.GetLayerMax()
    def GetBuffRepeat(self): return self._ipyData.GetBuffRepeat() # Buff叠加规则
    def GetDispersedLimit(self): return self._ipyData.GetDispersedLimit() or self._ipyData.GetSkillType() == ChConfig.Def_SkillType_Halo # 驱散限制
    def GetBuffRetain(self): return self._ipyData.GetBuffRetain()
    def GetFightPower(self): return self._ipyData.GetFightPower()
    
class PyBuff():
@@ -392,6 +393,8 @@
    def GetSkillData(self): return self._skillData
    def GetSkillID(self): return self._skillData.GetSkillID()
    def GetCurBuffState(self): return self._skillData.GetCurBuffState()
    def GetDispersedLimit(self): return self._skillData.GetDispersedLimit()
    def GetBuffRetain(self): return self._skillData.GetBuffRetain()
    def GetAddTiming(self): return self._addTiming
    def SetAddTiming(self, addTiming):
        self._addTiming = addTiming
@@ -661,6 +664,7 @@
    def GetLayerMax(self): return self._skillData.GetLayerMax()
    def GetBuffRepeat(self): return self._skillData.GetBuffRepeat() # Buff叠加规则
    def GetDispersedLimit(self): return self._skillData.GetDispersedLimit() # 驱散限制
    def GetBuffRetain(self): return self._ipyData.GetBuffRetain()
    def GetFightPower(self): return self._skillData.GetFightPower()
    
    ## ---------------------------------- 非技能表内容 ----------------------------------
@@ -844,6 +848,7 @@
        self._kvDict = {} # 自定义kv字典
        self._bigTurnAtkbackCnt = 0 # 大回合累计反击次数
        self._incrementValue = 0 # 自增值,每场战斗重置,用于确保唯一的场景,如 Skill tag 标签
        self._skillHappenFailCntDict = {} # 技能累计概率触发次数,使用成功后重置 {skillID:failCnt, ...}
        self._skillUseCntDict = {} # 技能累计使用次数 {skillID:useCnt, ...}
        self._skillTurnUseCntDict = {} # 技能单回合累计使用次数 {skillID:useCnt, ...}
        self._skillMgr = ObjPool.GetPoolMgr().acquire(SkillManager, self)
@@ -909,6 +914,7 @@
        return
    
    def ResetBattleEffect(self):
        ## 重置战斗属性,一般刷属性前调用
        self._batAttrDict = {}
        self._batAttrDict.update(self._initAttrDict)
        self.__onUpdBatAttr()
@@ -1077,9 +1083,19 @@
        self._skillTempAttrDict[attrID] = self._skillTempAttrDict.get(attrID, 0) + value
    def ClearSkillTempAttr(self): self._skillTempAttrDict = {}
    
    def GetSkillHappenFailCnt(self, skillID): return self._skillHappenFailCntDict.get(skillID, 0) # 技能概率触发失败累计次数
    def IsSkillCanHappen(self, skillID, happenRate):
        if happenRate and not GameWorld.CanHappen(happenRate, ChConfig.Def_MaxRateValue):
            self._skillHappenFailCntDict[skillID] = self._skillHappenFailCntDict.get(skillID, 0) + 1
            return False
        self._skillHappenFailCntDict.pop(skillID, 0)
        return True
    def GetSkillUseCnt(self, skillID): return self._skillUseCntDict.get(skillID, 0) # 单场战斗累计使用次数
    def GetSkillTurnUseCnt(self, skillID): return self._skillTurnUseCntDict.get(skillID, 0) # 单回合累计使用次数
    def ResetSkillUseCnt(self):
        ## 每场战斗开始时重置
        self._skillHappenFailCntDict = {}
        self._skillUseCntDict = {}
        self._skillTurnUseCntDict = {}
        self._incrementValue = 0
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
@@ -1569,8 +1569,6 @@
            batObj = batObjMgr.getBatObj(objID)
            if not batObj:
                continue
            if not batObj.IsAlive():
                continue
            
            turnFight.ResetOneActionUseSkillCnt()
            batObj.SetTiming(ChConfig.TurnTiming_Before) # 重置时机到回合前
@@ -1578,8 +1576,12 @@
                RefreshObjSkillByBigTurn(batObj)
                RefreshObjByBigTurn(turnFight, batObj)
            batObj.ResetBigTurn() # 每大回合重置
            TurnPassive.OnTriggerPassiveEffect(turnFight, batObj, ChConfig.TriggerWay_BigTurnStart)
            
            if not batObj.IsAlive():
                TurnPassive.OnTriggerPassiveEffect(turnFight, batObj, ChConfig.TriggerWay_BigTurnStartByDead)
            else:
                TurnPassive.OnTriggerPassiveEffect(turnFight, batObj, ChConfig.TriggerWay_BigTurnStart)
    return
def TurnFightPerTurnBigEnd(turnFight, turnNum):
@@ -1861,6 +1863,7 @@
    skillID = useSkill.GetSkillID() if useSkill else 0
    GameWorld.DebugLog("        %s 回合战斗主体被击杀: curID=%s,killerObjID=%s,skillID=%s" % (GetObjName(gameObj), objID, killerObjID, skillID))
    gameObj.SetDead()
    TurnBuff.DoBuffByDead(turnFight, gameObj)
    
    clientPack = ObjPool.GetPoolMgr().acquire(ChPyNetSendPack.tagMCTurnFightObjDead)
    clientPack.ObjID = objID
@@ -1871,19 +1874,6 @@
    # 暂时只算主线小怪
    if curPlayer and turnFight.mapID == ChConfig.Def_FBMapID_Main and gameObj.GetFaction() != ChConfig.Def_FactionA:
        GetMainFightMgr(curPlayer).killNPCCnt += 1
    # 清除光源buff
    buffMgr = gameObj.GetBuffManager()
    for index in range(buffMgr.GetBuffCount())[::-1]:
        buff = buffMgr.GetBuffByIndex(index)
        skillID = buff.GetSkillID()
        skillData = buff.GetSkillData()
        if skillData.GetSkillType() != ChConfig.Def_SkillType_Halo:
            continue
        if buff.GetOwnerID() != objID:
            continue
        GameWorld.DebugLog("删除光环buff: objID=%s,skillID=%s" % (objID, skillID))
        TurnBuff.DoBuffDel(turnFight, gameObj, buff)
    return True
def OnTurnAllOver(guid):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -93,6 +93,12 @@
Def_BuffValue_Count = 3     # buff记录的value个数
# buff保留类型定义
(
BuffRetainType_Dead, # 死亡保留 1
BuffRetainType_Revive, # 复活保留 2
) = range(1, 1 + 2)
#游戏对象属性--------------------------------------------
# 属性ID列表,所有对象类型通用,如Player、NPC
AttrIDList = (
@@ -168,7 +174,9 @@
AttrID_ComboDamPerDef,                      # 连击减伤 70
AttrID_PVPDamPer,                           # PVP增伤 71
AttrID_PVPDamPerDef,                        # PVP减伤 72
) = range(1, 1 + 72)
AttrID_ReviveHPPer,                         # 复活生命加成 73
AttrID_ReviveXPPer,                         # 复活怒气加成 74
) = range(1, 1 + 74)
# 需要计算的武将战斗属性ID列表
CalcBattleAttrIDList = [AttrID_Atk, AttrID_Def, AttrID_MaxHP, AttrID_StunRate, AttrID_StunRateDef, 
@@ -182,7 +190,8 @@
                        AttrID_WeiFinalDamPer, AttrID_WeiFinalDamPerDef, AttrID_ShuFinalDamPer, AttrID_ShuFinalDamPerDef,
                        AttrID_WuFinalDamPer, AttrID_WuFinalDamPerDef, AttrID_QunFinalDamPer, AttrID_QunFinalDamPerDef,
                        AttrID_BatDamPer, AttrID_BatDamPerDef, AttrID_PursueDamPer, AttrID_PursueDamPerDef,
                        AttrID_ComboDamPer, AttrID_ComboDamPerDef, AttrID_XPRecoverPer, AttrID_PVPDamPer, AttrID_PVPDamPerDef
                        AttrID_ComboDamPer, AttrID_ComboDamPerDef, AttrID_XPRecoverPer, AttrID_PVPDamPer, AttrID_PVPDamPerDef,
                        AttrID_ReviveHPPer, AttrID_ReviveXPPer,
                        ]
# 基础三维属性ID列表
@@ -3997,10 +4006,13 @@
TriggerWay_BeAtkBack, # 被反击时 39
TriggerWay_InBattlefield, # 在场时 40
TriggerWay_Revive, # 复活时 41
) = range(1, 1 + 41)
TriggerWay_BigTurnStartByDead, # 大回合开始时(死亡后有效) 42
) = range(1, 1 + 42)
# 不加载的被动触发方式,一般用于本技能固定触发逻辑用的
TriggerWayNoLoadList = [TriggerWay_CurSkillEff, TriggerWay_CurSkillEffLst]
# 死亡可以触发的方式
DeadCanTriggerWayList = [TriggerWay_BigTurnStartByDead]
# 被动触发有效来源
TriggerSrc_Skill = 1    # 身上技能有效
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/TurnFight.py
@@ -235,8 +235,15 @@
            GameWorld.DebugAnswer(curPlayer, "--- %s%s" % (objName, "" if batObj.IsAlive() else " [被击杀]"))
            GameWorld.DebugAnswer(curPlayer, "HP:%s/%s" % (batObj.GetHP(), batObj.GetMaxHP()))
            GameWorld.DebugAnswer(curPlayer, "攻:%s,防:%s,怒:%s" % (batObj.GetAtk(), batObj.GetDef(), batObj.GetXP()))
            attrStr = ""
            attrDict = batObj.GetBatAttrDict()
            GameWorld.DebugAnswer(curPlayer, "属性:%s" % attrDict)
            attrIDList = attrDict.keys()
            attrIDList.sort()
            for attrID in attrIDList:
                attrValue = attrDict[attrID]
                if attrValue:
                    attrStr += "%s=%s;" % (attrID, attrValue)
            GameWorld.DebugAnswer(curPlayer, "属性:%s" % attrStr)
            skillMgr = batObj.GetSkillManager()
            skillIDList = skillMgr.GetSkillIDList()
            GameWorld.DebugAnswer(curPlayer, "技能: %s,%s" % (len(skillIDList), skillIDList))
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -142,6 +142,7 @@
                        ("BYTE", "LayerMax", 0),
                        ("DWORD", "BuffRepeat", 0),
                        ("BYTE", "DispersedLimit", 0),
                        ("BYTE", "BuffRetain", 0),
                        ("DWORD", "FightPower", 0),
                        ),
@@ -2355,7 +2356,8 @@
    def GetLayerMax(self): return self.attrTuple[37] # 最大层数 BYTE
    def GetBuffRepeat(self): return self.attrTuple[38] # Buff叠加规则 DWORD
    def GetDispersedLimit(self): return self.attrTuple[39] # 驱散限制 BYTE
    def GetFightPower(self): return self.attrTuple[40] # 技能战斗力 DWORD
    def GetBuffRetain(self): return self.attrTuple[40] # Buff保留规则 BYTE
    def GetFightPower(self): return self.attrTuple[41] # 技能战斗力 DWORD
# 武将表
class IPY_Hero():
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_6014.py
@@ -16,11 +16,13 @@
#-------------------------------------------------------------------------------
import GameWorld
import ChConfig
def GetHappenValue(attacker, defender, curEffect, effSkill, effBuff, connSkill, **skillkwargs):
    addRate = curEffect.GetEffectValue(0)
    onlyFirstUse = curEffect.GetEffectValue(1) # 是否仅首次释放技能有效
    skillID = connSkill.GetSkillID() if connSkill else skillkwargs.get("connSkillID", 0)
    if onlyFirstUse:
        skillID = connSkill.GetSkillID() if connSkill else skillkwargs.get("connSkillID", 0)
        if not skillID:
            #GameWorld.DebugLog("没有增加概率的技能ID! %s" % skillkwargs)
            return
@@ -28,4 +30,22 @@
        if useCnt > 0:
            GameWorld.DebugLog("技能非首次使用不增加额外概率! skillID=%s,useCnt=%s" % (skillID, useCnt))
            return
    return curEffect.GetEffectValue(0)
    failAddRateEx = curEffect.GetEffectValue(2) # 失败次数额外增加概率
    if failAddRateEx:
        failCnt = attacker.GetSkillHappenFailCnt(skillID)
        mustHappenFailCnt = curEffect.GetEffectValue(3) # x次失败后必定释放,大于0有效
        if mustHappenFailCnt and failCnt >= mustHappenFailCnt:
            addRate = ChConfig.Def_MaxRateValue # 强制增加满概率
            GameWorld.DebugLog("技能概率失败次数必定成功: mustHappenFailCnt=%s,failCnt=%s,addRate=%s" % (mustHappenFailCnt, failCnt, addRate))
        elif failCnt > 0:
            addRate = failAddRateEx * failCnt
            GameWorld.DebugLog("技能概率失败次数增加概率: failAddRateEx=%s,failCnt=%s,addRate=%s" % (failAddRateEx, failCnt, addRate))
    if effBuff:
        buffLayer = effBuff.GetLayer()
        if buffLayer > 1:
            addRate *= buffLayer
            GameWorld.DebugLog("多层buff增加技能概率! skillID=%s,buffLayer=%s,addRate=%s" % (effBuff.GetSkillID(), buffLayer, addRate))
    return addRate
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuff.py
@@ -336,15 +336,17 @@
    DoBuffDel(turnFight, batObj, curBuff, relatedSkill)
    return
def DoBuffDel(turnFight, batObj, curBuff, relatedSkill=None, afterLogic=False, tagObj=None):
def DoBuffDel(turnFight, batObj, curBuff, relatedSkill=None, afterLogic=False, tagObj=None, noRefreshAttr=False, isSync=True):
    '''删除buff
    @param relatedSkill: 关联的技能
    @param afterLogic: 是否需要在关联技能处理完毕后才处理删除后续逻辑,如通知,触发被动等
    @param tagObj: 由谁引起的buff删除
    @param noRefreshAttr: 不刷新属性
    @return: isRefreshAttr 是否需要刷属性,如果设置了 noRefreshAttr,则要在外层刷属性
    '''
    
    release = True
    isSync = True
    release = True # 释放buff实例
    #isSync = True
    relatedSkillID = relatedSkill.GetSkillID() if relatedSkill else 0
    if afterLogic and relatedSkill:
        release = False
@@ -395,7 +397,7 @@
    if haveBuffPassiveEff:
        batObj.GetPassiveEffManager().DelBuffPassiveEffect(buffID)
        
    if isRefreshAttr:
    if isRefreshAttr and not noRefreshAttr:
        RefreshBuffAttr(batObj)
        
    if skillType == ChConfig.Def_SkillType_Halo and ownerID == buffObjID:
@@ -412,7 +414,7 @@
            if not haloBuff:
                continue
            DoBuffDel(turnFight, haloObj, haloBuff, relatedSkill, afterLogic, tagObj)
    return
    return isRefreshAttr
def DoBuffDelAfterLogicOver(turnFight, buffObjID, curBuff, relatedSkill):
    ## buff删除后续处理逻辑处理完毕
@@ -429,7 +431,73 @@
    if callFunc:
        callFunc(turnFight, batObj, curBuff, **kwargs)
    return
def DoBuffByDead(turnFight, batObj):
    ## 死亡处理buff
    isRefreshAttr = False
    objID = batObj.GetID()
    buffMgr = batObj.GetBuffManager()
    for index in range(buffMgr.GetBuffCount())[::-1]:
        buff = buffMgr.GetBuffByIndex(index)
        buffID = buff.GetBuffID()
        skillID = buff.GetSkillID()
        if buff.GetBuffRetain()&pow(2, ChConfig.BuffRetainType_Dead):
            GameWorld.DebugLog("死亡不清除的buff: objID=%s,buffID=%s,skillID=%s" % (objID, buffID, skillID))
            continue
        if DoBuffDel(turnFight, batObj, buff, noRefreshAttr=True, isSync=False): # 可不通知,前端默认都清除,复活后重新同步
            isRefreshAttr = True
    if isRefreshAttr:
        RefreshBuffAttr(batObj)
    return
def DoBuffByRevive(turnFight, batObj):
    ## 复活处理buff
    
    isRefreshAttr = False
    objID = batObj.GetID()
    buffMgr = batObj.GetBuffManager()
    for index in range(buffMgr.GetBuffCount()):
        buff = buffMgr.GetBuffByIndex(index)
        buffID = buff.GetBuffID()
        skillID = buff.GetSkillID()
        if buff.GetBuffRetain()&pow(2, ChConfig.BuffRetainType_Revive):
            GameWorld.DebugLog("复活不清除的buff: objID=%s,buffID=%s,skillID=%s" % (objID, buffID, skillID))
            SyncBuffRefresh(turnFight, batObj, buff, isNewAdd=True) # 复活时还存在的buff通知前端视为新添加的
            continue
        if DoBuffDel(turnFight, batObj, buff, noRefreshAttr=True, isSync=False): # 复活可不通知删除的buff
            isRefreshAttr = True
    if isRefreshAttr:
        RefreshBuffAttr(batObj)
    # 重新添加本阵营有效光环
    batObjMgr = BattleObj.GetBatObjMgr()
    batLineup = batObj.GetBatLineup()
    for tagObjID in batLineup.posObjIDDict.values():
        tagObj = batObjMgr.getBatObj(tagObjID)
        if not tagObj.IsAlive():
            continue
        tagBuffMgr = tagObj.GetBuffManager()
        for index in range(tagBuffMgr.GetBuffCount()):
            buff = tagBuffMgr.GetBuffByIndex(index)
            haloObjIDList = buff.GetHaloObjIDList()
            if not haloObjIDList or objID not in haloObjIDList:
                continue
            if buff.GetOwnerID() != tagObjID:
                # 非光源
                continue
            haloSkillID = buff.GetSkillID()
            GameWorld.DebugLog("复活后重新添加本阵营光环: objID=%s,ownerID=%s,haloSkillID=%s" % (objID, tagObjID, haloSkillID))
            haloSkill = tagObj.GetSkillManager().FindSkillByID(haloSkillID)
            if not haloSkill:
                continue
            OnAddBuff(turnFight, batObj, haloSkill, buffOwner=tagObj)
    # 光源重新添加有效光环,根据光源是否还有效规则优化,待处理
    return
def RefreshBuffAttr(batObj, isInit=False):
    ''' 刷新buff属性,如果有涉及到buff属性变更的,只能全部buff重新刷
    '''
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnPassive.py
@@ -35,7 +35,8 @@
    ''' 触发被动效果,可能触发技能、buff,需根据优先级触发
    '''
    if not batObj.IsAlive():
        return
        if triggerWay not in ChConfig.DeadCanTriggerWayList:
            return
    passiveEffMgr = batObj.GetPassiveEffManager()
    effInfoList = passiveEffMgr.GetPassiveEffByTrigger(triggerWay, connSkill, connSkillTypeID, connBuff)
    if not effInfoList:
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py
@@ -61,8 +61,12 @@
        return
    
    if not curBatObj.IsAlive():
        return
        if useSkill.GetSkillType() == ChConfig.Def_SkillType_Revive and useSkill.GetTagAim() == ChConfig.SkillTagAim_Self:
            GameWorld.DebugLog("死亡时使用复活自己的技能! skillID=%s" % skillID)
        else:
            # 其他技能死亡状态下无法释放
            return
    objID = curBatObj.GetID()
    
    if hasattr(useSkill, "GetRemainTime") and useSkill.GetRemainTime() > 0:
@@ -85,10 +89,15 @@
        rate = useSkill.GetHappenRate()
        if rate:
            rate += TurnPassive.GetTriggerEffectValue(turnFight, curBatObj, None, ChConfig.PassiveEff_AddSkillRate, useSkill)
            isRemove = False
            for tagObj in tagObjList[::-1]:
                if not GameWorld.CanHappen(rate, ChConfig.Def_MaxRateValue):
                if not curBatObj.IsSkillCanHappen(skillID, rate):
                    tagObjList.remove(tagObj)
                    isRemove = True
                    GameWorld.DebugLog("    概率不触发,移除目标! rate=%s,skillID=%s,tagID=%s" % (rate, skillID, tagObj.GetID()))
            if not tagObjList and isRemove:
                return
    if not tagObjList:
        # 可扩展其他目标选择,如复活技能没有死亡单位时则使用另外的效果
        GameWorld.DebugLog("找不到技能目标! skillID=%s,mapID=%s,funcLineID=%s" % (skillID, turnFight.mapID, turnFight.funcLineID), turnFight.playerID)
@@ -862,21 +871,35 @@
def SkillModule_3(turnFight, curBatObj, useSkill):
    ## 复活
    
    skillPer = useSkill.GetSkillPer()
    initXP = IpyGameDataPY.GetFuncCfg("AngerXP", 1)
    xpMax = IpyGameDataPY.GetFuncCfg("AngerXP", 2)
    for tagBatObj in useSkill.GetTagObjList():
        skillPer += GetAddSkillPer(turnFight, curBatObj, tagBatObj, useSkill) # 复活后的血量百分比
        skillPer = useSkill.GetSkillPer()
        skillPer += GetAddSkillPer(turnFight, curBatObj, tagBatObj, useSkill)
        reviveHPPer = tagBatObj.GetBatAttrValue(ChConfig.AttrID_ReviveHPPer)
        reviveHPPer += skillPer
        reviveHPPer += TurnPassive.GetTriggerEffectValue(turnFight, tagBatObj, curBatObj, ChConfig.AttrID_ReviveHPPer, useSkill)
        reviveXPPer = tagBatObj.GetBatAttrValue(ChConfig.AttrID_ReviveXPPer)
        reviveXPPer += TurnPassive.GetTriggerEffectValue(turnFight, tagBatObj, curBatObj, ChConfig.AttrID_ReviveXPPer, useSkill)
        
        dID = tagBatObj.GetID()
        dMapHP = tagBatObj.GetMaxHP()
        cureHP = int(dMapHP * skillPer / 10000.0)
        cureHP = int(dMapHP * reviveHPPer / 10000.0)
        xp = initXP + int(xpMax * reviveXPPer / 10000.0)
        tagBatObj.SetRevive(cureHP)
        tagBatObj.SetXP(xp, False)
        
        hurtObj = useSkill.AddHurtObj(dID)
        hurtObj.AddHurtType(ChConfig.HurtAtkType_Revive)
        hurtObj.SetHurtHP(cureHP)
        hurtObj.SetLostHP(cureHP)
        hurtObj.SetCurHP(tagBatObj.GetHP())
        GameWorld.DebugLog("    复活: dID=%s,cureHP=%s,skillPer=%s,%s/%s" % (dID, cureHP, skillPer, tagBatObj.GetHP(), dMapHP))
        GameWorld.DebugLog("    复活: dID=%s,cureHP=%s,skillPer=%s,reviveHPPer=%s,%s/%s,xp=%s,reviveXPPer=%s"
                           % (dID, cureHP, skillPer, reviveHPPer, tagBatObj.GetHP(), dMapHP, xp, reviveXPPer))
        
    return
@@ -1386,6 +1409,9 @@
                 
    # 复活时
    for tagObj in reviveObjList:
        # 同步最新的怒气及buff,血量已经在技能中通知了
        tagObj.SetXP(tagObj.GetXP())
        TurnBuff.DoBuffByRevive(turnFight, tagObj)
        TurnPassive.OnTriggerPassiveEffect(turnFight, tagObj, ChConfig.TriggerWay_Revive, curObj, connSkill=useSkill)
        TurnPassive.OnTriggerPassiveEffect(turnFight, tagObj, ChConfig.TriggerWay_InBattlefield, curObj, connSkill=useSkill)
        
@@ -1630,7 +1656,8 @@
        GameWorld.DebugLog("继承主技能目标! enhanceSkillID=%s" % enhanceSkillID)
        # 额外触发的技能直接在外层检查概率,如果都没有触发则不需要再处理
        enhanceRate = enhanceSkillData.GetHappenRate()
        enhanceRate += TurnPassive.GetTriggerEffectValue(turnFight, curBatObj, None, ChConfig.PassiveEff_AddSkillRate, connSkillTypeID=enhanceSkillData.GetSkillTypeID(), connSkillID=enhanceSkillID)
        if enhanceRate:
            enhanceRate += TurnPassive.GetTriggerEffectValue(turnFight, curBatObj, None, ChConfig.PassiveEff_AddSkillRate, connSkillTypeID=enhanceSkillData.GetSkillTypeID(), connSkillID=enhanceSkillID)
        enchanceTagObjList = []
        for tagObj in tagObjList:
            tagID = tagObj.GetID()
@@ -1650,7 +1677,7 @@
            if checkHeroSex and checkHeroSex != tagObj.GetSex():
                GameWorld.DebugLog("    非目标性别不触发: tagID=%s,sex=%s != %s" % (tagID, tagObj.GetSex(), checkHeroSex))
                continue
            if enhanceRate and enhanceRate != ChConfig.Def_MaxRateValue and not GameWorld.CanHappen(enhanceRate, ChConfig.Def_MaxRateValue):
            if not curBatObj.IsSkillCanHappen(enhanceSkillID, enhanceRate):
                GameWorld.DebugLog("    概率不触发: tagID=%s,enhanceRate=%s" % (tagID, enhanceRate))
                continue
            
@@ -1722,16 +1749,17 @@
    isOK = False
    # 继承主技能目标
    if passiveSkill.GetTagAim() == ChConfig.SkillTagAim_MainSkill:
        happenRate = passiveSkill.GetHappenRate()
        happenRate += TurnPassive.GetTriggerEffectValue(turnFight, batObj, None, ChConfig.PassiveEff_AddSkillRate, passiveSkill)
        GameWorld.DebugLog("被动触发技能,继承主技能目标! effSkillID=%s,effectID=%s,passiveSkillID=%s,happenRate=%s,bySkillID=%s" % (effSkillID, effectID, passiveSkillID, happenRate, bySkillID))
        if not tagObj:
            return
        happenRate = passiveSkill.GetHappenRate()
        if happenRate:
            happenRate += TurnPassive.GetTriggerEffectValue(turnFight, batObj, None, ChConfig.PassiveEff_AddSkillRate, passiveSkill)
        GameWorld.DebugLog("被动触发技能,继承主技能目标! effSkillID=%s,effectID=%s,passiveSkillID=%s,happenRate=%s,bySkillID=%s" % (effSkillID, effectID, passiveSkillID, happenRate, bySkillID))
        tagID = tagObj.GetID()
        if not tagObj.IsAlive() and passiveSkill.GetSkillType() != ChConfig.Def_SkillType_Revive:
            GameWorld.DebugLog("    已被击杀不触发: tagID=%s" % (tagID))
            return
        if happenRate and not GameWorld.CanHappen(happenRate, ChConfig.Def_MaxRateValue):
        if not batObj.IsSkillCanHappen(passiveSkillID, happenRate):
            GameWorld.DebugLog("    概率不触发: tagID=%s,happenRate=%s" % (tagID, happenRate))
            return
        passiveTagObjList = [tagObj]