hxp
2025-11-27 ab3c1e29995e5bae442a06bbd8c4ae821efe88d0
129 【战斗】战斗系统-服务端(优化被动buff触发有效效果逻辑;)
7个文件已修改
164 ■■■■ 已修改文件
PySysDB/PySysDBPY.h 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BattleObj.py 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py 30 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuff.py 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnPassive.py 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py 58 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PySysDB/PySysDBPY.h
@@ -101,15 +101,15 @@
    DWORD        EffectID1;    //效果ID1
    list        EffectValues1;    //效果值列表1
    BYTE        TriggerWay1;    //触发方式
    BYTE        TriggerSrc1;    //有效来源
    list        TriggerSrc1;    //有效来源
    DWORD        EffectID2;    //效果ID2
    list        EffectValues2;    //效果值列表2
    BYTE        TriggerWay2;    //触发方式
    BYTE        TriggerSrc2;    //有效来源
    list        TriggerSrc2;    //有效来源
    DWORD        EffectID3;    //效果ID3
    list        EffectValues3;    //效果值列表3
    BYTE        TriggerWay3;    //触发方式
    BYTE        TriggerSrc3;    //有效来源
    list        TriggerSrc3;    //有效来源
    WORD        CoolDownInit;    //初始冷却时间
    WORD        CoolDownTime;    //技能冷却时间
    list        BuffStateLimit;    //Buff状态限制组
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BattleObj.py
@@ -35,6 +35,7 @@
        # 被影响的技能ID: 0为所有技能
        self._AffectSkillDict = {} # 被动技能 {(触发方式, 有效来源):{技能ID:[effID, ...], ...}, ...}
        self._AffectBuffDict = {} # 被动buff {(触发方式, 有效来源):{buffID:[effID, ...], ...}, ...}
        self._buffSkillIDDict = {} # {buffID:skillID, ...}
        return
    
    def onRelease(self):
@@ -45,7 +46,7 @@
    def GetPassiveEffByTrigger(self, triggerWay, connSkill=None, connSkillTypeID=0, connBuff=None):
        '''获取可触发的效果列表,技能跟buff根据触发优先级按顺序触发,优先级越高越先执行,相同时技能优先
                        优先级之后有需要再扩展
        @return: [["skill/buff", skillID/buffID, effIDList], ...]
        @return: [["skill/buff", skillID, buffID, effIDList], ...]
        '''
        effList = []
        
@@ -75,7 +76,7 @@
                    if tWay in ChConfig.TriggerWayNoLoadList:
                        continue
                    if tSrc != ChConfig.TriggerSrc_SkillSelf:
                        # 仅添加本技能的
                        # 非对象身上已学的技能时,仅添加本技能有效的
                        continue
                    if tWay == ChConfig.TriggerWay_CalcEffValue:
                        tWay = "%s_%s" % (tWay, effectID)
@@ -83,7 +84,7 @@
                        continue
                    effIDList.append(effectID)
                if effIDList:
                    effList.append(["skill", skillID, effIDList])
                    effList.append(["skill", skillID, 0, effIDList])
                    
        # 优先取关联技能的
        if connSkillTypeID and connSkillTypeID not in [ChConfig.TriggerSrc_Skill, ChConfig.TriggerSrc_Buff, ChConfig.TriggerSrc_SkillSelf, ChConfig.TriggerSrc_BuffSelf]:
@@ -92,26 +93,26 @@
            if key in self._AffectSkillDict:
                effDict = self._AffectSkillDict[key]
                for skillID, effIDList in effDict.items():
                    effList.append(["skill", skillID, effIDList])
                    effList.append(["skill", skillID, 0, effIDList])
                    
            # buff
            key = (triggerWay, connSkillTypeID)
            if key in self._AffectBuffDict:
                effDict = self._AffectBuffDict[key]
                for buffID, effIDList in effDict.items():
                    effList.append(["buff", buffID, effIDList])
                    effList.append(["buff", self._buffSkillIDDict.get(buffID, 0), buffID, effIDList])
                    
        # 所有技能有效的
        key = (triggerWay, ChConfig.TriggerSrc_Skill)
        effDict = self._AffectSkillDict.get(key, {})
        for skillID, effIDList in effDict.items():
            effList.append(["skill", skillID, effIDList])
            effList.append(["skill", skillID, 0, effIDList])
            
        # 所有buff有效的
        key = (triggerWay, ChConfig.TriggerSrc_Buff)
        effDict = self._AffectBuffDict.get(key, {})
        for buffID, effIDList in effDict.items():
            effList.append(["buff", buffID, effIDList])
            effList.append(["buff", self._buffSkillIDDict.get(buffID, 0), buffID, effIDList])
            
        return effList
    
