From cc207773cbedb51c20300a87c62529ace416b086 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期五, 19 九月 2025 19:23:35 +0800
Subject: [PATCH] 129 【战斗】战斗系统-服务端(无敌支持,免疫伤害、dot、控制;小怪技能;)

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py |  245 +++++++++++++++++++++++++++++++++++--------------
 1 files changed, 175 insertions(+), 70 deletions(-)

diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py
index 1aea3dd..3d2c457 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py
@@ -76,9 +76,16 @@
         # 可扩展其他目标选择,如复活技能没有死亡单位时则使用另外的效果
         return
     
+    objID = curBatObj.GetID()
+    oneActionUseCnt = turnFight.GetOneActionUseSkillCnt(objID)
+    if oneActionUseCnt >= 20:
+        GameWorld.ErrLog("单次行动累计使用技能达到上限! objID=%s,oneActionUseCnt=%s" % (objID, oneActionUseCnt), turnFight.playerID)
+        return
+    oneActionUseCnt = turnFight.SetOneActionUseSkillCnt(objID, oneActionUseCnt + 1)
+    
     bySkillID = bySkill.GetSkillID() if bySkill else 0
-    GameWorld.DebugLog("使用技能: curID=%s,skillID=%s,tagCnt=%s,batType=%s,bySkillID=%s" 
-                       % (curBatObj.GetID(), skillID, len(tagObjList), batType, bySkillID))
+    GameWorld.DebugLog("●使用技能: curID=%s,skillID=%s,tagCnt=%s,batType=%s,bySkillID=%s,HP:%s/%s,oneActionUseCnt=%s" 
+                       % (objID, skillID, len(tagObjList), batType, bySkillID, curBatObj.GetHP(), curBatObj.GetMaxHP(), oneActionUseCnt))
     # 以下为技能可以使用的处理,之后的逻辑默认技能使用成功
     
     poolMgr = ObjPool.GetPoolMgr()
@@ -86,18 +93,28 @@
     if isinstance(useSkill, IpyGameDataPY.IPY_Skill):
         usePoolSkill = True
         # 统一使用 BattleObj.PySkill
-        useSkill = poolMgr.acquire(BattleObj.PySkill, useSkill)
+        useSkill = poolMgr.acquire(BattleObj.PySkill, useSkill, objID)
         
     useSkill.ResetUseRec()
     useSkill.SetTagObjList(tagObjList)
     useSkill.SetBatType(batType)
     useSkill.SetBySkill(bySkill)
     
+    isTurnNormalSkill = SkillCommon.isTurnNormalSkill(useSkill)
+    if isTurnNormalSkill:
+        # 普攻追击时强制重新开始算连击
+        useSkill.ComboCheckStart(batType == ChConfig.TurnBattleType_Pursue)
+        
     curBatObj.ClearSkillTempAttr()
+    tagIDList = []
     for tagObj in tagObjList:
+        tagIDList.append(tagObj.GetID())
         tagObj.ClearSkillTempAttr()
         
-    objID = curBatObj.GetID()
+    # 有功能分类的技能都认为是主技能
+    if useSkill.GetFuncType():
+        curBatObj.SetMainTagIDList(tagIDList)
+        
     useTag = ""
     
     #这个技能是Buff
@@ -126,8 +143,10 @@
         turnFight.addBatPack(clientPack)
         
     # 处理反击 或 连击
-    DoCombo(turnFight, curBatObj, useSkill)
-    
+    if isTurnNormalSkill:
+        if not DoCombo(turnFight, curBatObj, useSkill):
+            useSkill.ComboInterrupt()
+            
     # 最后重置、回收对象
     useSkill.ResetUseRec()
     if usePoolSkill:
@@ -448,7 +467,7 @@
     
     skillID = useSkill.GetSkillID()
     for tagBatObj in useSkill.GetTagObjList():
-        cureHP = CalcCureHP(curBatObj, tagBatObj, useSkill, largeNum=True)
+        cureHP = CalcCureHP(turnFight, curBatObj, tagBatObj, useSkill, largeNum=True)
         if cureHP <= 0:
             continue
         
