From 3beded4a9ae2e126158d89a4e7048f595ea0bc1b Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期一, 25 八月 2025 12:01:24 +0800
Subject: [PATCH] 129 【战斗】战斗系统-服务端(技能触发来源触发逻辑优化;增加承伤盾支持,0428通知buff相关值;增加嘲讽支持,优化技能选择目标逻辑;增加连击、反击、格挡、暴击、通用击晕支持;)

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5001.py |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py                      |   16 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py                    |  226 -------
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py                      |  739 ++++++++++++++++++++-------
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5010.py |   69 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuff.py                       |  116 +++-
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5011.py |   58 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BattleObj.py                     |  187 ++++--
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py                        |   32 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnPassive.py                    |   34 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuffs/BuffAtkType_1001.py     |   11 
 PySysDB/PySysDBPY.h                                                                                         |   10 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py         |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py                             |   66 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuffs/BuffAtkType_1003.py     |   27 +
 15 files changed, 1,069 insertions(+), 528 deletions(-)

diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index 447571b..8811fba 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -79,22 +79,21 @@
 	DWORD		EffectID1;	//效果ID1
 	list		EffectValues1;	//效果值列表1
 	BYTE		TriggerWay1;	//触发方式
-	BYTE		TriggerSrc1;	//触发来源
+	BYTE		TriggerSrc1;	//有效来源
 	list		TriggerParams1;	//触发参数
 	DWORD		EffectID2;	//效果ID2
 	list		EffectValues2;	//效果值列表2
 	BYTE		TriggerWay2;	//触发方式
-	BYTE		TriggerSrc2;	//触发来源
+	BYTE		TriggerSrc2;	//有效来源
 	list		TriggerParams2;	//触发参数
 	DWORD		EffectID3;	//效果ID3
 	list		EffectValues3;	//效果值列表3
 	BYTE		TriggerWay3;	//触发方式
-	BYTE		TriggerSrc3;	//触发来源
+	BYTE		TriggerSrc3;	//有效来源
 	list		TriggerParams3;	//触发参数
-	DWORD		ConnSkill;	//关联技能
 	WORD		CoolDownTime;	//技能冷却时间
 	list		IgnoreStates;	//无视限制列表
-	list		BuffStates;	//Buff状态值
+	BYTE		CurBuffState;	//Buff状态值
 	WORD		LastTime;	//持续时间
 	BYTE		LayerCnt;	//Buff层数
 	BYTE		LayerMax;	//最大层数
@@ -102,6 +101,7 @@
 	DWORD		DieContinue;	//Buff死亡存在
 	list		EnhanceSkillList;	//触发技能ID列表
 	DWORD		FightPower;	//技能战斗力
+	char		SkillMotionName; //技能动作名
 };
 
 //武将表
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BattleObj.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BattleObj.py
index 55da264..89f6bc2 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BattleObj.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/BattleObj.py
@@ -33,41 +33,45 @@
     def __init__(self, batObj):
         self._batObj = batObj
         # 被影响的技能ID: 0为所有技能
-        self._AffectSkillDict = {} # 被动技能 {(触发方式, 被影响的技能ID):{技能ID:[effID, ...], ...}, ...}
-        self._AffectBuffDict = {} # 被动buff {(触发方式, 被影响的技能ID):{buffID:[effID, ...], ...}, ...}
+        self._AffectSkillDict = {} # 被动技能 {(触发方式, 有效来源):{技能ID:[effID, ...], ...}, ...}
+        self._AffectBuffDict = {} # 被动buff {(触发方式, 有效来源):{buffID:[effID, ...], ...}, ...}
         return
     
-    def GetPassiveEffByTrigger(self, triggerWay, connSkill=None):
+    def GetPassiveEffByTrigger(self, triggerWay, connSkillTypeID=0):
         '''获取可触发的效果列表,技能跟buff根据触发优先级按顺序触发,优先级越高越先执行,相同时技能优先
                         优先级之后有需要再扩展
         @return: [["skill/buff", skillID/buffID, effIDList], ...]
         '''
-        connSkillID = connSkill.GetSkillTypeID() if connSkill else 0
         effList = []
-        # 技能
-        key = (triggerWay, connSkillID)
-        if key in self._AffectSkillDict:
-            effDict = self._AffectSkillDict[key]
-            for skillID, effIDList in effDict.items():
-                effList.append(["skill", skillID, effIDList])
-        if connSkillID != 0:
-            key = (triggerWay, 0)
-            effDict = self._AffectSkillDict.get(key, {})
-            for skillID, effIDList in effDict.items():
-                effList.append(["skill", skillID, effIDList])
-                
-        # buff
-        key = (triggerWay, connSkillID)
-        if key in self._AffectBuffDict:
-            effDict = self._AffectBuffDict[key]
-            for buffID, effIDList in effDict.items():
-                effList.append(["buff", buffID, effIDList])
-        if connSkillID != 0:
-            key = (triggerWay, 0)
-            effDict = self._AffectBuffDict.get(key, {})
-            for buffID, effIDList in effDict.items():
-                effList.append(["buff", buffID, effIDList])
-                
+        
+        # 优先取关联技能的
+        if connSkillTypeID and connSkillTypeID not in [ChConfig.TriggerSrc_Skill, ChConfig.TriggerSrc_Buff]:
+            # 技能
+            key = (triggerWay, connSkillTypeID)
+            if key in self._AffectSkillDict:
+                effDict = self._AffectSkillDict[key]
+                for skillID, effIDList in effDict.items():
+                    effList.append(["skill", skillID, 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])
+                    
+        # 所有技能有效的
+        key = (triggerWay, ChConfig.TriggerSrc_Skill)
+        effDict = self._AffectSkillDict.get(key, {})
+        for skillID, effIDList in effDict.items():
+            effList.append(["skill", skillID, effIDList])
+            
+        # 所有buff有效的
+        key = (triggerWay, ChConfig.TriggerSrc_Buff)
+        effDict = self._AffectBuffDict.get(key, {})
+        for buffID, effIDList in effDict.items():
+            effList.append(["buff", buffID, effIDList])
+            
         return effList
     
     def RefreshSkillPassiveEffect(self):
@@ -91,16 +95,16 @@
         ## 添加技能被动效果
         triggerWay = effect.GetTriggerWay()
         triggerSrc = effect.GetTriggerSrc()
-        if not triggerWay or triggerSrc != 1:
+        if not triggerWay:
+            return
+        if triggerSrc == ChConfig.TriggerSrc_Buff:
+            # buff有效的不加进来
             return
         
         skillID = curSkill.GetSkillID()
-        connSkillID = curSkill.GetConnSkill()
-        #priority = curSkill.GetPriority()
-        
         effectID = effect.GetEffectID()
         
-        key = (triggerWay, connSkillID)
+        key = (triggerWay, triggerSrc)
         if key not in self._AffectSkillDict:
             self._AffectSkillDict[key] = {}
         effDict = self._AffectSkillDict[key]