@@ -140,7 +141,7 @@
            return
        if triggerWay in ChConfig.TriggerWayNoLoadList:
            return
        if triggerSrc in [ChConfig.TriggerSrc_Buff, ChConfig.TriggerSrc_BuffSelf]:
        if effect.GetTriggerBuffEnable():
            # buff有效的不加进来
            return
        
@@ -190,8 +191,8 @@
            return
        if triggerWay in ChConfig.TriggerWayNoLoadList:
            return
        if triggerSrc in [ChConfig.TriggerSrc_Skill, ChConfig.TriggerSrc_SkillSelf]:
            # 技能有效的不加进来
        if not effect.GetTriggerBuffEnable():
            # 非buff有效的不加进来
            return
        
        buffID = buff.GetBuffID()
@@ -212,6 +213,7 @@
        effIDList = effDict[buffID]
        if effectID not in effIDList:
            effIDList.append(effectID)
        self._buffSkillIDDict[buffID] = skillData.GetSkillID()
        return
    
    def DelBuffPassiveEffect(self, buffID):
@@ -222,6 +224,7 @@
            effDict.pop(buffID)
            if not effDict:
                self._AffectBuffDict.pop(key)
            self._buffSkillIDDict.pop(buffID, 0)
        return
    
class HurtObj():
@@ -282,12 +285,13 @@
    
class SkillEffect():
    
    def __init__(self, effID, values, triggerWay=0, triggerSrc=0):
    def __init__(self, effID, values, triggerWay=0, triggerSrcs=[]):
        # @param triggerSrcs: 触发参数 [触发来源, buff时是否有效默认无效]
        self._effID = effID
        self._values = values
        self._triggerWay = triggerWay
        self._triggerSrc = triggerSrc
        #self._triggerParams = triggerParams if triggerParams else []
        self._triggerSrc = triggerSrcs[0] if len(triggerSrcs) > 0 else 0
        self._triggerBuffEnable = triggerSrcs[1] if len(triggerSrcs) > 1 else 0
        return
    
    def onRelease(self):
@@ -300,8 +304,13 @@
    def GetEffectValues(self): return self._values # 直接返回整个效果values
    def GetTriggerWay(self): return self._triggerWay
    def GetTriggerSrc(self): return self._triggerSrc
    #def GetTriggerParams(self, index): return self._triggerParams[index] if len(self._triggerParams) > index else 0
    def GetTriggerBuffEnable(self):
        if self.GetTriggerSrc() in [ChConfig.TriggerSrc_Buff, ChConfig.TriggerSrc_BuffSelf]:
            return True
        if self._triggerBuffEnable:
            return True
        return False
class SklllData():
    
    def __init__(self, ipyData):