@@ -580,8 +599,7 @@
                 纵排: 优先前面的单位
     '''
     
-    if not SkillCommon.isTurnNormalSkill(useSkill):
-        #GameWorld.DebugLog("非普攻不处理反击连击")
+    if not useSkill.ComboEnable():
         return
     
     tagFriendly = useSkill.GetTagFriendly()
@@ -602,7 +620,7 @@
     if not tagObj:
         return
     
-    comboNum = atkObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnComboNum)
+    comboNum = useSkill.GetComboNum()
     aComboRate = atkObj.GetBatAttrValue(ChConfig.AttrID_ComboRate)
     aComboRate += TurnPassive.GetTriggerEffectValue(turnFight, atkObj, tagObj, ChConfig.AttrID_ComboRate, useSkill)
     
@@ -614,14 +632,14 @@
         return
     GameWorld.DebugLog("● %s 【连击】 happenRate=%s,aComboRate=%s,dComboRateDef=%s,comboNum=%s" 
                        % (TurnAttack.GetObjName(atkObj), happenRate, aComboRate, dComboRateDef, comboNum))
-    atkObj.SetDict(ChConfig.Def_Obj_Dict_TurnComboNum, comboNum + 1)
+    useSkill.SetComboNum(comboNum + 1)
     
     # 连击特长
     DoHeroSpecialty(turnFight, atkObj, ChConfig.HeroSpecialty_Combo, useSkill.GetSkillID())
     
     # 连击根据技能目标配置逻辑重新选择目标
     OnUseSkill(turnFight, atkObj, useSkill, batType=ChConfig.TurnBattleType_Combo)
-    return
+    return True
 
 def __getCanAtkBackSkill(useSkill, tagObj):
     ## 获取是否可反击及反击技能
@@ -659,7 +677,7 @@
 def DoBeAttackResult(turnFight, curObj, useSkill, isUseSkill=False):
     '''被攻击结果
     @param curObj: 施法方或buff归属方