@@ -133,15 +137,16 @@
         '''
         triggerWay = effect.GetTriggerWay()
         triggerSrc = effect.GetTriggerSrc()
-        if not triggerWay or triggerSrc != 2:
+        if not triggerWay:
+            return
+        if triggerSrc == ChConfig.TriggerSrc_Skill:
+            # 技能有效的不加进来
             return
         
         buffID = buff.GetBuffID()
-        connSkillID = skillData.GetConnSkill()
-        #priority = skillData.GetPriority()
-        
         effectID = effect.GetEffectID()
-        key = (triggerWay, connSkillID)
+        
+        key = (triggerWay, triggerSrc)
         if key not in self._AffectBuffDict:
             self._AffectBuffDict[key] = {}
         effDict = self._AffectBuffDict[key]
@@ -170,7 +175,8 @@
     def Clear(self):
         self._objID = 0
         self._hurtTypes = 0 # 本次伤血类型,如闪避、暴击、格挡等,通过二进制或运算得到最终值,支持多种同时出现,如暴击的同时被格挡
-        self._hurtHP = 0 # 伤血值
+        self._hurtHP = 0 # 公式最终计算的伤害值,一般用于飘血
+        self._realHurtHP = 0 # 真实伤血值,被承伤盾抵扣后的可伤血的值
         self._lostHP = 0 # 实际掉血值
         self._curHP = 0 # 更新血量
         self._suckHP = 0 # 吸血量
@@ -190,6 +196,8 @@
         return self._hurtTypes & pow(2, hurtType) 
     def GetHurtHP(self): return self._hurtHP
     def SetHurtHP(self, hurtHP): self._hurtHP = hurtHP
+    def GetRealHurtHP(self): return self._realHurtHP
+    def SetRealHurtHP(self, realHurtHP): self._realHurtHP = realHurtHP
     def GetLostHP(self): return self._lostHP
     def SetLostHP(self, lostHP): self._lostHP = lostHP
     def GetCurHP(self): return self._curHP
@@ -235,6 +243,7 @@
             self._effDict[effID] = effect
         return
     
+    def GetIpyData(self): return self._ipyData
     def GetSkillID(self): return self._ipyData.GetSkillID()
     def GetSkillTypeID(self): return self._ipyData.GetSkillTypeID()
     def GetSkillLV(self): return self._ipyData.GetSkillLV()
@@ -259,7 +268,7 @@
     def GetConnSkill(self): return self._ipyData.GetConnSkill()
     def GetCoolDownTime(self): return self._ipyData.GetCoolDownTime()
     def GetIgnoreStates(self): return self._ipyData.GetIgnoreStates() # 无视限制列表
-    def GetBuffStates(self): return self._ipyData.GetBuffStates()
+    def GetCurBuffState(self): return self._ipyData.GetCurBuffState()
     def GetLastTime(self): return self._ipyData.GetLastTime() # 持续时间
     def GetLayerCnt(self): return self._ipyData.GetLayerCnt()
     def GetLayerMax(self): return self._ipyData.GetLayerMax()
@@ -267,6 +276,7 @@
     def GetDieContinue(self): return self._ipyData.GetDieContinue() # Buff死亡存在
     def GetEnhanceSkillList(self): return self._ipyData.GetEnhanceSkillList() # 额外触发的技能ID列表
     def GetFightPower(self): return self._ipyData.GetFightPower()
+    def GetSkillMotionName(self): return self._ipyData.GetSkillMotionName()
     
 class PyBuff():
     
@@ -277,7 +287,9 @@
         self._layer = 0
         self._calcTime = 0
         self._remainTime = 0
-        self._valueList = []
+        self._value1 = 0 # 值需要通知前端,开发时注意20亿问题
+        self._value2 = 0
+        self._value3 = 0
         return
     
     def GetSkillData(self): return self._skillData
@@ -292,9 +304,20 @@
     def SetCalcTime(self, calcTime): self._calcTime = calcTime
     def GetRemainTime(self): return self._remainTime
     def SetRemainTime(self, remainTime): self._remainTime = remainTime
-    def SetBuffValueList(self, valueList): self._valueList = valueList
-    def GetBuffValue(self, index):
-        return self._valueList[index] if len(self._valueList) > index else 0
+    def SetBuffValueList(self, valueList):
+        for index, value in enumerate(valueList):
+            if index == 0:
+                self.SetValue1(value)
+            elif index == 1:
+                self.SetValue2(value)
+            elif index == 2:
+                self.SetValue3(value)
+    def GetValue1(self): return self._value1
+    def SetValue1(self, value): self._value1 = value
+    def GetValue2(self): return self._value2
+    def SetValue2(self, value): self._value2 = value
+    def GetValue3(self): return self._value3
+    def SetValue3(self, value): self._value3 = value
     
 class BuffManager():
     ## 战斗对象buff管理器
@@ -336,6 +359,7 @@
         
         self._buffList.append(buff)
         self._buffIDDict[buffID] = buff
+        #GameWorld.DebugLog("ObjBuff:%s, AddBuff buffID=%s, %s, %s, %s, %s, %s" % (self._batObj.GetID(), buffID, buff, len(self._buffList), len(self._buffIDDict), self._buffList, self._buffIDDict))
         if skillTypeID not in self._skillTypeIDBuffIDs:
             self._skillTypeIDBuffIDs[skillTypeID] = []
         buffIDs = self._skillTypeIDBuffIDs[skillTypeID]
@@ -344,12 +368,15 @@
             
         return buff
     
-    def DelBuff(self, buffID):
+    def DelBuff(self, buffID, release=True):
         if buffID not in self._buffIDDict:
+            #GameWorld.DebugLog("ObjBuff:%s, DelBuff not in self._buffIDDict, buffID=%s, %s" % (self._batObj.GetID(), buffID, self._buffIDDict.keys()))
             return
+        #GameWorld.DebugLog("ObjBuff:%s, DelBuff %s, buffID=%s, dict:%s, len:%s, list:%s" % (self._batObj.GetID(), release, buffID, self._buffIDDict, len(self._buffList), self._buffList))
         buff = self._buffIDDict.pop(buffID)
         if buff in self._buffList:
             self._buffList.remove(buff)
+        #GameWorld.DebugLog("    ObjBuff:%s, buffID=%s, dict:%s, len:%s, dictKeys:%s, list:%s" % (self._batObj.GetID(), buffID, len(self._buffIDDict), len(self._buffList), self._buffIDDict.keys(), self._buffList))
         for skillTypeID, buffIDList in self._skillTypeIDBuffIDs.items():
             if buffID not in buffIDList:
                 continue
@@ -357,17 +384,19 @@
             if not buffIDList:
                 self._skillTypeIDBuffIDs.pop(skillTypeID)
             break
+        if release:
+            ObjPool.GetPoolMgr().release(buff)
         return
     
     def GetBuff(self, buffID): return self._buffIDDict.get(buffID, None)
-    def FindBuffIDBySkillID(self, skillID):
-        ## 返回该技能ID的所有buffID列表
+    def FindBuffBySkillID(self, skillID):
+        ## 返回该技能ID的所有buff列表
         skillData = IpyGameDataPY.GetIpyGameData("Skill", skillID)
         if not skillData:
             return []
-        return self.FindBuffIDBySkillTypeID(skillData.GetSkillTypeID())
-    def FindBuffIDBySkillTypeID(self, skillTypeID):
-        ## 返回该技能TypeID的所有buffID列表
+        return self.FindBuffBySkillTypeID(skillData.GetSkillTypeID())
+    def FindBuffBySkillTypeID(self, skillTypeID):
+        ## 返回该技能TypeID的所有buff列表
         if skillTypeID not in self._skillTypeIDBuffIDs:
             return []
         buffs = []
@@ -402,7 +431,6 @@
     def IsInBuffState(self, state): return state in self._buffStateDict ## 是否处于某种状态下
     def GetStateBuffIDList(self, state): return self._buffStateDict.get(state, []) # 获取某种状态的所有buffID列表
     
-    
 class PySkill():
     
     def __init__(self, ipyData):
@@ -413,14 +441,14 @@
         self._tagObjList = [] # 本次技能目标列表 [BatObj, ...]
         self._hurtList = [] # 本次伤血列表,可能同一个对象有多个伤害,如弹射等 [HurtObj, ...]
         self._bySkill = None # 由哪个技能触发的
-        self._isEnhanceSkill = False # 是否由主技能额外触发的(非被动触发,即主技能的EnhanceSkillList字段中的技能)
+        self._afterLogicList = [] # 技能释放后需要处理逻辑 [[logicType, logicParams], ...]
         return
     
     def ResetUseRec(self):
         self._batType = 0
         self._tagObjList = []
         self._bySkill = None
-        self._isEnhanceSkill = False
+        self._afterLogicList = []
         self.ClearHurtObj()
         return
     
@@ -444,11 +472,11 @@
     def GetHappenRate(self): return self._skillData.GetHappenRate() # 触发概率
     def GetEffect(self, index): return self._skillData.GetEffect(index)
     def GetEffectCount(self): return self._skillData.GetEffectCount()
-    def GetEffectByID(self, effID): return self._skillData.GetEffectByID()
+    def GetEffectByID(self, effID): return self._skillData.GetEffectByID(effID)
     def GetConnSkill(self): return self._skillData.GetConnSkill()
     def GetCoolDownTime(self): return self._skillData.GetCoolDownTime()
     def GetIgnoreStates(self): return self._skillData.GetIgnoreStates() # 无视限制列表
-    def GetBuffStates(self): return self._skillData.GetBuffStates()
+    def GetCurBuffState(self): return self._skillData.GetCurBuffState()
     def GetLastTime(self): return self._skillData.GetLastTime() # 持续时间
     def GetLayerCnt(self): return self._skillData.GetLayerCnt()
     def GetLayerMax(self): return self._skillData.GetLayerMax()
@@ -456,6 +484,7 @@
     def GetDieContinue(self): return self._skillData.GetDieContinue() # Buff死亡存在
     def GetEnhanceSkillList(self): return self._skillData.GetEnhanceSkillList() # 额外触发的技能ID列表
     def GetFightPower(self): return self._skillData.GetFightPower()
+    def GetSkillMotionName(self): return self._skillData.GetSkillMotionName()
     
     ## ---------------------------------- 非技能表内容 ----------------------------------
     def GetCalcTime(self): return self._calcTime
@@ -464,12 +493,18 @@
     def SetRemainTime(self, remainTime): self._remainTime = remainTime
     def GetBatType(self): return self._batType
     def SetBatType(self, batType): self._batType = batType
-    def GetIsEnhanceSkill(self): return self._isEnhanceSkill
-    def SetIsEnhanceSkill(self, isEnhanceSkill): self._isEnhanceSkill = isEnhanceSkill
     def GetBySkill(self): return self._bySkill
     def SetBySkill(self, bySkill): self._bySkill = bySkill
     def GetTagObjList(self): return self._tagObjList # 技能目标列表
     def SetTagObjList(self, tagObjList): self._tagObjList = tagObjList
+    def GetAfterLogicList(self): return self._afterLogicList
+    def AddAfterLogic(self, logicType, logicData):
+        '''添加技能释放后需要处理额外逻辑
+        @param logicType: 逻辑类型
+        @param logicData: 逻辑对应的数据
+        '''
+        self._afterLogicList.append([logicType, logicData])
+        return
     def ClearHurtObj(self):
         ## 清空伤血统计
         poolMgr = ObjPool.GetPoolMgr()
@@ -550,6 +585,7 @@
         self.ownerID = 0 # 所属玩家ID,可能为0,0代表非玩家的战斗实体
         self.heroID = 0
         self.skinID = 0
+        self.atkDistType = 0
         self.lv = 1
         self.fightPower = 0
         self.faction = 0 # 所属阵营,一般只有双方阵营, 1 或 2,发起方默认1
@@ -557,6 +593,7 @@
         self.posNum = 0 # 所在阵容站位
         self._hp = 0 # 当前生命值
         self._xp = 0 # 当前怒气值
+        self._isAlive = True # 是否活着
         self._initAttrDict = {} # 初始化时的属性,固定不变,初始化时已经算好的属性  {attrID:value, ...}
         self._batAttrDict = {} # 实际战斗属性,包含buff层级的实际属性
         self._skillTempAttrDict = {} # 某次技能释放中临时的属性增减 {attrID:+-value, ...}
@@ -605,6 +642,8 @@
     def GetID(self): return self.objID
     def GetName(self): return self.objName
     def SetName(self, name): self.objName = name
+    def GetAtkDistType(self): return self.atkDistType
+    def SetAtkDistType(self, atkDistType): self.atkDistType = atkDistType
     def GetNPCID(self): return self.npcID # 如果是NPC战斗单位,则该值非0
     def SetNPCID(self, npcID): self.npcID = npcID # 设置所属的NPCID
     def GetOwnerID(self): return self.ownerID # 如果是玩家战斗单位,则该值非0,为所属玩家ID
@@ -646,7 +685,41 @@
         ## 是否处于某种状态下
         return self._buffMgr.IsInBuffState(state)
     
+    def IsInControlled(self):
+        ## 是否被控制中
+        for state in ChConfig.InControlledStateList:
+            if self.IsInState(state):
+                return True
+        return False
+    
+    def CanAction(self):
+        ## 是否可以行动
+        if not self.IsAlive():
+            return False
+        if self.IsInControlled():
+            return False
+        return True
+    
+    def GetSneerTagObj(self):
+        ## 获取被嘲讽的目标,如果存在则一定是活着的目标
+        buffIDList = self._buffMgr.GetStateBuffIDList(ChConfig.BatObjState_Sneer)
+        if not buffIDList:
+            return
+        objMgr = GetBatObjMgr()
+        for buffID in buffIDList:
+            buff = self._buffMgr.GetBuff(buffID)
+            if not buff:
+                continue
+            tagObj = objMgr.getBatObj(buff.GetOwnerID())
+            if tagObj and tagObj.IsAlive(): # 活着才有效
+                return tagObj
+        return
+    
     # 战斗属性
+    def IsAlive(self): return self._isAlive # 是否活着
+    def SetDead(self):
+        self._isAlive = False
+        self._hp = 0
     def GetMaxHP(self): return self._batAttrDict.get(ChConfig.AttrID_MaxHP, 0)
     def SetMaxHP(self, maxHP, isNotify=False):
         self._batAttrDict[ChConfig.AttrID_MaxHP] = maxHP
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
index 31df10d..a12550f 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
@@ -267,12 +267,12 @@
                     batObj = batObjMgr.getBatObj(objID)
                     if not batObj:
                         continue
-                    if batObj.GetHP() > 0:
+                    if batObj.IsAlive():
                         allKilled = False
                         break
                     
             if allKilled:
-                self.winFaction = ChConfig.Def_FactionA if faction == ChConfig.Def_FactionB else ChConfig.Def_FactionA
+                self.winFaction = ChConfig.Def_FactionA if faction == ChConfig.Def_FactionB else ChConfig.Def_FactionB
                 DoTurnFightOver(self.guid)
                 return self.winFaction
             
@@ -556,7 +556,7 @@
     
     batObjMgr = BattleObj.GetBatObjMgr()
     initXP = IpyGameDataPY.GetFuncCfg("AngerXP", 1)
-    atkBackSkillIDList = IpyGameDataPY.GetFuncEvalCfg("ParryCfg", 3)
+    atkBackSkillIDList = IpyGameDataPY.GetFuncEvalCfg("ParryCfg", 2)
     for posNumKey, heroInfo in heroDict.items():
         posNum = int(posNumKey)
         
@@ -597,6 +597,7 @@
         batObj.SetLineupPos(posNum, num)
         batObj.SetFightPower(fightPower)
         batObj.SetLV(lv)
+        batObj.SetAtkDistType(atkDistType)
         if npcID:
             batObj.SetNPCID(npcID)
         elif lineupPlayerID:
@@ -1112,6 +1113,7 @@
     return
 
 def OnTimelineChange(turnFight):
+    ## 每个时间节点变化时处理
     
     nowTimeline = turnFight.getTimeline()
     
@@ -1120,8 +1122,14 @@
         for batLineup in batFaction.lineupDict.values():
             for objID in batLineup.posObjIDDict.values():
                 batObj = batObjMgr.getBatObj(objID)
-                if not batObj or batObj.GetHP() <= 0:
+                #GameWorld.DebugLog("OnTimelineChange! objID=%s" % (objID))
+                if not batObj or not batObj.IsAlive():
                     continue
+                
+                batObj.SetDict(ChConfig.Def_Obj_Dict_TurnComboNum, 0)
+                batObj.SetDict(ChConfig.Def_Obj_Dict_TurnMissNum, 0)
+                batObj.SetDict(ChConfig.Def_Obj_Dict_TurnParryNum, 0)
+                
                 curID = batObj.GetID()
                 skillManager = batObj.GetSkillManager()
                 for index in range(0, skillManager.GetSkillCount()):
@@ -1148,10 +1156,12 @@
                     remainTime = buff.GetRemainTime()
                     if not remainTime:
                         # 永久buff不处理
+                        #GameWorld.DebugLog("    永久buff不处理! curID=%s,index=%s,skillID=%s" % (curID, index, buff.GetSkillID()))
                         continue
                     calcTimeline = buff.GetCalcTime()
                     passTurn = __calcPassturn(calcTimeline, nowTimeline, False)
                     if passTurn <= 0:
+                        #GameWorld.DebugLog("    passTurn <= 0 passTurn=%s,calcTimeline=%s,nowTimeline=%s,skillID=%s" % (passTurn, calcTimeline, nowTimeline, buff.GetSkillID()))
                         continue
                     
                     updRemainTime = max(0, remainTime - passTurn)
@@ -1194,40 +1204,6 @@
         return
     
     TurnPassive.OnTriggerPassiveEffect(turnFight, batObj, ChConfig.TriggerWay_BigTurnStart)
-            
-#    SetTimeline(gameObj, turnNum, 0)
-#    # 重置连击、反击数
-#    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnComboNum, 0)
-#    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnAtkBackNum, 0)
-#    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnParryNum, 0)
-#    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnMissNum, 0)
-#    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnAtkAddXPCount, 0)
-#    gameObj.SetDict(ChConfig.Def_Obj_Dict_TurnXPUseState, 0)
-#    gameObj.SetDict(ChConfig.Def_PlayerKey_AttrFaintCD, 0) # 击晕CD
-#    
-#    objType = gameObj.GetGameObjType()
-#    objID = gameObj.GetID()
-#    objName = GetObjName(gameObj)
-#    GameWorld.DebugLog("ObjPerTurnStart: 回合%s, %s objType-ID-HP(%s-%s-%s)" % (turnNum, objName, objType, objID, GameObj.GetHP(gameObj)))
-#    
-#    # 每回合开始减技能CD
-#    skillManager = gameObj.GetSkillManager()
-#    for i in range(skillManager.GetSkillCount()):
-#        skill = skillManager.GetSkillByIndex(i)
-#        remainTime = skill.GetRemainTime()
-#        if not remainTime:
-#            continue
-#        skillID = skill.GetSkillID()
-#        updRemainTime = max(0, remainTime - ChConfig.Def_PerTurnTick)
-#        skill.SetRemainTime(updRemainTime)
-#        GameWorld.DebugLog("    skillID=%s,remainTime=%s,updRemainTime=%s" % (skillID, remainTime, updRemainTime))
-#        
-#    # 刷新定时处理的buff效果
-#    SkillShell.ProcessPersistBuff(gameObj, tick)
-#    
-#    PassiveBuffEffMng.OnPassiveSkillTrigger(gameObj, tagObj, None, ChConfig.TriggerType_TurnNum, tick)
-#    
-#    __logGameObjAttr(gameObj)
     return
 
 def TurnFightPerTurnBigEnd(turnFight, batObj, turnNum):
@@ -1271,6 +1247,8 @@
 def AddTurnObjHurtValue(curBatObj, tagBatObj, hurtValue, lostHP, skillID=0, isBounce=False):
     ## 回合对象添加伤害值
     # @param isBounce: 是否反弹伤害
+    if hurtValue <= 0:
+        return
     curID = curBatObj.GetID()
     tagID = tagBatObj.GetID()
     if curID != tagID:
@@ -1279,7 +1257,7 @@
                        % (curID, tagID, skillID, hurtValue, lostHP, updStatValue, tagBatObj.GetHP(), isBounce))
         
         if tagBatObj:
-            updStatValue = tagBatObj.StatDefValue(lostHP)
+            updStatValue = tagBatObj.StatDefValue(hurtValue)
             GameWorld.DebugLog("        统计承伤: curID=%s,tagID=%s,skillID=%s,hurtValue=%s,lostHP=%s,updStatValue=%s,curHP=%s,isBounce=%s" 
                            % (tagID, curID, skillID, hurtValue, lostHP, updStatValue, tagBatObj.GetHP(), isBounce))
             
@@ -1303,12 +1281,11 @@
     objName = GetObjName(curBatObj)
     
     # 是否可行动状态判断
-    canAction = True
-    
+    canAction = curBatObj.CanAction()
     if not canAction:
         GameWorld.DebugLog("★回合%s %s 当前状态不可行动!" % (turnNum, objName))
         return
-        
+    
     atk = curBatObj.GetAtk()
     curXP = curBatObj.GetXP()
     GameWorld.DebugLog("★回合%s %s 行动 : atk=%s,curHP=%s/%s,curXP=%s" % (turnNum, objName, atk, curHP, curBatObj.GetMaxHP(), curXP))
@@ -1338,6 +1315,9 @@
         if SkillCommon.isAngerSkill(useSkill):
             if curXP < xpMax:
                 continue
+            if curBatObj.IsInState(ChConfig.BatObjState_Sneer):
+                GameWorld.DebugLog("嘲讽状态下,无法主动释放怒技!") # 可被动释放怒技,如怒技追击
+                continue
             useCnt = -1 # xp技能优先释放
         else:
             useCnt = curBatObj.GetSkillUseCnt(skillID)
@@ -1354,166 +1334,12 @@
     TurnPassive.OnTriggerPassiveEffect(turnFight, curBatObj, ChConfig.TriggerWay_HeroActionEnd)
     return True
 
-def DoAttack(curBatObj, tagBatObj, tick, turnBattleType=ChConfig.TurnBattleType_Normal, useSkill=None):
-#    curID = curBatObj.GetID()
-#    npcID = curBatObj.GetNPCID()
-#    objName = GetObjName(curBatObj)
-#    GameWorld.DebugLog("    ● %s DoAttack: curID=%s,,turnBattleType=%s" % (objName, curID, turnBattleType))
-#    
-#    atkOK = False
-#    curBatObj.SetDict(ChConfig.Def_Obj_Dict_TurnBattleType, turnBattleType)
-#    
-#    if turnBattleType == ChConfig.TurnBattleType_AtkBack:
-#        if not tagBatObj:
-#            return
-#        skillManager = curBatObj.GetSkillManager()
-#        for index in range(0, skillManager.GetSkillCount()):
-#            skill = skillManager.GetSkillByIndex(index)
-#            if not skill:
-#                continue
-#            if skill.GetFuncType() == ChConfig.Def_SkillFuncType_AtkbackSkill:
-#                useSkill = skill
-#                break
-#        atkOK = SkillShell.DoLogic_UseSkill(curBatObj, tagBatObj, useSkill, tick)
-#    elif turnBattleType == ChConfig.TurnBattleType_Combo:
-#        if not tagBatObj:
-#            return
-#        atkOK = SkillShell.DoLogic_UseSkill(curBatObj, tagBatObj, useSkill, tick)
-#    else:
-#        curXP = GameObj.GetXP(curBatObj)
-#        xpMax = IpyGameDataPY.GetFuncCfg("AngerXP", 2) 
-#        skillManager = curBatObj.GetSkillManager()
-#        useSkillList = []
-#        #GameWorld.DebugLog('skillCount=%s' % skillManager.GetSkillCount(), npcID)
-#        for index in range(0, skillManager.GetSkillCount()):
-#            useSkill = skillManager.GetSkillByIndex(index)
-#            if not useSkill:
-#                continue
-#            if useSkill.GetFuncType() in [ChConfig.Def_SkillFuncType_AtkbackSkill]:
-#                #基础普攻不能主动释放,目前仅用于反击
-#                continue
-#            #被动技能无法使用
-#            if SkillCommon.isPassiveSkill(useSkill):
-#                continue
-#            #还在冷却时间内无法释放
-#            if useSkill.GetRemainTime():
-#                continue
-#            skillID = useSkill.GetSkillID()
-#            # 常规攻击优先xp
-#            if SkillCommon.isAngerSkill(useSkill) and turnBattleType == ChConfig.TurnBattleType_Normal:
-#                if curXP < xpMax:
-#                    continue
-#                useCnt = -1 # xp技能优先释放
-#            else:
-#                useCnt = curBatObj.GetDictByKey(ChConfig.Def_NPC_Dict_SkillUseCnt % skillID) # 该技能已使用次数
-#            useSkillList.append([useCnt, index, skillID, useSkill])
-#            
-#        useSkillList.sort() # 按使用次数优先升序排,使用次数低的优先判断使用
-#        #GameWorld.DebugLog('    技能使用顺序 = useSkillList%s' % str(useSkillList), npcID)
-#        
-#        for useInfo in useSkillList:
-#            useSkill = useInfo[-1]
-#            #skillID = useSkill.GetSkillID()
-#            atkOK, tagBatObj = OnUseSkill(curBatObj, useSkill, tick)
-#            if atkOK:
-#                break
-#            
-#    curBatObj.SetDict(ChConfig.Def_Obj_Dict_TurnBattleType, 0) # 无论攻击成功与否都重置战斗类型
-#    
-#    tagID = 0
-#    tagHP = 0
-#    if tagObj:
-#        tagID = tagObj.GetID()
-#        tagHP = GameObj.GetHP(tagObj)
-#    GameWorld.DebugLog('        atkOK=%s,tagID=%s,tagHP=%s' % (atkOK, tagID, tagHP), npcID)
-#    if not atkOK:
-#        return
-#    
-#    if not tagObj:
-#        return
-#    
-#    if GameObj.GetFaction(curNPC) == GameObj.GetFaction(tagObj):
-#        # 同阵营直接返回,不处理连击、反击
-#        return True
-#    
-#    curHP = GameObj.GetHP(curNPC)
-#    tagHP = GameObj.GetHP(tagObj)
-#    tagID = tagObj.GetID()
-#    GameWorld.DebugLog("            curID-HP=(%s-%s),tagID-HP=(%s-%s)" % (curID, curHP, tagID, tagHP))
-#    if tagHP <= 0 or curHP <= 0:
-#        return True
-#    
-#    # 反击,反击可打断连击,所以优先判断
-#    if CanAtkBack(curNPC, tagObj):
-#        DoAttack(tagObj, curNPC, tick, ChConfig.TurnBattleType_AtkBack)
-#        return True
-#    
-#    # 连击
-#    if CanCombo(curNPC, tagObj):
-#        DoAttack(curNPC, tagObj, tick, ChConfig.TurnBattleType_Combo, useSkill)
-#        
-    return True
-
-def CanAtkBack(atkObj, defObj):
-    ## 可否反击
-    posNum = atkObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnFightPosInfo) % 100
-    if posNum <= 0:
-        GameWorld.DebugLog("            被非主战单位攻击时无法触发反击: atkID=%s,posNum=%s" % (atkObj.GetID(), posNum))
-        return False
-    atkDistType = AttackCommon.GetAtkDistType(defObj)
-    if atkDistType == ChConfig.AtkDistType_Long:
-        if not IpyGameDataPY.GetFuncCfg("ParryCfg", 2):
-            GameWorld.DebugLog("            远程单位不可反击: defID=%s" % (defObj.GetID()))
-            return False
-    defAtkBackRate = GameObj.GetAtkBackRate(defObj) # 防方反击率
-    atkBackNum = defObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnAtkBackNum) # 已反击次数
-    if atkBackNum > 10:
-        # 内置最高反击数防范
-        return False
-    if atkBackNum > 0:
-        validPerList = IpyGameDataPY.GetFuncEvalCfg("TurnFight", 4)
-        vaildPer = validPerList[atkBackNum - 1] if len(validPerList) >= atkBackNum else 0
-        defAtkBackRate = int(defAtkBackRate * vaildPer / 100.0)
-        
-    atkAtkBackDefRate = GameObj.GetAtkBackDefRate(atkObj) # 攻方抵抗反击率
-    atkBackRate = max(0, defAtkBackRate - atkAtkBackDefRate)
-    if atkBackRate <= 0 or not GameWorld.CanHappen(atkBackRate):
-        GameWorld.DebugLog("            无法反击: defID=%s,atkBackNum=%s,atkBackRate=%s=(defAtkBackRate=%s - atkAtkBackDefRate=%s)" 
-                           % (defObj.GetID(), atkBackNum, atkBackRate, defAtkBackRate, atkAtkBackDefRate))
-        return False
-    GameWorld.DebugLog("            可以反击: defID=%s,atkBackNum=%s,atkBackRate=%s=(defAtkBackRate=%s - atkAtkBackDefRate=%s)" 
-                       % (defObj.GetID(), atkBackNum, atkBackRate, defAtkBackRate, atkAtkBackDefRate))
-    return True
-
-def CanCombo(atkObj, defObj):
-    ## 可否连击
-    
-    atkComboRate = GameObj.GetComboRate(atkObj) # 攻方连击率
-    comboNum = atkObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnComboNum) # 已连击次数
-    if comboNum > 10:
-        # 内置最高连击数防范
-        return False
-    if comboNum > 0:
-        validPerList = IpyGameDataPY.GetFuncEvalCfg("TurnFight", 3)
-        vaildPer = validPerList[comboNum - 1] if len(validPerList) >= comboNum else 0
-        atkComboRate = int(atkComboRate * vaildPer / 100.0)
-        
-    defComboReduce = GameObj.GetComboDefRate(defObj) # 防方抵抗连击率
-    comboRate = max(0, atkComboRate - defComboReduce)
-    if comboRate <= 0 or not GameWorld.CanHappen(comboRate):
-        GameWorld.DebugLog("            无法连击: atkID=%s,comboNum=%s,comboRate=%s=(atkComboRate=%s - defComboReduce=%s)" 
-                           % (atkObj.GetID(), comboNum, comboRate, atkComboRate, defComboReduce))
-        return False
-    GameWorld.DebugLog("            可以连击: atkID=%s,comboNum=%s,comboRate=%s=(atkComboRate=%s - defComboReduce=%s)" 
-                       % (atkObj.GetID(), comboNum, comboRate, atkComboRate, defComboReduce))
-    return True
-
 def SetObjKilled(turnFight, gameObj, killer=None, useSkill=None):
     objID = gameObj.GetID()
-    GameWorld.DebugLog("        %s 回合战斗主体被击杀: curID=%s" % (GetObjName(gameObj), objID))
-    gameObj.SetHP(0)
     killerObjID = killer.GetID() if killer else 0
     skillID = useSkill.GetSkillID() if useSkill else 0
+    GameWorld.DebugLog("        %s 回合战斗主体被击杀: curID=%s,killerObjID=%s,skillID=%s" % (GetObjName(gameObj), objID, killerObjID, skillID))
+    gameObj.SetDead()
     
     clientPack = ObjPool.GetPoolMgr().acquire(ChPyNetSendPack.tagMCTurnFightObjDead)
     clientPack.ObjID = objID
@@ -1551,7 +1377,7 @@
     
     turnFight.costTime = time.time() - turnFight.startTime
     winFaction = turnFight.winFaction
-    GameWorld.DebugLog("--- 战斗结束处理 --- %s, winFaction=%s, costTime=%ss" % (guid, winFaction, turnFight.costTime))
+    GameWorld.DebugLog("--- 战斗结束处理 ---, winFaction=%s, costTime=%ss, %s" % (winFaction, turnFight.costTime, guid))
     
     # 统计明细
     batObjMgr = BattleObj.GetBatObjMgr()
@@ -1577,7 +1403,7 @@
                 atkHurt = batObj.hurtStat
                 defHurt = batObj.defStat
                 cureHP = batObj.cureStat
-                GameWorld.DebugLog("    Pos:%s ID=%s-%s-%s,,HP=%s/%s, 输出=%s,承伤=%s,治疗=%s" 
+                GameWorld.DebugLog("    Pos:%s ID=%s,npcID=%s,heroID=%s,HP=%s/%s, 输出=%s,承伤=%s,治疗=%s" 
                                    % (posNum, objID, npcID, heroID, batObj.GetHP(), batObj.GetMaxHP(), atkHurt, defHurt, cureHP))
                 lineupStatInfo[str(posNum)] = {"ObjID":objID, "HeroID":heroID, "NPCID":npcID, "AtkHurt":atkHurt, "DefHurt":defHurt, "CureHP":cureHP}
                 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index 63e2843..3cde4bd 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -954,8 +954,11 @@
 
 Def_SkillID_Peace = 23048   # 玩家间和平buff
 #----------------------------------------------------------------------
-#战斗类型
-Def_ChanceDefRate = 2000    # 抵御伤害概率, 目前固定20%概率
+
+#技能释放后需要额外处理逻辑
+AfterLogic_DelBuff = "DelBuff"
+AfterLogic_AddBuff = "AddBuff"
+AfterLogic_SyncBuff = "SyncBuff"
 
 #伤害类型
 (
@@ -1312,6 +1315,17 @@
 CampType_Justice = ShareDefine.CampType_Justice  # 正义
 CampType_Evil = ShareDefine.CampType_Evil  # 邪恶
 
+#buff释放类型
+BuffAtkType_DamageShield = 1003 # 承伤盾
+
+#计算类型
+Def_CalcTypeList = (
+Def_Calc_Attack, # 攻击 0
+Def_Calc_MaxHP, # 最大生命值 1
+Def_Calc_HurtValue, # 伤害值 2
+Def_Calc_TagMaxHP, # 目标最大生命值 3
+) = range(4)
+
 #治疗类型(影响公式参数)
 Def_CureTypeList = (
 Def_Cure_Attack, # 攻击 0
@@ -1339,6 +1353,22 @@
 Def_Skill_HappenState_LuckyHit = 0x0004  # 必会心一击
 Def_Skill_HappenState_ThumpHit = 0x0008  # 必重击
 
+# 回合战斗行列数
+TurnFightRows = 2
+TurnFightCols = 3
+
+def GetInColNum(posNum):
+    ## 获取站位编号所在列编号
+    # @param posNum: 在阵容中的站位 1 ~ n
+    # @return:  1 ~ 总列数
+    return (posNum - 1) % TurnFightCols + 1
+
+def GetInRowNum(posNum):
+    ## 获取站位编号所在行编号
+    # @param posNum: 在阵容中的站位 1 ~ n
+    # @return:  1 ~ 总行数
+    return (posNum - 1) / TurnFightCols + 1
+
 # 技能目标 - 瞄准范围
 (
 SkillTagAim_All, # 全部 0
@@ -1356,7 +1386,8 @@
 SkillTagAffect_HPLowest, # 血量最低 1
 SkillTagAffect_HPHighest, # 血量最高 2
 SkillTagAffect_Death, # 死亡单位 3
-) = range(4)
+SkillTagAffect_UncontrolledPriority, # 未被控制优先 4
+) = range(5)
 
 #技能施法目标
 Def_UseSkillAim_Type = 3
@@ -3060,11 +3091,13 @@
 
 # 回合攻击战斗类型
 (
-TurnBattleType_Normal, # 常规攻击
-TurnBattleType_Combo, # 连击
-TurnBattleType_AtkBack, # 反击
-TurnBattleType_Pursue , # 追击
-) = range(4)
+TurnBattleType_Normal, # 常规攻击 0
+TurnBattleType_Combo, # 连击 1
+TurnBattleType_AtkBack, # 反击 2
+TurnBattleType_Pursue, # 追击 3
+TurnBattleType_Enhance, # 额外技能 4
+TurnBattleType_Passive, # 被动技能 5
+) = range(6)
 
 Def_PerTurnTick = 1000 # 每回合等同于常规tick时长
 
@@ -3158,7 +3191,11 @@
     BatObjState_Sneer, # 嘲讽 9
     BatObjState_LimitSkill, # 沉默 10
     BatObjState_LimitAddHP, # 禁疗 11
-) = range(12)
+    BatObjState_Stone, # 石化 12
+) = range(13)
+
+# 被控制的状态列表,无法行动,处于某些控制类buff影响状态下,如晕眩,冰冻,石化
+InControlledStateList = [BatObjState_Frozen, BatObjState_Stun, BatObjState_Stone]
 
 #玩家状态定义,不能超过31个,如超过,需扩展多个key支持
 Def_PlayerStateList = (
@@ -4465,7 +4502,16 @@
 TriggerWay_HeroTurnEnd, # 武将回合开始时    5
 TriggerWay_HeroActionStart, # 武将行动前    6
 TriggerWay_HeroActionEnd, # 武将行动后    7
-) = range(1, 1 + 7)
+TriggerWay_CalcTagInState, # 攻击计算时对方处于xx状态时(参数:状态1|2|...)一般用于攻击时属性计算  8
+TriggerWay_AttackOverTagInState, # 攻击计算后对方处于xx状态时(参数:状态1|2|...)一般用于攻击后触发效果  9
+TriggerWay_AttackOverDirect, # 直接攻击后 (非buff攻击)10
+TriggerWay_BeAttackedDirect, # 受到直接攻击时 (非buff攻击)11
+TriggerWay_ShieldBroken, # 承伤盾被击破时 12
+) = range(1, 1 + 12)
+
+# 被动触发有效来源
+TriggerSrc_Skill = 1
+TriggerSrc_Buff = 2
 
 (
 TriggerType_BeSuperHit, # 被暴击触发技能 1
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index 5fabeab..abf348a 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -49970,6 +49970,9 @@
                   ("LastTime", c_int),    # 剩余时长毫秒/回合数
                   ("Layer", c_ushort),    # 层数,不需要默认0
                   ("OwnerID", c_int),    # buff来源者,即施法方
+                  ("Value1", c_int),    
+                  ("Value2", c_int),    
+                  ("Value3", c_int),    
                   ]
 
     def __init__(self):
@@ -49993,6 +49996,9 @@
         self.LastTime = 0
         self.Layer = 0
         self.OwnerID = 0
+        self.Value1 = 0
+        self.Value2 = 0
+        self.Value3 = 0
         return
 
     def GetLength(self):
@@ -50011,7 +50017,10 @@
                                 RelatedSkillID:%d,
                                 LastTime:%d,
                                 Layer:%d,
-                                OwnerID:%d
+                                OwnerID:%d,
+                                Value1:%d,
+                                Value2:%d,
+                                Value3:%d
                                 '''\
                                 %(
                                 self.Cmd,
@@ -50022,7 +50031,10 @@
                                 self.RelatedSkillID,
                                 self.LastTime,
                                 self.Layer,
-                                self.OwnerID
+                                self.OwnerID,
+                                self.Value1,
+                                self.Value2,
+                                self.Value3
                                 )
         return DumpString
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index e98a113..00776b9 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -116,10 +116,9 @@
                         ("BYTE", "TriggerWay3", 0),
                         ("BYTE", "TriggerSrc3", 0),
                         ("list", "TriggerParams3", 0),