@@ -313,7 +322,6 @@
            values = getattr(ipyData, "GetEffectValues%s" % num)()
            triggerWay = getattr(ipyData, "GetTriggerWay%s" % num)()
            triggerSrc = getattr(ipyData, "GetTriggerSrc%s" % num)()
            #triggerParams = getattr(ipyData, "GetTriggerParams%s" % num)()
            effect = ObjPool.GetPoolMgr().acquire(SkillEffect, effID, values, triggerWay, triggerSrc)
            self._effList.append(effect)
            self._effDict[(effID, triggerWay)] = effect
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -913,22 +913,22 @@
AfterLogic_AddBuff = "AddBuff"
AfterLogic_SyncBuff = "SyncBuff"
#伤害类型
#伤害飘血类型
(
HurtType_Fail,              # 失败 - 如概率没有触发 0
HurtType_Normal,            # 伤害 1
HurtTYpe_Cure,              # 治疗 2
HurtType_Revive,            # 复活 3
HurtType_Immune,            # 免疫 4
HurtType_Parry,             # 格挡 5
HurtType_IgnoreDef,         # 无视防御/真实伤害 6
HurtType_SuperHit,          # 暴击 7
HurtType_Stun,              # 击晕 8 仅算概率触发的击晕,技能额外击晕效果的不算
HurtType_Miss,              # 闪避 9
HurtType_PoisonCureHurt,    # 伤害毒奶 10
HurtType_PoisonCureSuck,    # 吸血毒奶 11
HurtType_HarmSelf,          # 自残 12
HurtType_CaorenProtect,     # 本次伤害有受曹仁防护标记 13
HurtAtkType_Fail,              # 失败 - 如概率没有触发 0
HurtAtkType_Hurt,              # 伤害 1
HurtAtkType_Cure,              # 治疗 2
HurtAtkType_Revive,            # 复活 3
HurtAtkType_Immune,            # 免疫 4
HurtAtkType_Parry,             # 格挡 5
HurtAtkType_IgnoreDef,         # 无视防御/真实伤害 6
HurtAtkType_SuperHit,          # 暴击 7
HurtAtkType_Stun,              # 击晕 8 仅算概率触发的击晕,技能额外击晕效果的不算
HurtAtkType_Miss,              # 闪避 9
HurtAtkType_PoisonCureHurt,    # 伤害毒奶 10
HurtAtkType_PoisonCureSuck,    # 吸血毒奶 11
HurtAtkType_HarmSelf,          # 自残 12
HurtAtkType_CaorenProtect,     # 本次伤害有受曹仁防护标记 13
) = range(14)
#伤害类型
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -123,15 +123,15 @@
                        ("DWORD", "EffectID1", 0),
                        ("list", "EffectValues1", 0),
                        ("BYTE", "TriggerWay1", 0),
                        ("BYTE", "TriggerSrc1", 0),
                        ("list", "TriggerSrc1", 0),
                        ("DWORD", "EffectID2", 0),
                        ("list", "EffectValues2", 0),
                        ("BYTE", "TriggerWay2", 0),
                        ("BYTE", "TriggerSrc2", 0),
                        ("list", "TriggerSrc2", 0),
                        ("DWORD", "EffectID3", 0),
                        ("list", "EffectValues3", 0),
                        ("BYTE", "TriggerWay3", 0),
                        ("BYTE", "TriggerSrc3", 0),
                        ("list", "TriggerSrc3", 0),
                        ("WORD", "CoolDownInit", 0),
                        ("WORD", "CoolDownTime", 0),
                        ("list", "BuffStateLimit", 0),
@@ -2343,15 +2343,15 @@
    def GetEffectID1(self): return self.attrTuple[18] # 效果ID1 DWORD
    def GetEffectValues1(self): return self.attrTuple[19] # 效果值列表1 list
    def GetTriggerWay1(self): return self.attrTuple[20] # 触发方式 BYTE
    def GetTriggerSrc1(self): return self.attrTuple[21] # 有效来源 BYTE
    def GetTriggerSrc1(self): return self.attrTuple[21] # 有效来源 list
    def GetEffectID2(self): return self.attrTuple[22] # 效果ID2 DWORD
    def GetEffectValues2(self): return self.attrTuple[23] # 效果值列表2 list
    def GetTriggerWay2(self): return self.attrTuple[24] # 触发方式 BYTE
    def GetTriggerSrc2(self): return self.attrTuple[25] # 有效来源 BYTE
    def GetTriggerSrc2(self): return self.attrTuple[25] # 有效来源 list
    def GetEffectID3(self): return self.attrTuple[26] # 效果ID3 DWORD
    def GetEffectValues3(self): return self.attrTuple[27] # 效果值列表3 list
    def GetTriggerWay3(self): return self.attrTuple[28] # 触发方式 BYTE
    def GetTriggerSrc3(self): return self.attrTuple[29] # 有效来源 BYTE
    def GetTriggerSrc3(self): return self.attrTuple[29] # 有效来源 list
    def GetCoolDownInit(self): return self.attrTuple[30] # 初始冷却时间 WORD
    def GetCoolDownTime(self): return self.attrTuple[31] # 技能冷却时间 WORD
    def GetBuffStateLimit(self): return self.attrTuple[32] # Buff状态限制组 list
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuff.py
@@ -257,7 +257,7 @@
            continue
        
        if curEffect.GetTriggerWay():
            if curEffect.GetTriggerSrc() not in [ChConfig.TriggerSrc_Skill, ChConfig.TriggerSrc_SkillSelf] and refreshType == 1:
            if refreshType == 1 and curEffect.GetTriggerBuffEnable():
                passiveEffMgr.AddBuffPassiveEffect(curBuff, skillData, curEffect)
                
        elif effectID in ChConfig.AttrIDList:
@@ -386,7 +386,7 @@
            if triggerWay == ChConfig.TriggerWay_BuffDel:
                TurnPassive.OnTriggerPassiveEffect(turnFight, batObj, ChConfig.TriggerWay_BuffDel, connBuff=curBuff)
                
            if curEffect.GetTriggerSrc() not in [ChConfig.TriggerSrc_Skill, ChConfig.TriggerSrc_SkillSelf]:
            if curEffect.GetTriggerBuffEnable():
                haveBuffPassiveEff = True
                
        elif effectID in ChConfig.AttrIDList:
@@ -458,7 +458,7 @@
            if effID not in ChConfig.AttrIDList:
                continue
            if effect.GetTriggerSrc() not in [ChConfig.TriggerSrc_Skill]:
                # 技能时仅技能有效
                # 技能属性仅技能时有效
                continue
            attrID = effID
            attrValue = effect.GetEffectValue(0)
@@ -491,7 +491,7 @@
            effID = effect.GetEffectID()
            if effID not in ChConfig.AttrIDList:
                continue
            if effect.GetTriggerSrc() and effect.GetTriggerSrc() not in [ChConfig.TriggerSrc_Buff, ChConfig.TriggerSrc_BuffSelf]:
            if not (not effect.GetTriggerSrc() or effect.GetTriggerBuffEnable()):
                # buff时,不配默认有效,或仅buff有效
                continue
            attrID = effID
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnPassive.py
@@ -40,17 +40,16 @@
    effInfoList = passiveEffMgr.GetPassiveEffByTrigger(triggerWay, connSkill, connSkillTypeID, connBuff)
    if not effInfoList:
        return
    # [["skill/buff", skillID/buffID, effIDList], ...]
    # [["skill/buff", skillID, buffID, effIDList], ...]
    tagID = tagObj.GetID() if tagObj else 0
    GameWorld.DebugLog("触发被动: triggerWay=%s,objID=%s,tagID=%s,%s" % (triggerWay, batObj.GetID(), tagID, effInfoList))
    for effInfo in effInfoList:
        sign = effInfo[0]
        skillID, buffID, effIDList = effInfo[1:]
        if sign == "skill":
            skillID, effIDList = effInfo[1:]
            __doTriggerPassiveEffectBySkill(turnFight, batObj, tagObj, triggerWay, skillID, effIDList, connSkill, connBuff, **kwargs)
            
        elif sign == "buff":
            buffID, effIDList = effInfo[1:]
            __doTriggerPassiveEffectByBuff(turnFight, batObj, tagObj, triggerWay, buffID, effIDList, connSkill, connBuff, **kwargs)
            
    return
@@ -127,18 +126,17 @@
    curValue = 0
    skillMgr = atkObj.GetSkillManager()
    buffMgr = atkObj.GetBuffManager()
    # [["skill/buff", skillID/buffID, effIDList], ...]
    # [["skill/buff", skillID, buffID, effIDList], ...]
    tagID = defObj.GetID() if defObj else 0
    for effInfo in effInfoList:
        sign = effInfo[0]
        skillID, buffID, effIDList = effInfo[1:]
        if sign == "skill":
            skillID, effIDList = effInfo[1:]
            effSkill = skillMgr.FindSkillByID(skillID)
            if not effSkill and connSkill and connSkill.GetSkillID() == skillID:
                effSkill = connSkill
            effBuff = None
        elif sign == "buff":
            buffID, effIDList = effInfo[1:]
            effBuff = buffMgr.GetBuff(buffID)
            if not effBuff:
                continue
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py
@@ -732,7 +732,7 @@
    curBatObj.SetHarmSelfHP(harmHP) # 无视实际扣血量,直接更新
    
    # 单独通知前端表现
    hurtTypes = pow(2, ChConfig.HurtType_HarmSelf)
    hurtTypes = pow(2, ChConfig.HurtAtkType_HarmSelf)
    diffType, diffValue = 0, lostHP
    skillID = relatedSkillID = useSkill.GetSkillID()
    Sync_PropertyRefreshView(turnFight, curBatObj, ChConfig.AttrID_HP, updHP, diffValue, diffType, skillID, relatedSkillID, hurtTypes)