-    @param isUseSkill: 是否是直接使用技能的攻击结果
+    @param isUseSkill: 是否是直接使用技能的攻击结果,否则视为持续性的
     '''
     
     curID = curObj.GetID()
@@ -702,26 +720,44 @@
         TurnAttack.SetObjKilled(turnFight, curObj)
         
     # 统计伤血,可能单个技能对同一目标造成多次伤害
+    totalHurtValue = 0
     isSuperHit, isStun, isSuckHP = False, False, False
-    missObjIDList = []
+    missObjIDList, immuneObjIDList = [], []
     for hurtObj in useSkill.GetHurtObjList():
         hurtObjID = hurtObj.GetObjID()
         tagObj = batObjMgr.getBatObj(hurtObjID)
         if not tagObj:
             continue
-        if not hurtObj.HaveHurtType(ChConfig.HurtTYpe_Recovery) and (isTurnNormalSkill or isAngerSkill) and tagObj.IsAlive():
+        if not hurtObj.HaveHurtType(ChConfig.HurtTYpe_Recovery) and not hurtObj.HaveHurtType(ChConfig.HurtType_Immune) \
+            and (isTurnNormalSkill or isAngerSkill) and tagObj.IsAlive():
             __doSkillHurtAnger(tagObj, hurtObj.GetLostHP(), useSkill)
+            
+        if hurtObj.HaveHurtType(ChConfig.HurtType_Normal):
+            totalHurtValue += hurtObj.GetHurtHP()
+            
         if hurtObj.HaveHurtType(ChConfig.HurtType_Miss):
-            missObjIDList.append(hurtObjID)
+            if hurtObjID not in missObjIDList:
+                missObjIDList.append(hurtObjID)
             DoHeroSpecialty(turnFight, tagObj, ChConfig.HeroSpecialty_Miss, relatedSkillID)
+            
+        if hurtObj.HaveHurtType(ChConfig.HurtType_Immune):
+            if hurtObjID not in immuneObjIDList:
+                immuneObjIDList.append(hurtObjID)
+                
         if hurtObj.HaveHurtType(ChConfig.HurtType_Parry):
             DoHeroSpecialty(turnFight, tagObj, ChConfig.HeroSpecialty_Parry, relatedSkillID)
+            
         if hurtObj.HaveHurtType(ChConfig.HurtType_SuperHit):
             isSuperHit = True
+            
         if hurtObj.HaveHurtType(ChConfig.HurtType_Stun):
             isStun = True
+            
         if hurtObj.GetSuckHP() > 0:
             isSuckHP = True
+            
+    curObj.SetLastHurtValue(totalHurtValue) # 记录最后一次总伤害
+    
     # 群攻只触发一次特长
     if isSuperHit:
         DoHeroSpecialty(turnFight, curObj, ChConfig.HeroSpecialty_SuperHit, relatedSkillID)
@@ -735,9 +771,9 @@
     if curPlayer and curObj and curObj.GetOwnerID() == curPlayer.GetPlayerID():
         FBLogic.OnPlayerLineupAttackResult(curPlayer, curObj, killObjList, useSkill, turnFight.mapID, turnFight.funcLineID)
         
+    effIgnoreObjIDList = missObjIDList + immuneObjIDList
     # 优先触发本技能额外效果,注:仅该技能释放后该技能的额外效果视为主技能的效果,优先级最高
-    if isUseSkill:
-        __DoCurSkillEff(turnFight, curObj, useSkill, missObjIDList)
+    __DoCurSkillEff(turnFight, curObj, useSkill, effIgnoreObjIDList, isUseSkill)
         
     # ========== 以下触发被动 ==========
     
@@ -749,8 +785,7 @@
         
     for tagObj in useSkill.GetTagObjList():
         tagID = tagObj.GetID()
-        if tagID == curID or tagID in missObjIDList:
-            # 自己或对方闪避了不再触发被动
+        if tagID in effIgnoreObjIDList:
             continue
         
         # 直接攻击
@@ -758,6 +793,16 @@
             TurnPassive.OnTriggerPassiveEffect(turnFight, curObj, ChConfig.TriggerWay_AttackOverDirect, tagObj, connSkill=useSkill)
             TurnPassive.OnTriggerPassiveEffect(turnFight, tagObj, ChConfig.TriggerWay_BeAttackedDirect, curObj, connSkill=useSkill)
             
+        # 使用技能后
+        if isUseSkill:
+            TurnPassive.OnTriggerPassiveEffect(turnFight, curObj, ChConfig.TriggerWay_UseSkillOver, tagObj, connSkill=useSkill)
+            
+    if killObjList:
+        tagObj = killObjList[0]
+        TurnPassive.OnTriggerPassiveEffect(turnFight, curObj, ChConfig.TriggerWay_KillOneObj, tagObj, connSkill=useSkill)
+    for tagObj in killObjList:
+        TurnPassive.OnTriggerPassiveEffect(turnFight, curObj, ChConfig.TriggerWay_KillTagObj, tagObj, connSkill=useSkill)
+        
     return
 
 def __doCostZhanchui(turnFight, curBatObj, useSkill):
@@ -846,24 +891,28 @@
     Sync_PropertyRefreshView(turnFight, gameObj, ChConfig.AttrID_XP, updXP, addXP, diffType=1, relatedSkillID=relatedSkillID)
     return
 
-def __DoCurSkillEff(turnFight, curObj, useSkill, missObjIDList):
+def __DoCurSkillEff(turnFight, curObj, useSkill, effIgnoreObjIDList, isUseSkill):
     ## 执行本技能/buff释放后额外效果
     for index in xrange(useSkill.GetEffectCount()):
         curEffect = useSkill.GetEffect(index)
-        if curEffect.GetTriggerWay() != ChConfig.TriggerWay_CurSkillEff:
-            continue
-        
+        triggerWay = curEffect.GetTriggerWay()
+        if isUseSkill:
+            if triggerWay != ChConfig.TriggerWay_CurSkillEff:
+                continue
+        else:
+            if triggerWay != ChConfig.TriggerWay_CurSkillEffLst:
+                continue
+            
         effID = curEffect.GetEffectID()
-        GameWorld.DebugLog("执行额外技能效果: %s, missObjIDList=%s" % (effID, missObjIDList))
+        GameWorld.DebugLog("◆执行额外技能效果: %s, triggerWay=%s,effIgnoreObjIDList=%s" % (effID, triggerWay, effIgnoreObjIDList))
         if effID == 5010:
             # 额外技能效果
-            __doUseEnhanceSkill(turnFight, curObj, useSkill, curEffect, missObjIDList)
+            __doUseEnhanceSkill(turnFight, curObj, useSkill, curEffect, effIgnoreObjIDList)
             continue
         
         for tagObj in useSkill.GetTagObjList():
             tagID = tagObj.GetID()
-            GameWorld.DebugLog("    tagID=%s" % (tagID))
-            if tagID in missObjIDList:
+            if tagID in effIgnoreObjIDList:
                 # 闪避了不触发
                 continue
             
@@ -871,7 +920,7 @@
             
     return
 
-def __doUseEnhanceSkill(turnFight, curBatObj, useSkill, curEffect, missObjIDList):
+def __doUseEnhanceSkill(turnFight, curBatObj, useSkill, curEffect, effIgnoreObjIDList):
     ## 执行主技能的额外技能效果
     #if useSkill.GetBatType() == ChConfig.TurnBattleType_Enhance:
     #    #GameWorld.DebugLog("自身为额外触发的技能不再触发额外技能! skillID=%s" % useSkill.GetSkillID())
@@ -896,8 +945,8 @@
             if not tagObj.IsAlive():
                 GameWorld.DebugLog("    已被击杀不触发: tagID=%s" % (tagID))
                 continue
-            if tagID in missObjIDList:
-                GameWorld.DebugLog("    闪避的不触发: tagID=%s" % (tagID))
+            if tagID in effIgnoreObjIDList:
+                GameWorld.DebugLog("    闪避或免疫的不触发: tagID=%s" % (tagID))
                 continue
             if checkInStateList:
                 if not tagObj.CheckInState(checkInStateList):
@@ -984,7 +1033,7 @@
     
     else:
         hurtValue, hurtTypes = CalcHurtHP(turnFight, atkObj, defObj, curSkill, atkSkillValue, atkSkillPer)
-        hurtValue, realHurtHP = CalcHurtHPWithBuff(turnFight, atkObj, defObj, curSkill, hurtValue)
+        hurtValue, realHurtHP, hurtTypes = CalcHurtHPWithBuff(turnFight, atkObj, defObj, curSkill, hurtValue, hurtTypes)
         
         #伤害结构体
         hurtObj.SetHurtTypes(hurtTypes)
@@ -1015,6 +1064,7 @@
     skillID = curSkill.GetSkillID()
     pmType = GetPMType(atkObj, curSkill)
     ignoreDef = IsIgnoreDef(curSkill)
+    batType = curSkill.GetBatType()
     
     changeHurtType = TurnPassive.GetTriggerEffectValue(turnFight, atkObj, defObj, ChConfig.PassiveEff_ChangeHurtType, curSkill)
     if changeHurtType == 1:
@@ -1024,41 +1074,41 @@
     atkID = atkObj.GetID()
     defID = defObj.GetID()
     
+    calcType = curSkill.GetCalcType() # 伤害计算方式 0-按攻击
     isTurnNormalSkill = SkillCommon.isTurnNormalSkill(curSkill)
     isAngerSkill = SkillCommon.isAngerSkill(curSkill)
     isDot = ("damageoftime" in kwargs)
     angerOverflow = 0 # 怒气溢出值
     
-    mustHit = False
+    mustHit = False # 是否必命中
     if isAngerSkill:
         mustHit = True
         curXP = atkObj.GetXP()
         angerOverflow = max(atkObj.GetXP() - IpyGameDataPY.GetFuncCfg("AngerXP", 2), 0)
         GameWorld.DebugLog("XP必命中! curXP=%s,angerOverflow=%s" % (curXP, angerOverflow))
         
-    if isDot:
-        mustHit = True
-        
     #命中公式 攻击方类型不同,公式不同
-    if not mustHit:
+    if isTurnNormalSkill and not mustHit:
         aMissRateDef = atkObj.GetBatAttrValue(ChConfig.AttrID_MissRateDef) #atkObj.GetHit() # 抗闪避率 - 命中
         dMissRate = defObj.GetBatAttrValue(ChConfig.AttrID_MissRate) # 闪避率
-        missNum = defObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnMissNum)
+        missNum = curSkill.GetTagMissNum(defID)
         missRate = eval(IpyGameDataPY.GetFuncCompileCfg("MissCfg", 1))
         if GameWorld.CanHappen(missRate):
             GameWorld.DebugLog("闪避了! missRate=%s,dMissRate=%s,aMissRateDef=%s,missNum=%s" % (missRate, dMissRate, aMissRateDef, missNum))
-            defObj.SetDict(ChConfig.Def_Obj_Dict_TurnMissNum, missRate + 1)
+            curSkill.SetTagMissNum(defID, missRate + 1)
             return 0, pow(2, ChConfig.HurtType_Miss)
         
     hurtTypes = pow(2, ChConfig.HurtType_Normal)
     
-    #calcType = curSkill.GetCalcType() 目前暂时按攻击算伤害,之后可以扩展其他
-    
     isSuperHit, isParry, isStun = False, False, False
     aSuperDamPer, dSuperDamPerDef = 0, 0
+    # 暴击(dot除外)
     if not isDot:
         isSuperHit = CanSuperHit(turnFight, atkObj, defObj, curSkill) # 是否暴击
-        isParry = (isTurnNormalSkill and CanParry(turnFight, atkObj, defObj, curSkill)) # 是否格挡,仅针对普攻
+        
+    # 闪避、击晕、格挡
+    if isTurnNormalSkill:
+        isParry = CanParry(turnFight, atkObj, defObj, curSkill) # 是否格挡
         isStun = CanStun(turnFight, atkObj, defObj, curSkill) # 是否击晕
         
     if isSuperHit:
@@ -1078,10 +1128,12 @@
     #参与运算的数值
     #rand = random.random()                #种子数 0~1
     
-    aAtk = atkObj.GetBatAttrValue(ChConfig.AttrID_Atk) # 攻击方最大攻击
+    aAtk = atkObj.GetAtk() # 攻击方最大攻击
     
     dHP = defObj.GetHP()
-    dDef = 0 if ignoreDef else defObj.GetBatAttrValue(ChConfig.AttrID_Def) # 防守方防御力
+    dDef = 0 if ignoreDef else defObj.GetDef() # 防守方防御力
+    
+    atkSkillPer += TurnPassive.GetTriggerEffectValue(turnFight, atkObj, defObj, ChConfig.PassiveEff_AddSkillPer, curSkill)
     
     aFinalDamPer = atkObj.GetBatAttrValue(ChConfig.AttrID_FinalDamPer) # 最终加成
     dFinalDamPerDef = defObj.GetBatAttrValue(ChConfig.AttrID_FinalDamPerDef) # 最终减伤
@@ -1107,6 +1159,14 @@
         aPMDamPer = atkObj.GetBatAttrValue(ChConfig.AttrID_PhyDamPer) 
         dPMDamPerDef = defObj.GetBatAttrValue(ChConfig.AttrID_PhyDamPerDef)
         
+    aComboDamPer = 0 # 连击增伤
+    if batType == ChConfig.TurnBattleType_Combo:
+        aComboDamPer = atkObj.GetBatAttrValue(ChConfig.AttrID_ComboDamPer)
+        
+    aPursueDamPer = 0 # 追击增伤
+    if batType == ChConfig.TurnBattleType_Pursue:
+        aPursueDamPer = atkObj.GetBatAttrValue(ChConfig.AttrID_PursueDamPer)
+        
     # 所有万分率参数统一除10000.0
     atkSkillPer /= 10000.0
     aNormalSkillPer /= 10000.0
@@ -1120,20 +1180,27 @@
     dSuperDamPerDef /= 10000.0
     aFinalDamPer /= 10000.0
     dFinalDamPerDef /= 10000.0
+    aComboDamPer /= 10000.0
+    aPursueDamPer /= 10000.0
     
-    GameWorld.DebugLog("伤血计算: atkID=%s,defID=%s,skillID=%s,atkSkillPer=%s,aAtk=%s,dDef=%s,dHP=%s,hurtTypes=%s,aAddSkillPer=%s" 
-                       % (atkID, defID, skillID, atkSkillPer, aAtk, dDef, dHP, hurtTypes, aAddSkillPer))
+    if calcType != ChConfig.Def_Calc_Attack:
+        aAtk = GetCalcBaseValue(calcType, atkObj, defObj)
+    GameWorld.DebugLog("伤血计算: atkID=%s,defID=%s,skillID=%s,atkSkillPer=%s,calcType=%s,aAtk=%s,dDef=%s,dHP=%s,hurtTypes=%s,aAddSkillPer=%s" 
+                       % (atkID, defID, skillID, atkSkillPer, calcType, aAtk, dDef, dHP, hurtTypes, aAddSkillPer))
     
     # 持续性伤害
-    if isDot:
-        hurtValue = eval(IpyGameDataPY.GetFuncCompileCfg("DOTFormula", 1))
-        GameWorld.DebugLog("    持续技能伤害=%s" % (hurtValue))
-    elif isTurnNormalSkill:
+    if isTurnNormalSkill:
         hurtValue = eval(IpyGameDataPY.GetFuncCompileCfg("HurtFormula", 1))
         GameWorld.DebugLog("    普攻技能伤害=%s" % (hurtValue))
     elif isAngerSkill:
         hurtValue = eval(IpyGameDataPY.GetFuncCompileCfg("HurtFormula", 2))
         GameWorld.DebugLog("    怒气技能伤害=%s" % (hurtValue))
+    elif isDot:
+        hurtValue = eval(IpyGameDataPY.GetFuncCompileCfg("DOTFormula", 1))
+        GameWorld.DebugLog("    持续技能伤害=%s" % (hurtValue))
+    elif calcType != ChConfig.Def_Calc_Attack:
+        hurtValue = eval(IpyGameDataPY.GetFuncCompileCfg("CalcTypeFormula", 1))
+        GameWorld.DebugLog("    非按攻击力伤害=%s,calcType=%s,aAtk=%s" % (hurtValue, calcType, aAtk))
     else:
         hurtValue = eval(IpyGameDataPY.GetFuncCompileCfg("HurtFormula", 4))
         GameWorld.DebugLog("    其他伤害=%s" % (hurtValue))
@@ -1147,6 +1214,13 @@
     if multiValue and multiValue != 1:
         hurtValue = int(hurtValue * multiValue)
         GameWorld.DebugLog("    伤害倍值: hurtValue=%s,multiValue=%s" % (hurtValue, multiValue))
+        
+    hurtAtkPerMax = curSkill.GetHurtAtkPerMax() # 最大万分比,限制最终伤害不超过攻击力万分率
+    if hurtAtkPerMax:
+        aAtk = atkObj.GetAtk()
+        hurtValueMax = aAtk * hurtAtkPerMax / 10000.0
+        hurtValue = min(hurtValue, hurtValueMax)
+        GameWorld.DebugLog("    伤害最高限制: hurtValue=%s,hurtAtkPerMax=%s,aAtk=%s" % (hurtValue, hurtAtkPerMax, aAtk))
         
     hurtValue = max(1, int(hurtValue)) # 负值、保底防范,放最后
     return hurtValue, hurtTypes
@@ -1168,40 +1242,61 @@
     happenRate = eval(IpyGameDataPY.GetFuncCompileCfg("StunCfg", 1))
     if not GameWorld.CanHappen(happenRate):
         return False
-    GameWorld.DebugLog("击晕了: happenRate=%s,aStunRate=%s,dStunRateDef=%s" % (happenRate, aStunRate, dStunRateDef))
     stunSkillID = IpyGameDataPY.GetFuncCfg("StunCfg", 2)
-    TurnBuff.DoAddBuffBySkillID(turnFight, defObj, stunSkillID, atkObj, curSkill, afterLogic=True)
-    return True
+    if TurnBuff.DoAddBuffBySkillID(turnFight, defObj, stunSkillID, atkObj, curSkill, afterLogic=True):
+        GameWorld.DebugLog("击晕了: happenRate=%s,aStunRate=%s,dStunRateDef=%s" % (happenRate, aStunRate, dStunRateDef))
+        return True
+    return False
 
 def CanParry(turnFight, atkObj, defObj, curSkill):
     if defObj.IsInControlled():
         #被控制无法格挡
         return False
     
+    defID = defObj.GetID()
     # 格挡印记
     buffMgr = defObj.GetBuffManager()
     parryYJBuff = buffMgr.FindBuffByState(ChConfig.BatObjState_ParryYJ)
     if parryYJBuff and parryYJBuff.GetLayer():
         GameWorld.DebugLog("格挡印记格挡了: buffID=%s,buffLayer=%s" % (parryYJBuff.GetBuffID(), parryYJBuff.GetLayer()))
-        TurnBuff.DecBuffLayer(turnFight, defObj, parryYJBuff, 1, curSkill.GetSkillID())
+        TurnBuff.DoBuffLayerChange(turnFight, defObj, parryYJBuff, parryYJBuff.GetLayer() - 1, curSkill)
         return True
     
     aParryRateDef = atkObj.GetBatAttrValue(ChConfig.AttrID_ParryRateDef)
     dParryRate = defObj.GetBatAttrValue(ChConfig.AttrID_ParryRate)
-    parryNum = defObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnParryNum)
+    parryNum = curSkill.GetTagParryNum(defID)
     happenRate = eval(IpyGameDataPY.GetFuncCompileCfg("ParryCfg", 1))
     if GameWorld.CanHappen(happenRate):
         GameWorld.DebugLog("格挡了: happenRate=%s,aParryRateDef=%s,dParryRate=%s,parryNum=%s" % (happenRate, aParryRateDef, dParryRate, parryNum))
-        defObj.SetDict(ChConfig.Def_Obj_Dict_TurnParryNum, parryNum + 1)
+        curSkill.SetTagParryNum(defID, parryNum + 1)
         return True
     return False
 
-def CalcHurtHPWithBuff(turnFight, atkObj, defObj, curSkill, hurtValue):
+def CalcHurtHPWithBuff(turnFight, atkObj, defObj, curSkill, hurtValue, hurtTypes=0):
     ## 计算伤害后,因各种buff和状态的影响处理
-    # @return: hurtValue, realHurtHP
+    # @return: hurtValue, realHurtHP, hurtTypes
     
     if hurtValue <= 0:
-        return 0, 0
+        return 0, 0, hurtTypes
+    
+    if defObj.CheckInState(ChConfig.BatObjState_Wudi):
+        hurtTypes |= pow(2, ChConfig.HurtType_Immune) # 添加免疫
+        buffMgr = defObj.GetBuffManager()
+        for index in range(buffMgr.GetBuffCount()):
+            buff = buffMgr.GetBuffByIndex(index)
+            if not buff:
+                continue
+            skillData = buff.GetSkillData()
+            if skillData.GetCurBuffState() != ChConfig.BatObjState_Wudi:
+                continue
+            # 记录免疫的积攒伤害
+            buffValue = buff.GetValue1() + buff.GetValue2() * ChConfig.Def_PerPointValue
+            updBuffValue = buffValue + hurtValue
+            buff.SetValue1(updBuffValue % ChConfig.Def_PerPointValue)
+            buff.SetValue2(updBuffValue / ChConfig.Def_PerPointValue)
+            GameWorld.DebugLog("    无敌盾免疫伤害: defID=%s,buffID=%s,skillID=%s,updBuffValue=%s" 
+                               % (defObj.GetID(), buff.GetBuffID(), skillData.GetSkillID(), updBuffValue))
+        return 0, 0, hurtTypes
     
     # 减伤盾减伤, 会改变 hurtValue
     hurtValue = max(0, hurtValue)
@@ -1243,7 +1338,7 @@
                 buff.SetValue2(updShieldValue / ChConfig.Def_PerPointValue)
                 curSkill.AddAfterLogic(ChConfig.AfterLogic_SyncBuff, [defObj, buff, atkObj, "ReduceShieldValue"])
                 
-    return hurtValue, max(0, realHurtHP)
+    return hurtValue, max(0, realHurtHP), hurtTypes
 
 def CalcBounceHP(turnFight, atkObj, defObj, hurtObj, curSkill):
     '''计算反弹反弹伤害