-                        ("DWORD", "ConnSkill", 0),
                         ("WORD", "CoolDownTime", 0),
                         ("list", "IgnoreStates", 0),
-                        ("list", "BuffStates", 0),
+                        ("BYTE", "CurBuffState", 0),
                         ("WORD", "LastTime", 0),
                         ("BYTE", "LayerCnt", 0),
                         ("BYTE", "LayerMax", 0),
@@ -127,6 +126,7 @@
                         ("DWORD", "DieContinue", 0),
                         ("list", "EnhanceSkillList", 0),
                         ("DWORD", "FightPower", 0),
+                        ("char", "SkillMotionName", 0),
                         ),
 
                 "Hero":(
@@ -2989,29 +2989,29 @@
     def GetEffectID1(self): return self.attrTuple[17] # 效果ID1 DWORD
     def GetEffectValues1(self): return self.attrTuple[18] # 效果值列表1 list
     def GetTriggerWay1(self): return self.attrTuple[19] # 触发方式 BYTE
-    def GetTriggerSrc1(self): return self.attrTuple[20] # 触发来源 BYTE
+    def GetTriggerSrc1(self): return self.attrTuple[20] # 有效来源 BYTE
     def GetTriggerParams1(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] # 有效来源 BYTE
     def GetTriggerParams2(self): return self.attrTuple[26] # 触发参数 list
     def GetEffectID3(self): return self.attrTuple[27] # 效果ID3 DWORD
     def GetEffectValues3(self): return self.attrTuple[28] # 效果值列表3 list
     def GetTriggerWay3(self): return self.attrTuple[29] # 触发方式 BYTE
-    def GetTriggerSrc3(self): return self.attrTuple[30] # 触发来源 BYTE
+    def GetTriggerSrc3(self): return self.attrTuple[30] # 有效来源 BYTE
     def GetTriggerParams3(self): return self.attrTuple[31] # 触发参数 list
-    def GetConnSkill(self): return self.attrTuple[32] # 关联技能 DWORD
-    def GetCoolDownTime(self): return self.attrTuple[33] # 技能冷却时间 WORD
-    def GetIgnoreStates(self): return self.attrTuple[34] # 无视限制列表 list
-    def GetBuffStates(self): return self.attrTuple[35] # Buff状态值 list
-    def GetLastTime(self): return self.attrTuple[36] # 持续时间 WORD
-    def GetLayerCnt(self): return self.attrTuple[37] # Buff层数 BYTE
-    def GetLayerMax(self): return self.attrTuple[38] # 最大层数 BYTE
-    def GetBuffRepeat(self): return self.attrTuple[39] # Buff叠加规则 DWORD
-    def GetDieContinue(self): return self.attrTuple[40] # Buff死亡存在 DWORD
-    def GetEnhanceSkillList(self): return self.attrTuple[41] # 触发技能ID列表 list
-    def GetFightPower(self): return self.attrTuple[42] # 技能战斗力 DWORD
+    def GetCoolDownTime(self): return self.attrTuple[32] # 技能冷却时间 WORD
+    def GetIgnoreStates(self): return self.attrTuple[33] # 无视限制列表 list
+    def GetCurBuffState(self): return self.attrTuple[34] # Buff状态值 BYTE
+    def GetLastTime(self): return self.attrTuple[35] # 持续时间 WORD
+    def GetLayerCnt(self): return self.attrTuple[36] # Buff层数 BYTE
+    def GetLayerMax(self): return self.attrTuple[37] # 最大层数 BYTE
+    def GetBuffRepeat(self): return self.attrTuple[38] # Buff叠加规则 DWORD
+    def GetDieContinue(self): return self.attrTuple[39] # Buff死亡存在 DWORD
+    def GetEnhanceSkillList(self): return self.attrTuple[40] # 触发技能ID列表 list
+    def GetFightPower(self): return self.attrTuple[41] # 技能战斗力 DWORD
+    def GetSkillMotionName(self): return self.attrTuple[42] # 技能动作名 char
 
 # 武将表
 class IPY_Hero():
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py
index f04ff00..5560b0a 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py
@@ -1848,6 +1848,10 @@
     #0通哟  1 PVP类型  2PVE类型  
     return curSkill.GetHurtType() % 10
 
+def isDamageShieldSkill(skillData):
+    ## 是否承伤盾技能
+    return skillData.GetAtkType() == ChConfig.BuffAtkType_DamageShield
+
 def isAngerSkill(curSkill):
     ## 是否怒气技能
     return curSkill and curSkill.GetFuncType() == ChConfig.Def_SkillFuncType_AngerSkill
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5001.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5001.py
index c5e745b..391f7aa 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5001.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5001.py
@@ -17,7 +17,7 @@
 
 import TurnBuff
 
-def DoBuffEffectLogic(turnFight, batObj, curBuff, curEffect, connSkill):
+def DoBuffEffectLogic(turnFight, batObj, tagObj, curBuff, curEffect, connSkill):
     singleLayerCnt = max(1, curEffect.GetEffectValue(0)) # 单次消耗层数/次数
     noDel = curEffect.GetEffectValue(1) # 是否不扣除层数,默认0-扣除 1-不扣除
     isAll = curEffect.GetEffectValue(2) # 是否结算剩余全部层数/次数,默认0结算单次
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5010.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5010.py
new file mode 100644
index 0000000..c1a41be
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5010.py
@@ -0,0 +1,69 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Skill.PassiveTrigger.PassiveEff_5010
+#
+# @todo:攻击方触发释放技能(可继承主技能目标或重新设置目标)
+# @author hxp
+# @date 2025-08-25
+# @version 1.0
+#
+# 详细描述: 攻击方触发释放技能(可继承主技能目标或重新设置目标)
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-08-25 12:00"""
+#-------------------------------------------------------------------------------
+
+import TurnSkill
+import IpyGameDataPY
+import GameWorld
+import ChConfig
+
+def DoSkillEffectLogic(turnFight, batObj, tagObj, effSkill, curEffect, connSkill):
+    effectID = curEffect.GetEffectID()
+    skillID = curEffect.GetEffectValue(0)
+    if not skillID:
+        passiveSkill = effSkill
+    else:
+        passiveSkill = IpyGameDataPY.GetIpyGameData("Skill", skillID)
+    if not passiveSkill:
+        return
+    passiveSkillID = passiveSkill.GetSkillID()
+    tagObjList = connSkill.GetTagObjList() if connSkill else []
+    # 继承主技能目标
+    if passiveSkill.GetTagAim() == ChConfig.SkillTagAim_MainSkill and tagObjList:
+        happenRate = passiveSkill.GetHappenRate()
+        GameWorld.DebugLog("被动触发技能,继承主技能目标! effectID=%s,passiveSkillID=%s,happenRate=%s" % (effectID, passiveSkillID, happenRate))
+        passiveTagObjList = []
+        for tagObj in tagObjList:
+            tagID = tagObj.GetID()
+            if tagObj.GetHP() <= 0:
+                GameWorld.DebugLog("    已被击杀不触发: tagID=%s" % (tagID))
+                continue
+            inHurt = False
+            for hurtObj in connSkill.GetHurtObjList():
+                if hurtObj.GetObjID() != tagID:
+                    continue
+                if not hurtObj.GetHurtHP() or hurtObj.HaveHurtType(ChConfig.HurtType_Miss):
+                    continue
+                inHurt = True
+                break
+            if not inHurt:
+                GameWorld.DebugLog("    没有伤血不触发: tagID=%s" % (tagID))
+                continue
+            if happenRate and happenRate != ChConfig.Def_MaxRateValue and not GameWorld.CanHappen(happenRate, ChConfig.Def_MaxRateValue):
+                GameWorld.DebugLog("    概率不触发: tagID=%s,happenRate=%s" % (tagID, happenRate))
+                continue
+            passiveTagObjList.append(tagObj)
+            
+        if passiveTagObjList:
+            TurnSkill.OnUseSkill(turnFight, batObj, passiveSkill, passiveTagObjList, batType=ChConfig.TurnBattleType_Passive, bySkill=connSkill)
+    else:
+        GameWorld.DebugLog("被动触发技能,重新锁定目标! effectID=%s,passiveSkillID=%s" % (effectID, passiveSkillID))
+        TurnSkill.OnUseSkill(turnFight, batObj, passiveSkill, batType=ChConfig.TurnBattleType_Passive, bySkill=connSkill)
+        
+    return
+
+def DoBuffEffectLogic(turnFight, batObj, tagObj, curBuff, curEffect, connSkill):
+    return DoSkillEffectLogic(turnFight, batObj, tagObj, None, curEffect, connSkill)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5011.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5011.py
new file mode 100644
index 0000000..bf90eff
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/PassiveTrigger/PassiveEff_5011.py
@@ -0,0 +1,58 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Skill.PassiveTrigger.PassiveEff_5011
+#
+# @todo:被击方触发释放技能(对攻击方或重新设置目标)
+# @author hxp
+# @date 2025-08-25
+# @version 1.0
+#
+# 详细描述: 被击方触发释放技能(对攻击方或重新设置目标)
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-08-25 12:00"""
+#-------------------------------------------------------------------------------
+
+import TurnSkill
+import IpyGameDataPY
+import GameWorld
+import ChConfig
+
+def DoSkillEffectLogic(turnFight, batObj, tagObj, effSkill, curEffect, connSkill):
+    effectID = curEffect.GetEffectID()
+    skillID = curEffect.GetEffectValue(0)
+    if not skillID:
+        passiveSkill = effSkill
+    else:
+        passiveSkill = IpyGameDataPY.GetIpyGameData("Skill", skillID)
+    if not passiveSkill:
+        return
+    passiveSkillID = passiveSkill.GetSkillID()
+    # 继承主技能目标
+    if passiveSkill.GetTagAim() == ChConfig.SkillTagAim_MainSkill:
+        happenRate = passiveSkill.GetHappenRate()
+        GameWorld.DebugLog("被动触发技能,继承主技能目标! effectID=%s,passiveSkillID=%s,happenRate=%s" % (effectID, passiveSkillID, happenRate))
+        tagObjList = [tagObj]
+        passiveTagObjList = []
+        for tagObj in tagObjList:
+            tagID = tagObj.GetID()
+            if tagObj.GetHP() <= 0:
+                GameWorld.DebugLog("    已被击杀不触发: tagID=%s" % (tagID))
+                continue
+            if happenRate and happenRate != ChConfig.Def_MaxRateValue and not GameWorld.CanHappen(happenRate, ChConfig.Def_MaxRateValue):
+                GameWorld.DebugLog("    概率不触发: tagID=%s,happenRate=%s" % (tagID, happenRate))
+                continue
+            passiveTagObjList.append(tagObj)
+            
+        if passiveTagObjList:
+            TurnSkill.OnUseSkill(turnFight, batObj, passiveSkill, passiveTagObjList, batType=ChConfig.TurnBattleType_Passive, bySkill=connSkill)
+    else:
+        GameWorld.DebugLog("被动触发技能,重新锁定目标! effectID=%s,passiveSkillID=%s" % (effectID, passiveSkillID))
+        TurnSkill.OnUseSkill(turnFight, batObj, passiveSkill, batType=ChConfig.TurnBattleType_Passive, bySkill=connSkill)
+        
+    return
+
+def DoBuffEffectLogic(turnFight, batObj, tagObj, curBuff, curEffect, connSkill):
+    return DoSkillEffectLogic(turnFight, batObj, tagObj, None, curEffect, connSkill)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuff.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuff.py
index 27ddea2..68799eb 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuff.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuff.py
@@ -18,44 +18,70 @@
 import ChConfig
 import GameWorld
 import ChPyNetSendPack
+import IpyGameDataPY
 import TurnBuffs
+import BattleObj
 import ObjPool
 
 GameWorld.ImportAll("Script\\Skill\\", "TurnBuffs")
 
-def GetAddBuffValue(attacker, defender, curSkill):
+def GetAddBuffValue(turnFight, attacker, defender, curSkill):
     callFunc = GameWorld.GetExecFunc(TurnBuffs, "BuffAtkType_%d.%s" % (curSkill.GetAtkType(), "CalcBuffValue"))
     if not callFunc:
         return []
-    return callFunc(attacker, defender, curSkill)
+    return callFunc(turnFight, attacker, defender, curSkill)
 
-def OnAddBuff(turnFight, batObj, buffSkill, buffOwner=None):
+def DoAddBuffBySkillID(turnFight, batObj, skillID, buffOwner=None, bySkill=None, afterLogic=False):
+    ## 根据技能ID添加buff
+    if not skillID:
+        return
+    skillIpyData = IpyGameDataPY.GetIpyGameData("Skill", skillID)
+    if not skillIpyData:
+        return
+    tagObjList = [batObj]
+    poolMgr = ObjPool.GetPoolMgr()
+    useSkill = poolMgr.acquire(BattleObj.PySkill, skillIpyData)
+    useSkill.SetTagObjList(tagObjList)
+    
+    OnAddBuff(turnFight, batObj, useSkill, buffOwner, bySkill, afterLogic)
+    
+    poolMgr.release(useSkill)
+    return
+
+def OnAddBuff(turnFight, batObj, buffSkill, buffOwner=None, bySkill=None, afterLogic=False):
     skillID = buffSkill.GetSkillID()
-    bySkill = buffSkill.GetBySkill()
+    bySkill = buffSkill.GetBySkill() if not bySkill else bySkill
     relatedSkillID = bySkill.GetSkillID() if bySkill else 0
     curID = batObj.GetID()
     if not buffOwner:
         buffOwner = batObj
     ownerID = buffOwner.GetID()
-    buffValueList = GetAddBuffValue(buffOwner, batObj, buffSkill)
-    GameWorld.DebugLog("OnAddBuff: curID=%s,skillID=%s,ownerID=%s,relatedSkillID=%s,buffValueList=%s" % (curID, skillID, ownerID, relatedSkillID, buffValueList))
+    buffValueList = GetAddBuffValue(turnFight, buffOwner, batObj, buffSkill)
+    GameWorld.DebugLog("OnAddBuff: curID=%s,skillID=%s,atkType=%s,buffValueList=%s,ownerID=%s,relatedSkillID=%s" 
+                       % (curID, skillID, buffSkill.GetAtkType(), buffValueList, ownerID, relatedSkillID))
     
     skillTypeID = buffSkill.GetSkillTypeID()
     # 先简单做下能加上即可
     buffMgr = batObj.GetBuffManager()
-    buffIDList = buffMgr.FindBuffIDBySkillTypeID(skillTypeID)
-    if buffIDList:
-        GameWorld.DebugLog("    已经存在该buff: skillTypeID=%s,buffIDList=%s" % (skillTypeID, buffIDList))
-        # buff堆叠逻辑
-        
+    buffList = buffMgr.FindBuffBySkillTypeID(skillTypeID)
+    if buffList:
+        # buff堆叠逻辑,待处理,先直接通知
+        for buff in buffList:
+            if not buff:
+                continue
+            GameWorld.DebugLog("    已经存在该buff: buffID=%s,skillTypeID=%s" % (buff.GetBuffID(), skillTypeID))
+            if afterLogic and bySkill:
+                bySkill.AddAfterLogic(ChConfig.AfterLogic_AddBuff, [batObj, buff, buffOwner])
+            else:
+                SyncBuffRefresh(turnFight, batObj, buff, relatedSkillID)
+                
         return True
     
-    __AddNewBuff(turnFight, batObj, buffMgr, buffSkill, buffValueList, buffOwner)
+    __AddNewBuff(turnFight, batObj, buffMgr, buffSkill, buffValueList, buffOwner, bySkill, afterLogic)
     return True
 
-def __AddNewBuff(turnFight, batObj, buffMgr, buffSkill, buffValueList, buffOwner):
+def __AddNewBuff(turnFight, batObj, buffMgr, buffSkill, buffValueList, buffOwner, bySkill=None, afterLogic=False):
     skillID = buffSkill.GetSkillID()
-    bySkill = buffSkill.GetBySkill()
     relatedSkillID = bySkill.GetSkillID() if bySkill else 0
     curID = batObj.GetID()
     ownerID = buffOwner.GetID()
@@ -71,11 +97,13 @@
     buff.SetRemainTime(buffSkill.GetLastTime())
     buff.SetLayer(buffSkill.GetLayerCnt())
     buff.SetBuffValueList(buffValueList)
-    buffStates = buffSkill.GetBuffStates()
-    for buffState in buffStates:
-        buffMgr.AddBuffState(buffState, buffID)
-    isNotify = True
-    if isNotify:
+    curBuffState = buffSkill.GetCurBuffState()
+    if curBuffState:
+        buffMgr.AddBuffState(curBuffState, buffID)
+        
+    if afterLogic and bySkill:
+        bySkill.AddAfterLogic(ChConfig.AfterLogic_AddBuff, [batObj, buff, buffOwner])
+    else:
         SyncBuffRefresh(turnFight, batObj, buff, relatedSkillID)
         
     DoBuffAddOver(turnFight, batObj, buffSkill, buff, buffOwner)
@@ -101,7 +129,7 @@
             continue
         
         if curEffect.GetTriggerWay():
-            if curEffect.GetTriggerSrc() == 2:
+            if curEffect.GetTriggerSrc() != ChConfig.TriggerSrc_Skill:
                 passiveEffMgr.AddBuffPassiveEffect(addBuff, buffSkill, curEffect)
                 
         elif effectID in ChConfig.AttrIDList:
@@ -117,12 +145,24 @@
         
     return
 
-def DoBuffDel(turnFight, batObj, curBuff):
-    ## 删除buff
+def DoBuffDel(turnFight, batObj, curBuff, relatedSkill=None, afterLogic=False, tagObj=None):
+    '''删除buff
+    @param relatedSkill: 关联的技能
+    @param afterLogic: 是否需要在关联技能处理完毕后才处理删除后续逻辑,如通知,触发被动等
+    @param tagObj: 由谁引起的buff删除
+    '''
     
+    release = True
+    isSync = True
+    relatedSkillID = relatedSkill.GetSkillID() if relatedSkill else 0
+    if afterLogic and relatedSkill:
+        release = False
+        isSync = False
+        
     isRefreshAttr = False # 是否刷属性
     haveBuffPassiveEff = False
     
+    buffObjID = batObj.GetID()
     buffMgr = batObj.GetBuffManager()
     buffID = curBuff.GetBuffID()
     skillData = curBuff.GetSkillData()
@@ -135,7 +175,7 @@
             continue
         
         if curEffect.GetTriggerWay():
-            if curEffect.GetTriggerSrc() == 2:
+            if curEffect.GetTriggerSrc() != ChConfig.TriggerSrc_Skill:
                 haveBuffPassiveEff = True
                 
         elif effectID in ChConfig.AttrIDList:
@@ -149,16 +189,27 @@
     if haveBuffPassiveEff:
         batObj.GetPassiveEffManager().DelBuffPassiveEffect(buffID)
         
-    buffStates = skillData.GetBuffStates()
-    for buffState in buffStates:
-        buffMgr.DelBuffState(buffState, buffID)
+    curBuffState = skillData.GetCurBuffState()
+    if curBuffState:
+        buffMgr.DelBuffState(curBuffState, buffID)
         
     # 最后删除buff、通知
-    buffMgr.DelBuff(buffID)
-    SyncBuffDel(turnFight, batObj, buffID)
-    
+    buffMgr.DelBuff(buffID, release)
+    if isSync:
+        SyncBuffDel(turnFight, buffObjID, buffID, relatedSkillID)
+    if afterLogic and relatedSkill:
+        tagObjID = tagObj.GetID() if tagObj else buffObjID
+        relatedSkill.AddAfterLogic(ChConfig.AfterLogic_DelBuff, [buffObjID, curBuff, tagObjID])
+        
     if isRefreshAttr:
         RefreshBuffAttr(batObj)
+    return
+
+def DoBuffDelAfterLogicOver(turnFight, buffObjID, curBuff, relatedSkill):
+    ## buff删除后续处理逻辑处理完毕
+    relatedSkillID = relatedSkill.GetSkillID() if relatedSkill else 0
+    SyncBuffDel(turnFight, buffObjID, curBuff.GetBuffID(), relatedSkillID)
+    ObjPool.GetPoolMgr().release(curBuff)
     return
 
 def DoBuffProcess(turnFight, batObj, curBuff):
@@ -245,12 +296,15 @@
     clientPack.LastTime = curBuff.GetRemainTime()
     clientPack.Layer = curBuff.GetLayer()
     clientPack.OwnerID = curBuff.GetOwnerID()
+    clientPack.Value1 = curBuff.GetValue1()
+    clientPack.Value2 = curBuff.GetValue2()
+    clientPack.Value3 = curBuff.GetValue3()
     turnFight.addBatPack(clientPack)
     return
 
-def SyncBuffDel(turnFight, curBatObj, buffID, relatedSkillID=0):
+def SyncBuffDel(turnFight, objID, buffID, relatedSkillID=0):
     clientPack = ObjPool.GetPoolMgr().acquire(ChPyNetSendPack.tagSCBuffDel)
-    clientPack.ObjID = curBatObj.GetID()
+    clientPack.ObjID = objID
     clientPack.BuffID = buffID
     clientPack.RelatedSkillID = relatedSkillID
     turnFight.addBatPack(clientPack)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuffs/BuffAtkType_1001.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuffs/BuffAtkType_1001.py
index 5cdb4f1..485606d 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuffs/BuffAtkType_1001.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuffs/BuffAtkType_1001.py
@@ -16,19 +16,20 @@
 #-------------------------------------------------------------------------------
 
 import TurnSkill
+import ChConfig
 
-def CalcBuffValue(attacker, defender, curSkill):
+def CalcBuffValue(turnFight, attacker, defender, curSkill):
     #calcType = curSkill.GetCalcType()
     skillPer = curSkill.GetSkillPer()
     skillValue = curSkill.GetSkillValue()
     
-    hurtValue, hurtTypes = TurnSkill.CalcHurtHP(attacker, defender, curSkill, skillValue, skillPer, damageoftime=1)
-    return [hurtValue, hurtTypes]
+    hurtValue, hurtTypes = TurnSkill.CalcHurtHP(turnFight, attacker, defender, curSkill, skillValue, skillPer, damageoftime=1)
+    return [hurtValue % ChConfig.Def_PerPointValue, hurtValue / ChConfig.Def_PerPointValue, hurtTypes]
 
 def DoBuffProcess(turnFight, batObj, curBuff):
     ## 执行单次逻辑
-    hurtValue = curBuff.GetBuffValue(0) # 单次伤害
-    hurtTypes = curBuff.GetBuffValue(1)
+    hurtValue = curBuff.GetValue1() + curBuff.GetValue2() * ChConfig.Def_PerPointValue # 单次伤害
+    hurtTypes = curBuff.GetValue3()
     TurnSkill.DoDOTAttack(turnFight, batObj, curBuff, hurtValue, hurtTypes)
     return
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuffs/BuffAtkType_1003.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuffs/BuffAtkType_1003.py
new file mode 100644
index 0000000..f8077ad
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnBuffs/BuffAtkType_1003.py
@@ -0,0 +1,27 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Skill.TurnBuffs.BuffAtkType_1003
+#
+# @todo:承伤护盾
+# @author hxp
+# @date 2025-08-25
+# @version 1.0
+#
+# 详细描述: 承伤护盾
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2025-08-25 12:00"""
+#-------------------------------------------------------------------------------
+
+import TurnSkill
+import ChConfig
+
+def CalcBuffValue(turnFight, attacker, defender, curSkill):
+    calcType = curSkill.GetCalcType()
+    skillPer = curSkill.GetSkillPer()
+    skillValue = curSkill.GetSkillValue()
+    baseValue = TurnSkill.GetCalcBaseValue(calcType, attacker, defender)
+    shieldValue = int(baseValue * skillPer / 10000.0) + skillValue
+    return [shieldValue % ChConfig.Def_PerPointValue, shieldValue / ChConfig.Def_PerPointValue]
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnPassive.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnPassive.py
index c1e7a9b..5dfbcf4 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnPassive.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnPassive.py
@@ -31,31 +31,49 @@
     buffEffInfo and GameWorld.DebugLog("    被动Buff效果: %s" % buffEffInfo)
     return
 
-def OnTriggerPassiveEffect(turnFight, batObj, triggerType, connSkill=None):
+def OnTriggerPassiveEffect(turnFight, batObj, triggerType, tagObj=None, connSkill=None, connSkillTypeID=0):
     ''' 触发被动效果,可能触发技能、buff,需根据优先级触发
     '''
     passiveEffMgr = batObj.GetPassiveEffManager()
-    effInfoList = passiveEffMgr.GetPassiveEffByTrigger(triggerType, connSkill=connSkill)
+    if not connSkillTypeID and connSkill:
+        connSkillTypeID = connSkill.GetSkillTypeID()
+    effInfoList = passiveEffMgr.GetPassiveEffByTrigger(triggerType, connSkillTypeID)
     if not effInfoList:
         return
     # [["skill/buff", skillID/buffID, effIDList], ...]
-    GameWorld.DebugLog("触发被动: triggerType=%s,objID=%s,%s" % (triggerType, batObj.GetID(), effInfoList))
+    tagID = tagObj.GetID() if tagObj else 0
+    GameWorld.DebugLog("触发被动: triggerType=%s,objID=%s,tagID=%s,%s" % (triggerType, batObj.GetID(), tagID, effInfoList))
     for effInfo in effInfoList:
         sign = effInfo[0]
         if sign == "skill":
             skillID, effIDList = effInfo[1:]
-            __doTriggerPassiveEffectBySkill(turnFight, batObj, skillID, effIDList, connSkill)
+            __doTriggerPassiveEffectBySkill(turnFight, batObj, tagObj, skillID, effIDList, connSkill)
             
         elif sign == "buff":
             buffID, effIDList = effInfo[1:]
-            __doTriggerPassiveEffectByBuff(turnFight, batObj, buffID, effIDList, connSkill)
+            __doTriggerPassiveEffectByBuff(turnFight, batObj, tagObj, buffID, effIDList, connSkill)
             
     return
 
-def __doTriggerPassiveEffectBySkill(turnFight, batObj, skillID, effIDList, connSkill=None):
+def __doTriggerPassiveEffectBySkill(turnFight, batObj, tagObj, skillID, effIDList, connSkill=None):
+    skillMgr = batObj.GetSkillManager()
+    effSkill = skillMgr.FindSkillByID(skillID)
+    if not effSkill:
+        return
+    
+    for effID in effIDList:
+        curEffect = effSkill.GetEffectByID(effID)
+        if not curEffect:
+            continue
+        pyName = "PassiveEff_%s" % effID
+        callFunc = GameWorld.GetExecFunc(PassiveTrigger, "%s.%s" % (pyName, "DoSkillEffectLogic"))
+        if not callFunc:
+            continue
+        callFunc(turnFight, batObj, tagObj, effSkill, curEffect, connSkill)
+        
     return
 
-def __doTriggerPassiveEffectByBuff(turnFight, batObj, buffID, effIDList, connSkill=None):
+def __doTriggerPassiveEffectByBuff(turnFight, batObj, tagObj, buffID, effIDList, connSkill=None):
     buffMgr = batObj.GetBuffManager()
     curBuff = buffMgr.GetBuff(buffID)
     if not curBuff:
@@ -70,7 +88,7 @@
         callFunc = GameWorld.GetExecFunc(PassiveTrigger, "%s.%s" % (pyName, "DoBuffEffectLogic"))
         if not callFunc:
             continue
-        callFunc(turnFight, batObj, curBuff, curEffect, connSkill)
+        callFunc(turnFight, batObj, tagObj, curBuff, curEffect, connSkill)
         
     return
 
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 b35f747..5701a0c 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/TurnSkill.py
@@ -24,6 +24,7 @@
 import ChPyNetSendPack
 import PlayerControl
 import ShareDefine
+import TurnPassive
 import TurnAttack
 import TurnBuff
 import ObjPool
@@ -44,7 +45,7 @@
     ## 是否无视防御
     return useSkill.GetHurtType() / 10 == 1 # 2为真伤,待扩展
 
-def OnUseSkill(turnFight, curBatObj, useSkill, tagObjList=None, batType=ChConfig.TurnBattleType_Normal, bySkill=None, isEnhanceSkill=False):
+def OnUseSkill(turnFight, curBatObj, useSkill, tagObjList=None, batType=ChConfig.TurnBattleType_Normal, bySkill=None):
     '''使用技能通用入口
     @param useSkill: 使用的技能,注意并不一定是身上的技能,可能只是 SkillData 表数据
     @param bySkill: 由哪个技能额外触发的,比如附加触发的技能或被动技能均可能由某个技能触发
@@ -76,8 +77,8 @@
         return
     
     bySkillID = bySkill.GetSkillID() if bySkill else 0
-    GameWorld.DebugLog("使用技能: curID=%s,skillID=%s,tagCnt=%s,batType=%s,bySkillID=%s,isEnhanceSkill=%s" 
-                       % (curBatObj.GetID(), skillID, len(tagObjList), batType, bySkillID, isEnhanceSkill))
+    GameWorld.DebugLog("使用技能: curID=%s,skillID=%s,tagCnt=%s,batType=%s,bySkillID=%s" 
+                       % (curBatObj.GetID(), skillID, len(tagObjList), batType, bySkillID))
     # 以下为技能可以使用的处理,之后的逻辑默认技能使用成功
     
     poolMgr = ObjPool.GetPoolMgr()
@@ -87,11 +88,10 @@
         # 统一使用 BattleObj.PySkill
         useSkill = poolMgr.acquire(BattleObj.PySkill, useSkill)
         
+    useSkill.ResetUseRec()
     useSkill.SetTagObjList(tagObjList)
     useSkill.SetBatType(batType)
     useSkill.SetBySkill(bySkill)
-    useSkill.SetIsEnhanceSkill(isEnhanceSkill)
-    useSkill.ClearHurtObj()
     
     curBatObj.ClearSkillTempAttr()
     for tagObj in tagObjList:
@@ -99,7 +99,11 @@
         
     objID = curBatObj.GetID()
     useTag = ""
-    if not isEnhanceSkill:
+    
+    #这个技能是Buff
+    if SkillCommon.IsBuff(useSkill):
+        __doAddBuff(turnFight, curBatObj, useSkill)
+    else:
         # 因为可能触发连击,所以标记需带上累计使用技能次数,确保唯一
         useTag = "Skill_%s_%s_%s" % (objID, skillID, curBatObj.GetSkillUseCnt(skillID) + 1)
         clientPack = poolMgr.acquire(ChPyNetSendPack.tagSCTurnFightTag)
@@ -108,12 +112,10 @@
         clientPack.Sign = 0
         turnFight.addBatPack(clientPack)
         
-    #这个技能是Buff
-    if SkillCommon.IsBuff(useSkill):
-        __doAddBuff(turnFight, curBatObj, useSkill)
-    else:
         __doUseSkill(turnFight, curBatObj, useSkill)
         
+    DoAttackResult(turnFight, curBatObj, useSkill)
+    
     if useTag:
         clientPack = poolMgr.acquire(ChPyNetSendPack.tagSCTurnFightTag)
         clientPack.Tag = useTag
@@ -121,6 +123,9 @@
         clientPack.Sign = 1
         turnFight.addBatPack(clientPack)
         
+    # 处理反击 或 连击
+    DoCombo(turnFight, curBatObj, useSkill)
+    
     # 最后重置、回收对象
     useSkill.ResetUseRec()
     if usePoolSkill:
@@ -128,18 +133,28 @@
     return True
 
 def GetSkillTags(turnFight, curBatObj, tagAim, tagFriendly, tagAffect, tagCount):
-    ## 获取技能目标    
+    ## 获取技能目标
+    # @return: [主目标, 目标2, ...]
+    
     curFaction = curBatObj.GetFaction()
     
     # 自己,直接返回
     if tagAim == ChConfig.SkillTagAim_Self:
         return [curBatObj]
     
+    sneerObj = None # 嘲讽目标
+    sneerObjID, sneerObjPosNum = 0, 0
     if tagFriendly:
         tagFaction = curFaction
     else:
         tagFaction = ChConfig.Def_FactionB if curFaction == ChConfig.Def_FactionA else ChConfig.Def_FactionA
-        
+        sneerObj = curBatObj.GetSneerTagObj() # 被嘲讽的目标,对敌的强制锁定被嘲讽目标
+                
+    sneerObjFirst = True # 嘲讽目标优先
+    if sneerObj:
+        sneerObjID = sneerObj.GetID()
+        sneerObjPosNum = sneerObj.GetPosNum()
+    
     batObjMgr = BattleObj.GetBatObjMgr()
     lineupNum = curBatObj.GetLineupNum()
     posNum = curBatObj.GetPosNum()
@@ -159,123 +174,224 @@
         
         # 对位
         if tagAim == ChConfig.SkillTagAim_Relative:
-            posNumList = [posNum] # 优先对位位置,再其他位置按顺序遍历
-            pNumList = batLineup.posObjIDDict.keys()
-            pNumList.sort()
-            for pNum in pNumList:
-                if pNum > 0 and pNum not in posNumList:
-                    posNumList.append(pNum)
-            for pNum in posNumList:
-                if pNum not in batLineup.posObjIDDict:
-                    continue
-                tagObjID = batLineup.posObjIDDict[pNum]
-                tagBatObj = batObjMgr.getBatObj(tagObjID)
-                if not __skillTagFilter(tagBatObj, tagAffect):
-                    continue
-                aimObjList.append(tagBatObj) # 对位的默认只选1个
-                break
-            
+            if sneerObj:
+                aimObjList.append(sneerObj)
+            else:
+                relativeObj = __GetRelativeObjDefault(batObjMgr, curBatObj, posNum, batLineup)
+                if relativeObj:
+                    aimObjList.append(relativeObj)
+                    
         # 前排
         elif tagAim == ChConfig.SkillTagAim_FrontRow:
-            # 优先前排,如果没有则后排亦是前排
-            for pNumList in [[1, 2, 3], [4, 5, 6]]:
-                hasObj = False
-                for pNum in pNumList:
-                    if pNum not in batLineup.posObjIDDict:
-                        continue
-                    tagObjID = batLineup.posObjIDDict[pNum]
-                    tagBatObj = batObjMgr.getBatObj(tagObjID)
-                    if not __skillTagFilter(tagBatObj, tagAffect):
-                        continue
-                    hasObj = True
-                    aimObjList.append(tagBatObj)
-                if hasObj:
-                    break
-                
+            aimObjList = __getRowAimObjList(batObjMgr, posNum, sneerObj, batLineup, tagAffect, False)
+            
         # 后排
         elif tagAim == ChConfig.SkillTagAim_BackRow:
-            # 优先后排,如果没有则前排亦是后排
-            for pNumList in [[4, 5, 6], [1, 2, 3]]:
-                hasObj = False
-                for pNum in pNumList:
-                    if pNum not in batLineup.posObjIDDict:
-                        continue
-                    tagObjID = batLineup.posObjIDDict[pNum]
-                    tagBatObj = batObjMgr.getBatObj(tagObjID)
-                    if not __skillTagFilter(tagBatObj, tagAffect):
-                        continue
-                    hasObj = True
-                    aimObjList.append(tagBatObj)
-                if hasObj:
-                    break
-                
+            aimObjList = __getRowAimObjList(batObjMgr, posNum, sneerObj, batLineup, tagAffect, True)
+            
         # 竖排/纵排
         elif tagAim == ChConfig.SkillTagAim_Vertical:
-            verticalNumList = [[1, 4], [2, 5], [3, 6]]
-            for pNumList in verticalNumList:
-                # 优先对位排
-                if posNum in pNumList:
-                    verticalNumList.remove(pNumList)
-                    verticalNumList.insert(0, pNumList)
-                    break
-            for pNumList in verticalNumList:
-                hasObj = False
-                for pNum in pNumList:
+            # 优先自己所在纵
+            inColNum = ChConfig.GetInColNum(posNum)
+            colNumList = range(1, 1 + ChConfig.TurnFightCols)
+            if inColNum in colNumList:
+                colNumList.remove(inColNum)
+                colNumList.insert(0, inColNum)
+                
+            # 优先嘲讽所在纵
+            if sneerObj:
+                sneerInColNum = ChConfig.GetInColNum(sneerObjPosNum)
+                if sneerInColNum in colNumList:
+                    colNumList.remove(sneerInColNum)
+                    colNumList.insert(0, sneerInColNum)
+                    
+            GameWorld.DebugLog("纵排: colNumList=%s,sneerObjID-PosNum=%s-%s" % (colNumList, sneerObjID, sneerObjPosNum))
+            for col in colNumList:
+                for row in range(1, 1 + ChConfig.TurnFightRows):
+                    pNum = (row - 1) * ChConfig.TurnFightCols + col
+                    #GameWorld.DebugLog("    col=%s,row=%s,pNum=%s" % (col, row, pNum))
                     if pNum not in batLineup.posObjIDDict:
                         continue
                     tagObjID = batLineup.posObjIDDict[pNum]
                     tagBatObj = batObjMgr.getBatObj(tagObjID)
                     if not __skillTagFilter(tagBatObj, tagAffect):
                         continue
-                    hasObj = True
                     aimObjList.append(tagBatObj)
-                if hasObj:
+                if aimObjList:
                     break
                 
         # 其他,默认全部
         else:
-            pNumList = batLineup.posObjIDDict.keys()
-            for pNum in pNumList:
-                if pNum <= 0:
-                    continue
-                tagObjID = batLineup.posObjIDDict[pNum]
-                tagBatObj = batObjMgr.getBatObj(tagObjID)
-                if not __skillTagFilter(tagBatObj, tagAffect):
-                    continue
-                aimObjList.append(tagBatObj)
+            inColNum = ChConfig.GetInColNum(posNum) # 玩家所在纵列
+            # 优先自己所在纵
+            colNumList = range(1, 1 + ChConfig.TurnFightCols)
+            if inColNum in colNumList:
+                colNumList.remove(inColNum)
+                colNumList.insert(0, inColNum)
                 
+            GameWorld.DebugLog("全部: colNumList=%s,sneerObjID-PosNum=%s-%s" % (colNumList, sneerObjID, sneerObjPosNum))
+            # 按前排优先原则
+            for row in range(1, 1 + ChConfig.TurnFightRows):
+                for col in colNumList:
+                    pNum = (row - 1) * ChConfig.TurnFightCols + col
+                    #GameWorld.DebugLog("    col=%s,row=%s,pNum=%s" % (col, row, pNum))
+                    if pNum not in batLineup.posObjIDDict:
+                        continue
+                    tagObjID = batLineup.posObjIDDict[pNum]
+                    tagBatObj = batObjMgr.getBatObj(tagObjID)
+                    if not __skillTagFilter(tagBatObj, tagAffect):
+                        continue
+                    aimObjList.append(tagBatObj)
+                    
     # 目标细分
     # 血量最低
     if tagAffect == ChConfig.SkillTagAffect_HPLowest:
         aimObjList.sort(key=lambda o:(o.GetHP()), reverse=False)
         #GameWorld.DebugLog("血量最低排序: %s" % [[o.GetID(), o.GetHP(), o.GetMaxHP()] for o in aimObjList])
-        aimObjList = aimObjList[:tagCount]
         
     # 血量最高
     elif tagAffect == ChConfig.SkillTagAffect_HPHighest:
         aimObjList.sort(key=lambda o:(o.GetHP()), reverse=True)
         #GameWorld.DebugLog("血量最高排序: %s" % [[o.GetID(), o.GetHP(), o.GetMaxHP()] for o in aimObjList])
-        aimObjList = aimObjList[:tagCount]
+        
+    # 未被控制优先
+    elif tagAffect == ChConfig.SkillTagAffect_UncontrolledPriority:
+        sneerObjFirst = False
+        aimObjList.sort(key=lambda o:(o.IsInControlled()))
+        GameWorld.DebugLog("未被控制优先: %s" % [[o.GetID(), o.IsInControlled()] for o in aimObjList])
         
     else:
         # 范围目标超过个数,则随机取
         if tagCount and len(aimObjList) > tagCount:
             random.shuffle(aimObjList)
-            aimObjList = aimObjList[:tagCount]
             
+    # 嘲讽优先
+    if sneerObjFirst and sneerObj:
+        if sneerObj in aimObjList and aimObjList.index(sneerObj) != 0:
+            aimObjList.remove(sneerObj)
+            aimObjList.insert(0, sneerObj)
+            
+    if tagCount and len(aimObjList) > tagCount:
+        aimObjList = aimObjList[:tagCount]
+        
     return aimObjList
+
+def __getRowAimObjList(batObjMgr, posNum, sneerObj, batLineup, tagAffect, rowReverse):
+    ## 获取行排目标对象列表
+    # @param rowReverse: 是否后排优先原则
+    
+    # 前后排顺序
+    if rowReverse:
+        rowNumList = range(1, 1 + ChConfig.TurnFightRows)[::-1]
+    else:
+        rowNumList = range(1, 1 + ChConfig.TurnFightRows)
+        
+    # 优先嘲讽对象所在行
+    sneerObjID, sneerObjPosNum = 0, 0
+    if sneerObj:
+        sneerObjID = sneerObj.GetID()
+        sneerObjPosNum = sneerObj.GetPosNum()
+        sneerInRowNum = ChConfig.GetInRowNum(sneerObjPosNum) # 所在行排
+        if sneerInRowNum in rowNumList:
+            rowNumList.remove(sneerInRowNum)
+            rowNumList.insert(0, sneerInRowNum)
+            
+    inColNum = ChConfig.GetInColNum(posNum) # 玩家所在纵列
+    # 优先自己所在纵,为主目标
+    colNumList = range(1, 1 + ChConfig.TurnFightCols)
+    if inColNum in colNumList:
+        colNumList.remove(inColNum)
+        colNumList.insert(0, inColNum)
+        
+    GameWorld.DebugLog("前后排: rowNumList=%s,colNumList=%s,sneerObjID-PosNum=%s-%s" % (rowNumList, colNumList, sneerObjID, sneerObjPosNum))
+    aimObjList = []
+    for row in rowNumList:
+        for col in colNumList:
+            pNum = (row - 1) * ChConfig.TurnFightCols + col
+            #GameWorld.DebugLog("    row=%s,col=%s,pNum=%s" % (row, col, pNum))
+            if pNum not in batLineup.posObjIDDict:
+                continue
+            tagObjID = batLineup.posObjIDDict[pNum]
+            tagBatObj = batObjMgr.getBatObj(tagObjID)
+            if not __skillTagFilter(tagBatObj, tagAffect):
+                continue
+            aimObjList.append(tagBatObj)
+        if aimObjList:
+            break
+        
+    return aimObjList
+
+def GetRelativeObj(turnFight, curBatObj):
+    '''获取对位目标,嘲讽时优先对位嘲讽目标
+    对位目标用途: 
+    1. 对位目标并不代表仅攻击该目标
+    2. 攻击时根据技能攻击目标范围优先攻击对位目标所在的横排或纵排
+    3. 对位目标可用于判断连击、弱疗
+    '''
+    sneerObj = curBatObj.GetSneerTagObj()
+    if sneerObj:
+        # 有嘲讽目标优先直接对位
+        return sneerObj
+    
+    curFaction = curBatObj.GetFaction()
+    # 默认对位敌对阵营
+    tagFaction = ChConfig.Def_FactionB if curFaction == ChConfig.Def_FactionA else ChConfig.Def_FactionA
+    
+    batObjMgr = BattleObj.GetBatObjMgr()
+    lineupNum = curBatObj.GetLineupNum()
+    posNum = curBatObj.GetPosNum()
+    
+    batFaction = turnFight.getBatFaction(tagFaction)
+    lineupNumList = [lineupNum] # 敌方优先对位阵容,再其他阵容,支持多阵容对战
+    for tagNum in batFaction.lineupDict.keys():
+        if tagNum not in lineupNumList:
+            lineupNumList.append(tagNum)
+            
+    for num in lineupNumList:
+        batLineup = batFaction.getBatlineup(num)
+        relativeObj = __GetRelativeObjDefault(batObjMgr, curBatObj, posNum, batLineup)
+        if relativeObj:
+            return relativeObj
+        
+    # 理论上只要战斗没有结束,一定会有对位目标,这里默认返回自己,外层可不需要判断是否存在对位目标
+    return curBatObj
+
+def __GetRelativeObjDefault(batObjMgr, curBatObj, posNum, batLineup):
+    ## 获取在某一阵营中的默认对位目标
+    
+    tagAffect = ChConfig.SkillTagAffect_None # 默认对位目标不需要细分目标,默认规则即可
+    inColNum = ChConfig.GetInColNum(posNum) # 玩家所在纵列
+    # 优先自己所在纵
+    colNumList = range(1, 1 + ChConfig.TurnFightCols)
+    if inColNum in colNumList:
+        colNumList.remove(inColNum)
+        colNumList.insert(0, inColNum)
+        
+    # 按前排优先原则
+    for row in range(ChConfig.TurnFightRows):
+        for col in colNumList:
+            pNum = row * ChConfig.TurnFightCols + col
+            if pNum not in batLineup.posObjIDDict:
+                continue
+            tagObjID = batLineup.posObjIDDict[pNum]
+            tagBatObj = batObjMgr.getBatObj(tagObjID)
+            if not __skillTagFilter(tagBatObj, tagAffect):
+                continue
+            return tagBatObj
+        
+    return
 
 def __skillTagFilter(tagBatObj, tagAffect):
     ## 技能目标过滤器
     # @return: 是否允许添加该单位
     if not tagBatObj:
         return False
-    if tagAffect != ChConfig.SkillTagAffect_Death and tagBatObj.GetHP() <= 0:
+    if tagAffect != ChConfig.SkillTagAffect_Death and not tagBatObj.IsAlive():
         return False
-    if tagAffect == ChConfig.SkillTagAffect_Death and tagBatObj.GetHP() > 0:
+    if tagAffect == ChConfig.SkillTagAffect_Death and tagBatObj.IsAlive():
         return False
-    if not tagBatObj.GetCanAttack():
-        return False
+    #if not tagBatObj.GetCanAttack(): 策划要求不可攻击的对象也要可选中
+    #    return False
     return True
 
 def __doAddBuff(turnFight, curBatObj, useSkill):
@@ -284,7 +400,6 @@
     for tagBatObj in useSkill.GetTagObjList():
         TurnBuff.OnAddBuff(turnFight, tagBatObj, useSkill, buffOwner=curBatObj)
         
-    DoAttackResult(turnFight, curBatObj, useSkill)
     return
 
 def __doUseSkill(turnFight, curBatObj, useSkill):
@@ -294,50 +409,36 @@
     # 通用攻击
     if atkType == 1:
         SkillModule_1(turnFight, curBatObj, useSkill)
-        return
-    
     # 治疗
     if atkType == 2:
         SkillModule_2(turnFight, curBatObj, useSkill)
-        return
-    
     # 复活
-    if atkType == 3:
-        return
-    
+    elif atkType == 3:
+        pass
     # 多次攻击(锁目标多次伤害,非前端的多段飘血)
-    if atkType == 4:
-        return
-    
+    elif atkType == 4:
+        pass
     # 弹射(多次攻击,切换目标)
-    if atkType == 5:
-        return
-    
+    elif atkType == 5:
+        pass
     # 怒气增
-    if atkType == 6:
+    elif atkType == 6:
         SkillModule_6(turnFight, curBatObj, useSkill, "Increase")
-        return
-    
     # 怒气减
-    if atkType == 7:
+    elif atkType == 7:
         SkillModule_6(turnFight, curBatObj, useSkill, "Reduce")
-        return
-    
     # 怒气偷
-    if atkType == 8:
+    elif atkType == 8:
         SkillModule_6(turnFight, curBatObj, useSkill, "Steal")
-        return
-    
+        
     return
 
 def SkillModule_1(turnFight, curBatObj, useSkill):
     ## 通用攻击,单攻、群攻
     
-    #执行攻击结果
     for tagBatObj in useSkill.GetTagObjList():
-        __doSkillHurtHP(curBatObj, tagBatObj, useSkill)
+        __doSkillHurtHP(turnFight, curBatObj, tagBatObj, useSkill)
         
-    DoAttackResult(turnFight, curBatObj, useSkill)
     return
 
 def SkillModule_2(turnFight, curBatObj, useSkill):
@@ -366,7 +467,6 @@
         
         TurnAttack.AddTurnObjCureHP(tagBatObj, curBatObj, cureHP, realCureHP, skillID)
         
-    DoAttackResult(turnFight, curBatObj, useSkill)
     return
 
 def SkillModule_6(turnFight, curBatObj, useSkill, opType):
@@ -432,7 +532,6 @@
         GameWorld.DebugLog("    加总怒气: curID=%s,curStealTotal=%s,curXP=%s,updXP=%s" % (curID, curStealTotal, curXP, updValue))
         Sync_PropertyRefreshView(turnFight, curBatObj, attrID, updValue, diffValue, diffType, skillID, relatedSkillID)
         
-    DoAttackResult(turnFight, curBatObj, useSkill)
     return
 
 def DoAttackResult(turnFight, curBatObj, useSkill):
@@ -451,52 +550,192 @@
         useSkill.SetCalcTime(turnFight.getTimeline())
         useSkill.SetRemainTime(useSkill.GetCoolDownTime())
         
-    # 需先通知伤血 - 前端按顺序优先表现技能释放内容,
-    isEnhanceSkill = useSkill.GetIsEnhanceSkill()
-    if not isEnhanceSkill or len(useSkill.GetHurtObjList()):
+    # 需先技能使用 - 前端按顺序优先表现技能释放内容,前端需要动作或有伤血则通知
+    if useSkill.GetSkillMotionName() or len(useSkill.GetHurtObjList()):
         Sync_UseSkill(turnFight, curBatObj, useSkill)
-    if not isEnhanceSkill:
-        __doCostZhanchui(turnFight, curBatObj, useSkill)
-        __doSkillUserAnger(turnFight, curBatObj, useSkill)
         
-    DoBeAttackOver(turnFight, curBatObj, useSkill)
+    __doCostZhanchui(turnFight, curBatObj, useSkill)
+    __doSkillUserAnger(turnFight, curBatObj, useSkill)
     
-    # 最后处理反击 或 连击
-    
+    DoBeAttackResult(turnFight, curBatObj, useSkill)
     return
 
-def DoBeAttackOver(turnFight, curBatObj, useSkill):
-    '''被攻击结果
-    @param curBatObj: 施法方或buff归属方
+def DoCombo(turnFight, curBatObj, useSkill):
+    '''
+        格挡、反击、连击规则
+        1. 所有武将或怪物均可能产生格挡,群攻时格挡一对一判断,均可能产生格挡
+        2. 仅普攻时可被反击,反判断本次技能目标中的主目标(即对位目标)是否产生格挡,且是近战武将,是的话可反击
+        
+        连击:
+        1. 仅普攻可连击,反击打断连击
+        2. 非对敌技能,如奶妈回血普攻,判断对位目标抗连属性是否可连击
+        3. 对敌技能,判断本次技能目标中的主目标(即对位目标)抗连属性是否可连击
+        
+        对敌技能主目标:
+                单体: 默认该目标
+                嘲讽: 优先被嘲讽的目标
+                横排: 优先该排中与自己同列的,否则按顺序
+                纵排: 优先前面的单位
     '''
     
+    if not SkillCommon.isTurnNormalSkill(useSkill):
+        #GameWorld.DebugLog("非普攻不处理反击连击")
+        return
+    
+    tagFriendly = useSkill.GetTagFriendly()
+    if tagFriendly:
+        tagObj = GetRelativeObj(turnFight, curBatObj)
+    else:
+        tagObjList = useSkill.GetTagObjList()
+        if not tagObjList:
+            return
+        tagObj = tagObjList[0] # 第一个默认为主目标,技能对象选择逻辑时决定主目标
+        atkBackSkill = __getCanAtkBackSkill(useSkill, tagObj)
+        if atkBackSkill:
+            # 可以反击,打断连击
+            GameWorld.DebugLog("● %s 【反击】" % TurnAttack.GetObjName(tagObj))
+            OnUseSkill(turnFight, tagObj, atkBackSkill, [curBatObj], ChConfig.TurnBattleType_AtkBack)
+            return
+        
+    if not tagObj:
+        return
+    
+    if CanCombo(curBatObj, tagObj):
+        # 连击根据技能目标配置逻辑重新选择目标
+        GameWorld.DebugLog("● %s 【连击】" % TurnAttack.GetObjName(curBatObj))
+        OnUseSkill(turnFight, curBatObj, useSkill, batType=ChConfig.TurnBattleType_Combo)
+        
+    return
+
+def __getCanAtkBackSkill(useSkill, tagObj):
+    ## 获取是否可反击及反击技能
+    if not tagObj:
+        return
+    
+    tagID = tagObj.GetID()
+    if tagObj.GetAtkDistType() != ChConfig.AtkDistType_Short:
+        GameWorld.DebugLog("非近战不可反击! tagID=%s" % tagID)
+        return
+    
+    canAtkBack = False
+    for hurtObj in useSkill.GetHurtObjList():
+        if hurtObj.GetObjID() != tagID:
+            continue
+        if hurtObj.HaveHurtType(ChConfig.HurtType_Parry): # 格挡时可反击
+            canAtkBack = True
+            break
+        
+    if not canAtkBack:
+        GameWorld.DebugLog("没有格挡不可反击! tagID=%s" % tagID)
+        return
+    
+    skillManager = tagObj.GetSkillManager()
+    for index in range(0, skillManager.GetSkillCount()):
+        useSkill = skillManager.GetSkillByIndex(index)
+        if not useSkill:
+            continue
+        if useSkill.GetFuncType() == ChConfig.Def_SkillFuncType_AtkbackSkill:
+            GameWorld.DebugLog("可以反击! tagID=%s" % tagID)
+            return useSkill
+    return
+
+def CanCombo(atkObj, defObj):
+    ## 可否连击
+    comboNum = atkObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnComboNum)
+    aComboRate = atkObj.GetBatAttrValue(ChConfig.AttrID_ComboRate)
+    dComboRateDef = defObj.GetBatAttrValue(ChConfig.AttrID_ComboRateDef)
+    happenRate = eval(IpyGameDataPY.GetFuncCompileCfg("ComboCfg", 1))
+    if GameWorld.CanHappen(happenRate):
+        GameWorld.DebugLog("可以连击! atkID=%s,happenRate=%s,aComboRate=%s,dComboRateDef=%s,comboNum=%s" 
+                           % (atkObj.GetID(), happenRate, aComboRate, dComboRateDef, comboNum))
+        atkObj.SetDict(ChConfig.Def_Obj_Dict_TurnComboNum, comboNum + 1)
+        return True
+    GameWorld.DebugLog("无法连击! atkID=%s,happenRate=%s,aComboRate=%s,dComboRateDef=%s,comboNum=%s" 
+                       % (atkObj.GetID(), happenRate, aComboRate, dComboRateDef, comboNum))
+    return False
+
+def DoBeAttackResult(turnFight, curObj, useSkill):
+    '''被攻击结果
+    @param curObj: 施法方或buff归属方
+    '''
+    
+    curID = curObj.GetID()
     isTurnNormalSkill = SkillCommon.isTurnNormalSkill(useSkill)
     isAngerSkill = SkillCommon.isAngerSkill(useSkill)
     
-    # 统计死亡
+    batObjMgr = BattleObj.GetBatObjMgr()
+    
+    # 优先处理afterLogic,可再预先汇总一些会触发被动的信息
+    relatedSkillID = useSkill.GetSkillID()
+    shieldBrokenList = [] # 记录盾破
+    afterLogicList = useSkill.GetAfterLogicList()
+    for logicType, logicData in afterLogicList:
+        if logicType == ChConfig.AfterLogic_DelBuff:
+            buffObjID, buff, tagObjID = logicData
+            buffSkillData = buff.GetSkillData()
+            buffSkillTypeID = buffSkillData.GetSkillTypeID()
+            TurnBuff.DoBuffDelAfterLogicOver(turnFight, buffObjID, buff, useSkill)
+            if SkillCommon.isDamageShieldSkill(buffSkillData):
+                shieldBrokenList.append([buffObjID, tagObjID, buffSkillTypeID])
+                
+        elif logicType == ChConfig.AfterLogic_AddBuff:
+            batObj, buff, _ = logicData
+            TurnBuff.SyncBuffRefresh(turnFight, batObj, buff, relatedSkillID)
+            
+        elif logicType == ChConfig.AfterLogic_SyncBuff:
+            buffObj, buff, _, _ = logicData
+            TurnBuff.SyncBuffRefresh(turnFight, buffObj, buff, relatedSkillID)
+            
+    # 统计结果
     killObjIDList = [] # 击杀的目标ID列表
     for tagObj in useSkill.GetTagObjList():
         tagID = tagObj.GetID()
-        # 可能单个技能对同一目标造成多次伤害,所以这里遍历,如弹射等
-        for hurtObj in useSkill.GetHurtObjList():
-            if hurtObj.GetObjID() == tagID and not hurtObj.HaveHurtType(ChConfig.HurtTYpe_Recovery) and (isTurnNormalSkill or isAngerSkill):
-                __doSkillHurtAnger(tagObj, hurtObj.GetLostHP(), useSkill)
-        if tagObj.GetHP() <= 0:
+        if tagObj.IsAlive() and tagObj.GetHP() <= 0:
             killObjIDList.append(tagID)
-            TurnAttack.SetObjKilled(turnFight, tagObj, curBatObj, useSkill)
-    if curBatObj and curBatObj.GetHP() <= 0:
-        TurnAttack.SetObjKilled(turnFight, curBatObj)
+            TurnAttack.SetObjKilled(turnFight, tagObj, curObj, useSkill)
+    if curObj and curObj.IsAlive() and curObj.GetHP() <= 0:
+        TurnAttack.SetObjKilled(turnFight, curObj)
         
+    # 可能单个技能对同一目标造成多次伤害
+    missObjIDList = []
+    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():
+            __doSkillHurtAnger(tagObj, hurtObj.GetLostHP(), useSkill)
+        if hurtObj.HaveHurtType(ChConfig.HurtType_Miss):
+            missObjIDList.append(hurtObjID)
+            
     # 结算副本相关的攻击结果,仅主动发起玩家阵容武将触发
     curPlayer = turnFight.curPlayer
-    if curPlayer and curBatObj and curBatObj.GetOwnerID() == curPlayer.GetPlayerID():
-        FBLogic.OnPlayerLineupAttackResult(curPlayer, curBatObj, killObjIDList, useSkill, turnFight.mapID, turnFight.funcLineID)
-        
+    if curPlayer and curObj and curObj.GetOwnerID() == curPlayer.GetPlayerID():
+        FBLogic.OnPlayerLineupAttackResult(curPlayer, curObj, killObjIDList, useSkill, turnFight.mapID, turnFight.funcLineID)
+            
     # 额外触发技能
-    __doUseEnhanceSkill(turnFight, curBatObj, useSkill)
+    __doUseEnhanceSkill(turnFight, curObj, useSkill)
     
-    # 循环触发被动,待扩展
+    # ========== 以下触发被动 ==========
     
+    # 破盾时
+    for buffObjID, tagObjID, buffSkillTypeID in shieldBrokenList:
+        buffObj = batObjMgr.getBatObj(buffObjID)
+        tagObj = batObjMgr.getBatObj(tagObjID)
+        TurnPassive.OnTriggerPassiveEffect(turnFight, buffObj, ChConfig.TriggerWay_ShieldBroken, tagObj, connSkillTypeID=buffSkillTypeID)
+        
+    for tagObj in useSkill.GetTagObjList():
+        tagID = tagObj.GetID()
+        if tagID == curID or tagID in missObjIDList:
+            # 自己或对方闪避了不再触发被动
+            continue
+        
+        TurnPassive.OnTriggerPassiveEffect(turnFight, curObj, ChConfig.TriggerWay_AttackOverTagInState, tagObj, connSkill=useSkill)
+        # 直接攻击
+        if not SkillCommon.IsBuff(useSkill):
+            TurnPassive.OnTriggerPassiveEffect(turnFight, curObj, ChConfig.TriggerWay_AttackOverDirect, tagObj, connSkill=useSkill)
+            TurnPassive.OnTriggerPassiveEffect(turnFight, tagObj, ChConfig.TriggerWay_BeAttackedDirect, curObj, connSkill=useSkill)
+            
     return
 
 def __doCostZhanchui(turnFight, curBatObj, useSkill):
@@ -573,15 +812,13 @@
 def __doUseEnhanceSkill(turnFight, curBatObj, useSkill):
     if not curBatObj:
         return
-    if useSkill.GetIsEnhanceSkill():
+    if useSkill.GetBatType() == ChConfig.TurnBattleType_Enhance:
         #GameWorld.DebugLog("自身为额外触发的技能不再触发额外技能! skillID=%s" % useSkill.GetSkillID())
         return
     enhanceSkillIDList = useSkill.GetEnhanceSkillList()
     if not enhanceSkillIDList:
         return
     GameWorld.DebugLog("额外触发的技能! skillID=%s,enhanceSkillIDList=%s" % (useSkill.GetSkillID(), enhanceSkillIDList))
-    # 根据触发技能的特点决定是触发一次还是 触发多次
-    # 群体BUFF的请参考 IsPlayerUseSkill 客户端决定对象,一样可以实现同样效果
     tagObjList = useSkill.GetTagObjList()
     for enhanceSkillID in enhanceSkillIDList:
         enhanceSkillData = IpyGameDataPY.GetIpyGameData("Skill", enhanceSkillID)
@@ -589,7 +826,7 @@
             continue
         # 继承主技能目标
         if enhanceSkillData.GetTagAim() == ChConfig.SkillTagAim_MainSkill:
-            GameWorld.DebugLog("    额外触发技能,继承主技能目标! enhanceSkillID=%s" % enhanceSkillID)
+            GameWorld.DebugLog("额外触发技能,继承主技能目标! enhanceSkillID=%s" % enhanceSkillID)
             # 额外触发的技能直接在外层检查概率,如果都没有触发则不需要再处理
             enhanceRate = enhanceSkillData.GetHappenRate()
             enchanceTagObjList = []
@@ -602,7 +839,7 @@
                 for hurtObj in useSkill.GetHurtObjList():
                     if hurtObj.GetObjID() != tagID:
                         continue
-                    if not hurtObj.GetHurtHP() or hurtObj.HaveHurtType(ChConfig.HurtType_Miss):
+                    if hurtObj.HaveHurtType(ChConfig.HurtType_Miss):
                         continue
                     inHurt = True
                     break
@@ -616,16 +853,16 @@
                 enchanceTagObjList.append(tagObj)
                 
             if enchanceTagObjList:
-                OnUseSkill(turnFight, curBatObj, enhanceSkillData, enchanceTagObjList, bySkill=useSkill, isEnhanceSkill=True)
+                OnUseSkill(turnFight, curBatObj, enhanceSkillData, enchanceTagObjList, batType=ChConfig.TurnBattleType_Enhance, bySkill=useSkill)
                 
             continue
         
-        GameWorld.DebugLog("    额外触发技能,重新锁定目标! enhanceSkillID=%s" % enhanceSkillID)
-        OnUseSkill(turnFight, curBatObj, enhanceSkillData, bySkill=useSkill, isEnhanceSkill=True)
+        GameWorld.DebugLog("额外触发技能,重新锁定目标! enhanceSkillID=%s" % enhanceSkillID)
+        OnUseSkill(turnFight, curBatObj, enhanceSkillData, batType=ChConfig.TurnBattleType_Enhance, bySkill=useSkill)
         
     return
 
-def __doSkillHurtHP(attacker, defObj, curSkill):
+def __doSkillHurtHP(turnFight, attacker, defObj, curSkill):
     ## 执行技能伤血,只计算伤血,其他逻辑等技能同步后再处理
     # @return: None - 没有执行成功,即忽略该目标
     
@@ -647,33 +884,32 @@
         pass
     
     else:
-        hurtValue, hurtTypes = CalcHurtHP(atkObj, defObj, curSkill, atkSkillValue, atkSkillPer)
-        
-        # 各种减伤 吸收盾处理
-        #hurtValue = CalcHurtHPWithBuff(atkObj, defObj, hurtValue, curSkill, tick)
+        hurtValue, hurtTypes = CalcHurtHP(turnFight, atkObj, defObj, curSkill, atkSkillValue, atkSkillPer)
+        hurtValue, realHurtHP = CalcHurtHPWithBuff(turnFight, atkObj, defObj, curSkill, hurtValue)
         
         #伤害结构体
         hurtObj.SetHurtTypes(hurtTypes)
         hurtObj.SetHurtHP(hurtValue)
-        remainHP = min(dMaxHP, max(0, dHP - hurtValue)) # 剩余血量
+        hurtObj.SetRealHurtHP(realHurtHP)
+        remainHP = min(dMaxHP, max(0, dHP - realHurtHP)) # 剩余血量
         
     remainHP = int(remainHP)    #防范
     lostHP = dHP - remainHP # 实际掉血量
     hurtObj.SetLostHP(lostHP)
     hurtObj.SetCurHP(remainHP)
     defObj.SetHP(remainHP)
-    GameWorld.DebugLog("    伤血: atkID=%s,defID=%s,hurtValue=%s,lostHP=%s,%s/%s" % (atkID, defID, hurtValue, lostHP, defObj.GetHP(), defObj.GetMaxHP()))
+    GameWorld.DebugLog("    伤血: atkID=%s,defID=%s,hurtValue=%s,realHurtHP=%s,lostHP=%s,%s/%s" 
+                       % (atkID, defID, hurtValue, realHurtHP, lostHP, defObj.GetHP(), defObj.GetMaxHP()))
+    TurnAttack.AddTurnObjHurtValue(atkObj, defObj, hurtValue, lostHP, skillID)
     
     #反弹伤害
-    CalcBounceHP(atkObj, defObj, hurtObj, curSkill)
+    CalcBounceHP(turnFight, atkObj, defObj, hurtObj, curSkill)
     
     #吸血
     CalcSuckBlood(atkObj, defObj, hurtObj, curSkill)
-    
-    TurnAttack.AddTurnObjHurtValue(atkObj, defObj, hurtValue, lostHP, skillID)
     return
 
-def CalcHurtHP(atkObj, defObj, curSkill, atkSkillValue, atkSkillPer, **kwargs):
+def CalcHurtHP(turnFight, atkObj, defObj, curSkill, atkSkillValue, atkSkillPer, **kwargs):
     '''计算伤害,默认按攻击计算
     '''
     pmType = GetPMType(atkObj, curSkill)
@@ -696,6 +932,9 @@
         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:
         aMissRateDef = atkObj.GetBatAttrValue(ChConfig.AttrID_MissRateDef) #atkObj.GetHit() # 抗闪避率 - 命中
@@ -703,19 +942,26 @@
         missNum = defObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnMissNum)
         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)
             return 0, pow(2, ChConfig.HurtType_Miss)
         
     hurtTypes = pow(2, ChConfig.HurtType_Normal)
     
     #calcType = curSkill.GetCalcType() 目前暂时按攻击算伤害,之后可以扩展其他
     
-    isSuperHit = False # 是否暴击
-    if isDot:
-        isSuperHit = False
+    isSuperHit, isParry = False, False
+    aSuperDamPer, dSuperDamPerDef = 0, 0
+    if not isDot:
+        isSuperHit = CanSuperHit(atkObj, defObj) # 是否暴击
+        isParry = (isTurnNormalSkill and CanParry(atkObj, defObj)) # 是否格挡,仅针对普攻
+        CanStun(turnFight, atkObj, defObj, curSkill) # 是否击晕
+        
     if isSuperHit:
         hurtTypes |= pow(2, ChConfig.HurtType_SuperHit)
+        aSuperDamPer = atkObj.GetBatAttrValue(ChConfig.AttrID_SuperDamPer)
+        dSuperDamPerDef = atkObj.GetBatAttrValue(ChConfig.AttrID_SuperDamPerDef)
         
-    isParry = False # 是否格挡
     if isParry:
         hurtTypes |= pow(2, ChConfig.HurtType_Parry)
         
@@ -723,7 +969,7 @@
         hurtTypes |= pow(2, ChConfig.HurtType_IgnoreDef)
         
     #参与运算的数值
-    rand = random.random()                #种子数 0~1
+    #rand = random.random()                #种子数 0~1
     
     aAtk = atkObj.GetBatAttrValue(ChConfig.AttrID_Atk) # 攻击方最大攻击
     
@@ -759,6 +1005,8 @@
     dAngerSkillPerDef /= 10000.0
     aPMDamPer /= 10000.0
     dPMDamPerDef /= 10000.0
+    aSuperDamPer /= 10000.0
+    dSuperDamPerDef /= 10000.0
     aFinalDamPer /= 10000.0
     dFinalDamPerDef /= 10000.0
     
@@ -782,35 +1030,132 @@
         hurtValue = eval(IpyGameDataPY.GetFuncCompileCfg("HurtFormula", 4))
         GameWorld.DebugLog("    其他伤害=%s" % (hurtValue))
         
+    if isParry:
+        parryReduceRatio = IpyGameDataPY.GetFuncCfg("ParryCfg", 3)
+        hurtValue = hurtValue * (1 - parryReduceRatio)
+        GameWorld.DebugLog("    格挡后伤害=%s,parryReduceRatio=%s" % (hurtValue, parryReduceRatio))
+        
     hurtValue = max(1, int(hurtValue)) # 负值、保底防范
-    
     return hurtValue, hurtTypes
 
-def CalcBounceHP(atkObj, defObj, hurtObj, curSkill):
+def CanSuperHit(atkObj, defObj):
+    aSuperHitRate = atkObj.GetBatAttrValue(ChConfig.AttrID_SuperHitRate)
+    dSuperHitRateDef = defObj.GetBatAttrValue(ChConfig.AttrID_SuperHitRateDef)
+    happenRate = eval(IpyGameDataPY.GetFuncCompileCfg("SuperHitCfg", 1))
+    if GameWorld.CanHappen(happenRate):
+        GameWorld.DebugLog("暴击了: happenRate=%s,aSuperHitRate=%s,dSuperHitRateDef=%s" % (happenRate, aSuperHitRate, dSuperHitRateDef))
+        return True
+    return False
+
+def CanStun(turnFight, atkObj, defObj, curSkill):
+    aStunRate = atkObj.GetBatAttrValue(ChConfig.AttrID_StunRate)
+    dStunRateDef = defObj.GetBatAttrValue(ChConfig.AttrID_StunRateDef)
+    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
+
+def CanParry(atkObj, defObj):
+    if defObj.IsInControlled():
+        #被控制无法格挡
+        return False
+    aParryRateDef = atkObj.GetBatAttrValue(ChConfig.AttrID_ParryRateDef)
+    dParryRate = defObj.GetBatAttrValue(ChConfig.AttrID_ParryRate)
+    parryNum = defObj.GetDictByKey(ChConfig.Def_Obj_Dict_TurnParryNum)
+    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)
+        return True
+    return False
+
+def CalcHurtHPWithBuff(turnFight, atkObj, defObj, curSkill, hurtValue):
+    ## 计算伤害后,因各种buff和状态的影响处理
+    # @return: hurtValue, realHurtHP
+    
+    if hurtValue <= 0:
+        return 0, 0
+    
+    # 减伤盾减伤, 会改变 hurtValue
+    hurtValue = max(0, hurtValue)
+        
+    # 承伤盾承伤,剩余时间短的优先承伤,承伤不影响输出,相当于额外的HP,仅用于抵扣掉血,仅 改变 realHurtHP
+    realHurtHP = hurtValue
+    shieldBuffList = []
+    buffMgr = defObj.GetBuffManager()
+    for index in range(buffMgr.GetBuffCount()):
+        buff = buffMgr.GetBuffByIndex(index)
+        skillData = buff.GetSkillData()
+        # 承伤盾
+        if SkillCommon.isDamageShieldSkill(skillData):
+            remainTime = buff.GetRemainTime() # 剩余回合
+            if not skillData.GetLastTime():
+                remainTime = 999 # 永久盾
+            buffValue = buff.GetValue1() + buff.GetValue2() * ChConfig.Def_PerPointValue # 剩余盾值
+            shieldBuffList.append([remainTime, buffValue, buff])
+            
+    if shieldBuffList:
+        shieldBuffList.sort()
+        for _, buffValue, buff in shieldBuffList:
+            if realHurtHP <= 0:
+                break
+            buffID = buff.GetBuffID()
+            if realHurtHP < buffValue:
+                damageShieldValue = realHurtHP
+            else:
+                damageShieldValue = buffValue
+            GameWorld.DebugLog("    承伤盾: buffID=%s,buffValue=%s,realHurtHP=%s,damageShieldValue=%s" % (buffID, buffValue, realHurtHP, damageShieldValue))
+            realHurtHP -= damageShieldValue # 承伤值
+            if damageShieldValue >= buffValue:
+                GameWorld.DebugLog("        删除盾: buffID=%s,realHurtHP=%s" % (buffID, realHurtHP))
+                TurnBuff.DoBuffDel(turnFight, defObj, buff, relatedSkill=curSkill, afterLogic=True, tagObj=atkObj)
+            else:
+                updShieldValue = buffValue - damageShieldValue
+                GameWorld.DebugLog("        更新盾值: updShieldValue=%s,realHurtHP=%s" % (updShieldValue, realHurtHP))
+                buff.SetValue1(updShieldValue % ChConfig.Def_PerPointValue)
+                buff.SetValue2(updShieldValue / ChConfig.Def_PerPointValue)
+                curSkill.AddAfterLogic(ChConfig.AfterLogic_SyncBuff, [defObj, buff, atkObj, "ReduceShieldValue"])
+                
+    return hurtValue, max(0, realHurtHP)
+
+def CalcBounceHP(turnFight, atkObj, defObj, hurtObj, curSkill):
     '''计算反弹反弹伤害
     '''
     if not atkObj.GetCanAttack():
         return
     
     bounceHP = int(hurtObj.GetHurtHP() * random.uniform(0.1, 0.2))
-    
     if bounceHP <= 0:
         return
     
-    remainHP = atkObj.GetHP() - bounceHP # 反弹允许弹到负值,如果最终吸血没有吸到正值则算死亡
+    GameWorld.DebugLog("    反弹伤害=%s,%s/%s" % (bounceHP, atkObj.GetHP(), atkObj.GetMaxHP()))
+    bounceHP, realBounceHP = CalcHurtHPWithBuff(turnFight, defObj, atkObj, curSkill, bounceHP)
+    if bounceHP <= 0:
+        return
     hurtObj.SetBounceHP(bounceHP)
-    atkObj.SetHP(remainHP)
-    GameWorld.DebugLog("    反弹伤害=%s,remainHP=%s/%s" % (bounceHP, remainHP, atkObj.GetMaxHP()))
     
-    TurnAttack.AddTurnObjHurtValue(defObj, atkObj, bounceHP, bounceHP, isBounce=True)
+    if realBounceHP > 0:
+        remainHP = atkObj.GetHP() - realBounceHP # 反弹允许弹到负值,如果最终吸血没有吸到正值则算死亡
+        atkObj.SetHP(remainHP)
+        GameWorld.DebugLog("        bounceHP=%s,realBounceHP=%s,%s/%s" % (bounceHP, realBounceHP, atkObj.GetHP(), atkObj.GetMaxHP()))
+        
+    TurnAttack.AddTurnObjHurtValue(defObj, atkObj, bounceHP, realBounceHP, isBounce=True)
     return
 
 def CalcSuckBlood(atkObj, defObj, hurtObj, curSkill):
     '''计算吸血
     '''
     
-    suckHP = int(hurtObj.GetHurtHP() * random.uniform(0.1, 0.2))
+    hurtHP = hurtObj.GetHurtHP()
+    if hurtHP <= 1:
+        return
     
+    aSuckHPPer = atkObj.GetBatAttrValue(ChConfig.AttrID_SuckHPPer)
+    dSuckHPPerDef = defObj.GetBatAttrValue(ChConfig.AttrID_SuckHPPerDef)
+    suckHP = int(eval(IpyGameDataPY.GetFuncCompileCfg("SuckHPCfg", 1)))
     if suckHP <= 0:
         return
     
@@ -821,7 +1166,7 @@
     
     hurtObj.SetSuckHP(suckHP)
     atkObj.SetHP(remainHP)
-    GameWorld.DebugLog("    吸血=%s,remainHP=%s/%s" % (suckHP, remainHP, maxHP))
+    GameWorld.DebugLog("    吸血=%s,remainHP=%s/%s,aSuckHPPer=%s,dSuckHPPerDef=%s" % (suckHP, remainHP, maxHP, aSuckHPPer, dSuckHPPerDef))
     
     # 吸血暂定算治疗
     TurnAttack.AddTurnObjCureHP(atkObj, atkObj, suckHP, cureHP)
@@ -830,21 +1175,12 @@
 def CalcCureHP(userObj, tagObj, curSkill, largeNum=False):
     ''' 计算治疗值
     '''
-    cureBaseValue = 0     #治疗基础值
     cureType = curSkill.GetCalcType()
     skillPer = curSkill.GetSkillPer()
     #skillValue = curSkill.GetSkillValue()
     
-    #获得基础治疗值
-    if cureType == ChConfig.Def_Cure_Attack:
-        cureBaseValue = userObj.GetAtk()
-    elif cureType == ChConfig.Def_Cure_MaxHP:
-        cureBaseValue = userObj.GetMaxHP()
-    #elif cureType == ChConfig.Def_Cure_HurtValue:
-    #    cureBaseValue = GameObj.GetLastHurtValue(userObj)
-    elif cureType == ChConfig.Def_Cure_TagMaxHP:
-        cureBaseValue = 0 if not tagObj else tagObj.GetMaxHP()
-        
+    cureBaseValue = GetCalcBaseValue(cureType, userObj, tagObj)
+    
     #skillPer += PassiveBuffEffMng.GetPassiveSkillValueByTriggerType(userObj, None, curSkill, ChConfig.TriggerType_AddHP)
     
     # 回合制
@@ -874,6 +1210,18 @@
                        % (cureHP, curSkill.GetSkillID(), cureType, baseValue, skillPer, curePer, cureDefPer, angerOverflow))
     return cureHP
 
+def GetCalcBaseValue(calcType, curObj, tagObj):
+    ##获得基础计算值
+    if calcType == ChConfig.Def_Calc_Attack:
+        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_TagMaxHP:
+        baseValue = 0 if not tagObj else tagObj.GetMaxHP()
+    return baseValue
+
 def DoDOTAttack(turnFight, batObj, curBuff, hurtValue, hurtTypes):
     ## 执行单次dot逻辑
     skillID = curBuff.GetSkillID()
@@ -887,34 +1235,39 @@
     atkObj = buffOwner
     defObj = batObj
     
-    tagObjList = [defObj]
-    dHP = defObj.GetHP()
     defID = defObj.GetID()
-    GameWorld.DebugLog("结算dot: defID=%s,buffID=%s,skillID=%s,ownerID=%s,hurtValue=%s,hurtTypes=%s,dHP=%s/%s" 
-                       % (defID, buffID, skillID, ownerID, hurtValue, hurtTypes, dHP, defObj.GetMaxHP()))
+    tagObjList = [defObj]
     
     poolMgr = ObjPool.GetPoolMgr()
     useSkill = poolMgr.acquire(BattleObj.PySkill, skillIpyData)
     useSkill.SetTagObjList(tagObjList)
     useSkill.ClearHurtObj()
+    hurtObj = useSkill.AddHurtObj(defID)
     
-    remainHP = max(0, dHP - hurtValue) # 剩余血量
+    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)
+    
+    # dot的反弹、吸血待定
+    
+    remainHP = max(0, dHP - realHurtHP) # 剩余血量
     lostHP = dHP - remainHP # 实际掉血量
     defObj.SetHP(remainHP)
     
-    hurtObj = useSkill.AddHurtObj(defID)
+    GameWorld.DebugLog("    hurtValue=%s,realHurtHP=%s,lostHP=%s,%s/%s" % (hurtValue, realHurtHP, lostHP, defObj.GetHP(), defObj.GetMaxHP()))
+    
     hurtObj.SetHurtTypes(hurtTypes)
     hurtObj.SetHurtHP(hurtValue)
+    hurtObj.SetRealHurtHP(realHurtHP)
     hurtObj.SetLostHP(lostHP)
     hurtObj.SetCurHP(remainHP)
-    
-    # dot的反弹、吸血待定
     
     TurnAttack.AddTurnObjHurtValue(atkObj, batObj, hurtValue, lostHP, skillID)
     
     Sync_PropertyRefreshView(turnFight, defObj, ChConfig.AttrID_HP, remainHP, hurtValue, diffType=0, skillID=skillID, hurtTypes=hurtTypes)
     
-    DoBeAttackOver(turnFight, atkObj, useSkill)
+    DoBeAttackResult(turnFight, atkObj, useSkill)
     
     useSkill.ResetUseRec()
     poolMgr.release(useSkill)

--
Gitblit v1.8.0