@@ -872,7 +872,7 @@
        tagBatObj.SetRevive(cureHP)
        
        hurtObj = useSkill.AddHurtObj(dID)
        hurtObj.AddHurtType(ChConfig.HurtType_Revive)
        hurtObj.AddHurtType(ChConfig.HurtAtkType_Revive)
        hurtObj.SetHurtHP(cureHP)
        hurtObj.SetLostHP(cureHP)
        hurtObj.SetCurHP(tagBatObj.GetHP())
@@ -892,8 +892,9 @@
    for tagBatObj, cureHP, poisonCureOwner in calcCureResults:
        # 汇总毒奶
        if poisonCureOwner:
            hurtTypes = pow(2, ChConfig.HurtTYpe_Cure)
            hurtTypes |= pow(2, ChConfig.HurtType_PoisonCureHurt)
            hurtTypes = pow(2, ChConfig.HurtAtkType_Cure)
            hurtTypes |= pow(2, ChConfig.HurtAtkType_Hurt)
            hurtTypes |= pow(2, ChConfig.HurtAtkType_PoisonCureHurt)
            hurtValue = cureHP
            hurtValue, hurtTypes, immuneHurt = CalcHurtWithBuff(turnFight, atkObj, tagBatObj, hurtValue, hurtTypes)
            calcHurtResults.append([tagBatObj, hurtValue, hurtTypes, immuneHurt])
@@ -909,7 +910,7 @@
        tagBatObj.SetHP(remainHP)
        
        hurtObj = curSkill.AddHurtObj(dID)
        hurtObj.AddHurtType(ChConfig.HurtTYpe_Cure)
        hurtObj.AddHurtType(ChConfig.HurtAtkType_Cure)
        hurtObj.SetHurtHP(cureHP)
        hurtObj.SetLostHP(realCureHP)
        hurtObj.SetCurHP(tagBatObj.GetHP())
@@ -977,8 +978,9 @@
    if poisonCureOwner:
        GameWorld.DebugLog("本次治疗为毒奶: cureHP=%s" % cureHP)
        hurtValue = cureHP
        hurtTypes = pow(2, ChConfig.HurtTYpe_Cure)
        hurtTypes |= pow(2, ChConfig.HurtType_PoisonCureHurt)
        hurtTypes = pow(2, ChConfig.HurtAtkType_Cure)
        hurtTypes |= pow(2, ChConfig.HurtAtkType_Hurt)
        hurtTypes |= pow(2, ChConfig.HurtAtkType_PoisonCureHurt)
        hurtValue, hurtTypes, immuneHurt = CalcHurtWithBuff(turnFight, poisonCureOwner, defObj, hurtValue, hurtTypes)
        calcHurtResults = [[defObj, hurtValue, hurtTypes, immuneHurt]]
        DoSkillHurtHP(turnFight, poisonCureOwner, useSkill, calcHurtResults, "PoisonCOT")
@@ -988,7 +990,7 @@
        defObj.SetHP(remainHP)
        
        hurtObj = useSkill.AddHurtObj(defID)
        hurtObj.AddHurtType(ChConfig.HurtTYpe_Cure)
        hurtObj.AddHurtType(ChConfig.HurtAtkType_Cure)
        hurtObj.SetHurtHP(cureHP)
        hurtObj.SetLostHP(realCureHP)
        hurtObj.SetCurHP(defObj.GetHP())
@@ -1195,7 +1197,7 @@
    for hurtObj in useSkill.GetHurtObjListAll():
        if hurtObj.GetObjID() != tagID:
            continue
        if hurtObj.HaveHurtType(ChConfig.HurtType_Parry): # 格挡时可反击
        if hurtObj.HaveHurtType(ChConfig.HurtAtkType_Parry): # 格挡时可反击
            canAtkBack = True
            break
        