@@ -1256,8 +1351,9 @@
         return
     
     GameWorld.DebugLog("    反弹伤害=%s,%s/%s" % (bounceHP, atkObj.GetHP(), atkObj.GetMaxHP()))
-    bounceHP, realBounceHP = CalcHurtHPWithBuff(turnFight, defObj, atkObj, curSkill, bounceHP)
+    bounceHP, realBounceHP, _ = CalcHurtHPWithBuff(turnFight, defObj, atkObj, curSkill, bounceHP)
     if bounceHP <= 0:
+        GameWorld.DebugLog("        bounceHP=%s" % (bounceHP))
         return
     hurtObj.SetBounceHP(bounceHP)
     
@@ -1296,7 +1392,7 @@
     TurnAttack.AddTurnObjCureHP(atkObj, atkObj, suckHP, cureHP)
     return
 
-def CalcCureHP(userObj, tagObj, curSkill, largeNum=False):
+def CalcCureHP(turnFight, userObj, tagObj, curSkill, largeNum=False):
     ''' 计算治疗值
     '''
     cureType = curSkill.GetCalcType()
@@ -1305,7 +1401,7 @@
     
     cureBaseValue = GetCalcBaseValue(cureType, userObj, tagObj)
     
-    #skillPer += PassiveBuffEffMng.GetPassiveSkillValueByTriggerType(userObj, None, curSkill, ChConfig.TriggerType_AddHP)
+    skillPer += TurnPassive.GetTriggerEffectValue(turnFight, userObj, tagObj, ChConfig.PassiveEff_AddSkillPer, curSkill)
     
     # 回合制
     curePer = 0 # 治疗加成