@@ -1289,39 +1291,39 @@
        tagObj = batObjMgr.getBatObj(hurtObjID)
        if not tagObj:
            continue
        if not hurtObj.HaveHurtType(ChConfig.HurtTYpe_Cure) and not hurtObj.HaveHurtType(ChConfig.HurtType_Immune) \
        if hurtObj.HaveHurtType(ChConfig.HurtAtkType_Hurt) and not hurtObj.HaveHurtType(ChConfig.HurtAtkType_Immune) \
            and (isTurnNormalSkill or isAngerSkill) and tagObj.IsAlive():
            __doSkillHurtAnger(tagObj, hurtObj.GetLostHP(), useSkill)
            
        if hurtObj.HaveHurtType(ChConfig.HurtType_Normal):
        if hurtObj.HaveHurtType(ChConfig.HurtAtkType_Hurt):
            totalHurtValue += hurtObj.GetHurtHP()
            if hurtObj.GetLostHP() > 0: # 有掉血的
                if hurtObjID not in beHurtObjIDList:
                    beHurtObjIDList.append(hurtObjID)
                    
        if hurtObj.HaveHurtType(ChConfig.HurtType_Miss):
        if hurtObj.HaveHurtType(ChConfig.HurtAtkType_Miss):
            if hurtObjID not in missObjIDList:
                missObjIDList.append(hurtObjID)
            DoHeroSpecialty(turnFight, tagObj, ChConfig.HeroSpecialty_Miss, relatedSkillID)
            
        if hurtObj.HaveHurtType(ChConfig.HurtType_Revive):
        if hurtObj.HaveHurtType(ChConfig.HurtAtkType_Revive):
            if tagObj not in reviveObjList:
                reviveObjList.append(tagObj)
                
        if hurtObj.HaveHurtType(ChConfig.HurtType_Immune):
        if hurtObj.HaveHurtType(ChConfig.HurtAtkType_Immune):
            if hurtObjID not in immuneObjIDList:
                immuneObjIDList.append(hurtObjID)
                
        if hurtObj.HaveHurtType(ChConfig.HurtType_Parry):
        if hurtObj.HaveHurtType(ChConfig.HurtAtkType_Parry):
            DoHeroSpecialty(turnFight, tagObj, ChConfig.HeroSpecialty_Parry, relatedSkillID)
            if hurtObjID not in parryObjIDList:
                parryObjIDList.append(hurtObjID)
                
        if hurtObj.HaveHurtType(ChConfig.HurtType_SuperHit):
        if hurtObj.HaveHurtType(ChConfig.HurtAtkType_SuperHit):
            if hurtObjID not in superHitObjIDList:
                superHitObjIDList.append(hurtObjID)
                
        if hurtObj.HaveHurtType(ChConfig.HurtType_Stun):
        if hurtObj.HaveHurtType(ChConfig.HurtAtkType_Stun):
            if hurtObjID not in stunObjIDList:
                stunObjIDList.append(hurtObjID)
                
@@ -1781,9 +1783,9 @@
        if GameWorld.CanHappen(missRate):
            GameWorld.DebugLog("闪避了! missRate=%s,dMissRate=%s,aMissRateDef=%s,missNum=%s" % (missRate, dMissRate, aMissRateDef, missNum))
            curSkill.SetTagMissNum(defID, missRate + 1)
            return 0, pow(2, ChConfig.HurtType_Miss)
            return 0, pow(2, ChConfig.HurtAtkType_Miss)
        
    hurtTypes = pow(2, ChConfig.HurtType_Normal)
    hurtTypes = pow(2, ChConfig.HurtAtkType_Hurt)
    
    isSuperHit, isParry, isStun = False, False, False
    aSuperDamPer, dSuperDamPerDef = 0, 0
@@ -1797,7 +1799,7 @@
        isStun = CanStun(turnFight, atkObj, defObj, curSkill) # 是否击晕
        
    if isSuperHit:
        hurtTypes |= pow(2, ChConfig.HurtType_SuperHit)
        hurtTypes |= pow(2, ChConfig.HurtAtkType_SuperHit)
        aSuperDamPer = IpyGameDataPY.GetFuncCfg("SuperHitCfg", 2) * 10000
        aSuperDamPer += atkObj.GetBatAttrValue(ChConfig.AttrID_SuperDamPer)
        aSuperDamPer += TurnPassive.GetTriggerEffectValue(turnFight, atkObj, defObj, ChConfig.AttrID_SuperDamPer, curSkill)