@@ -1340,8 +1436,8 @@
         baseValue = curObj.GetAtk()
     elif calcType == ChConfig.Def_Calc_MaxHP:
         baseValue = curObj.GetMaxHP()
-    #elif cureType == ChConfig.Def_Calc_HurtValue:
-    #    baseValue = GameObj.GetLastHurtValue(userObj)
+    elif calcType == ChConfig.Def_Calc_LastHurt:
+        baseValue = curObj.GetLastHurtValue()
     elif calcType == ChConfig.Def_Calc_TagMaxHP:
         baseValue = 0 if not tagObj else tagObj.GetMaxHP()
     return baseValue
@@ -1361,26 +1457,26 @@
     atkObj = buffOwner
     defObj = batObj
     
+    atkID = ownerID
     defID = defObj.GetID()
     tagObjList = [defObj]
     
     poolMgr = ObjPool.GetPoolMgr()
-    useSkill = poolMgr.acquire(BattleObj.PySkill, skillIpyData)
+    useSkill = poolMgr.acquire(BattleObj.PySkill, skillIpyData, atkID)
     useSkill.SetTagObjList(tagObjList)
     useSkill.ClearHurtObj()
     hurtObj = useSkill.AddHurtObj(defID)
     
     dHP = defObj.GetHP()
-    GameWorld.DebugLog("结算dot: defID=%s,buffID=%s,skillID=%s,ownerID=%s,hurtValue=%s,hurtTypes=%s,dHP=%s" 
-                       % (defID, buffID, skillID, ownerID, hurtValue, hurtTypes, dHP))
-    hurtValue, realHurtHP = CalcHurtHPWithBuff(turnFight, atkObj, defObj, useSkill, hurtValue)
+    GameWorld.DebugLog("结算dot: atkID=%s,defID=%s,buffID=%s,skillID=%s,ownerID=%s,hurtValue=%s,hurtTypes=%s,dHP=%s" 
+                       % (atkID, defID, buffID, skillID, ownerID, hurtValue, hurtTypes, dHP))
+    hurtValue, realHurtHP, hurtTypes = CalcHurtHPWithBuff(turnFight, atkObj, defObj, useSkill, hurtValue, hurtTypes)
     
     # dot的反弹、吸血待定
     
     remainHP = max(0, dHP - realHurtHP) # 剩余血量
     lostHP = dHP - remainHP # 实际掉血量
     defObj.SetHP(remainHP)
-    
     GameWorld.DebugLog("    hurtValue=%s,realHurtHP=%s,lostHP=%s,%s/%s" % (hurtValue, realHurtHP, lostHP, defObj.GetHP(), defObj.GetMaxHP()))
     
     hurtObj.SetHurtTypes(hurtTypes)
@@ -1421,6 +1517,15 @@
         hurt.SuckHP = min(hurtObj.GetSuckHP(), ChConfig.Def_UpperLimit_DWord)
         hurt.BounceHP = min(hurtObj.GetBounceHP(), ChConfig.Def_UpperLimit_DWord)
         clientPack.HurtList.append(hurt)
+    if not clientPack.HurtList:
+        for tagObj in useSkill.GetTagObjList():
+            tagID = tagObj.GetID()
+            hurt = poolMgr.acquire(ChPyNetSendPack.tagSCUseSkillHurt)
+            hurt.ObjID = tagID
+            hurt.CurHP = tagObj.GetHP() % ChConfig.Def_PerPointValue
+            hurt.CurHPEx = tagObj.GetHP() / ChConfig.Def_PerPointValue
+            clientPack.HurtList.append(hurt)
+            
     clientPack.HurtCount = len(clientPack.HurtList)
     turnFight.addBatPack(clientPack)
     return

--
Gitblit v1.8.0