@@ -1806,14 +1808,14 @@
        GameWorld.DebugLog("aSuperDamPer=%s,dSuperDamPerDef=%s" % (aSuperDamPer, dSuperDamPerDef))
        
    if isParry:
        hurtTypes |= pow(2, ChConfig.HurtType_Parry)
        hurtTypes |= pow(2, ChConfig.HurtAtkType_Parry)
        
    if ignoreDef:
        GameWorld.DebugLog("无视防御/真实伤害!")
        hurtTypes |= pow(2, ChConfig.HurtType_IgnoreDef)
        hurtTypes |= pow(2, ChConfig.HurtAtkType_IgnoreDef)
        
    if isStun:
        hurtTypes |= pow(2, ChConfig.HurtType_Stun)
        hurtTypes |= pow(2, ChConfig.HurtAtkType_Stun)
        
    #参与运算的数值
    #rand = random.random()                #种子数 0~1
@@ -2040,7 +2042,7 @@
    
    hurtValue = int(hurtValue)
    if defObj.CheckInState(ChConfig.BatObjState_Wudi):
        hurtTypes |= pow(2, ChConfig.HurtType_Immune) # 添加免疫
        hurtTypes |= pow(2, ChConfig.HurtAtkType_Immune) # 添加免疫
        immuneHurt = hurtValue
        hurtValue = 0
        return hurtValue, hurtTypes, immuneHurt
@@ -2169,7 +2171,7 @@
        immuneHurt = max(int(immuneHurtDict.pop(tagID, 0)), 0) # 因为有标记-1值,所以加max
        # 主要目标的免疫标记外层已经处理,仅额外处理标记曹仁防护
        if caorenProtectID == tagID:
            hurtTypes |= pow(2, ChConfig.HurtType_CaorenProtect) # 标记受到曹仁防护,前端表现需要
            hurtTypes |= pow(2, ChConfig.HurtAtkType_CaorenProtect) # 标记受到曹仁防护,前端表现需要
        finalHurtResults.append([tagObj, finalHurt, hurtTypes, immuneHurt])
        finalHurtTotal = finalHurtTotal + finalHurt + immuneHurt
        GameWorld.DebugLog("得出主要目标分摊后的最终伤害: tagID=%s,finalHurt=%s,hurtTypes=%s,immuneHurt=%s,finalHurtTotal=%s" % (tagID, finalHurt, hurtTypes, immuneHurt, finalHurtTotal))
@@ -2181,11 +2183,11 @@
        tagObj = batObjMgr.getBatObj(tagID)
        if not tagObj:
            continue
        hurtTypes = pow(2, ChConfig.HurtType_Normal)
        hurtTypes = pow(2, ChConfig.HurtAtkType_Hurt)
        finalHurt = int(hurtValueDict.pop(tagID, 0))
        immuneHurt = max(int(immuneHurtDict.pop(tagID, 0)), 0)
        if immuneHurt > 0:
            hurtTypes |= pow(2, ChConfig.HurtType_Immune) # 添加免疫
            hurtTypes |= pow(2, ChConfig.HurtAtkType_Immune) # 添加免疫
        finalHurtTotal = finalHurtTotal + finalHurt + immuneHurt
        GameWorld.DebugLog("得出额外目标分摊后的最终伤害: tagID=%s,finalHurt=%s,hurtTypes=%s,immuneHurt=%s,finalHurtTotal=%s" % (tagID, finalHurt, hurtTypes, immuneHurt, finalHurtTotal))
        if finalHurt > 0 or immuneHurt > 0: # 额外目标有受伤或免疫才算
@@ -2496,7 +2498,7 @@
        GameWorld.DebugLog("    本次吸血为毒奶: suckHP=%s,hurtValue=%s" % (suckHP, hurtValue))
        DoLostHP(turnFight, atkObj, defObj, hurtValue, curSkill, "PoisonSuckBlood", hpCanNegative=True, immuneHurt=immuneHurt) # 吸血毒奶生命允许负值
        
        hurtObj.AddHurtType(ChConfig.HurtType_PoisonCureSuck)
        hurtObj.AddHurtType(ChConfig.HurtAtkType_PoisonCureSuck)
        hurtObj.SetSuckHP(hurtValue) # 如果前端有需要表现免疫吸血毒奶,可以判断吸血毒奶下该值为0代表免疫
        return