From 1cbdeae386bdfab0b9e996ffb4df0301ce19ff9e Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期一, 01 九月 2025 10:48:01 +0800
Subject: [PATCH] 129 【战斗】战斗系统-服务端(修复主线战斗击杀无法结算经验、掉落bug;)

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py |  442 ++++++++++++++++++++++++------------------------------
 1 files changed, 195 insertions(+), 247 deletions(-)

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..dab5601 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/TurnAttack.py
@@ -20,11 +20,11 @@
 #-------------------------------------------------------------------------------
 
 import ChConfig
+import PlayerTask
 import ChPyNetSendPack
 import NetPackCommon
 import PlayerControl
 import GameWorld
-import GameObj
 import FBCommon
 import IpyGameDataPY
 import PlayerOnline
@@ -33,7 +33,6 @@
 import PyGameData
 import ItemControler
 import SkillCommon
-import AttackCommon
 import BattleObj
 import TurnPassive
 import TurnSkill
@@ -267,12 +266,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
             
@@ -435,6 +434,8 @@
         self.teamMax = 1 # 当前波最大小队,某场战斗可能包含多个小队,所有小队混流击杀完才算过了本波
         self.nextTeam = False # 下次前端请求战斗是否是下一小队,否则都是重新刷新当前进度怪
         self.waveLineupList = [] # 小队列表
+        self.strongerLV = 0
+        self.difficulty = 0
         self.turnFight = GetTurnFightMgr().addTurnFight(ChConfig.Def_FBMapID_Main, 0, playerID)
         return
     
@@ -500,9 +501,11 @@
     
     return lineupInfo
 
-def GetNPCLineupInfo(lineupID):
+def GetNPCLineupInfo(lineupID, strongerLV=0, difficulty=0):
     ## 获取NPC阵容信息
     # @param lineupID: 阵容ID
+    # @param npcLV: 成长NPC等级
+    # @param difficulty: 成长NPC难度系数
     # @return: 阵容全部信息json字典,前端通用格式
     ipyData = IpyGameDataPY.GetIpyGameData("NPCLineup", lineupID)
     if not ipyData:
@@ -515,9 +518,46 @@
         npcID = getattr(ipyData, "GetPosNPCID%s" % posNum)()
         if not npcID:
             continue
-        npcData = NPCCommon.GetNPCDataPy(npcID)
-        if not npcData:
+        battleDict = GetNPCBattleDict(npcID, strongerLV, difficulty)
+        if not battleDict:
             continue
+        heroDict[str(posNum)] = battleDict
+        
+    lineupInfo = {"NPCLineupID":lineupID, "Hero":heroDict}
+    return lineupInfo
+
+def GetNPCBattleDict(npcID, strongerLV=0, difficulty=0):
+    ## 获取NPC战斗相关字典,支持成长NPC
+    # @param strongerLV: 成长等级
+    # @param difficulty: 难度系数
+    npcData = NPCCommon.GetNPCDataPy(npcID)
+    if not npcData:
+        return
+    heroID = npcData.GetRelatedHeroID()
+    npcLV = npcData.GetLV()
+    
+    lvIpyData = None
+    heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID) if heroID else None
+    npcStronger = IpyGameDataPY.GetIpyGameDataNotLog("NPCStronger", npcID)
+    if npcStronger and strongerLV:
+        lvIpyData = IpyGameDataPY.GetIpyGameData("PlayerLV", strongerLV)
+        if lvIpyData:
+            npcLV = strongerLV
+    if not lvIpyData:
+        lvIpyData = IpyGameDataPY.GetIpyGameData("PlayerLV", npcLV)
+        
+    if heroIpyData and lvIpyData:
+        skinIDList = heroIpyData.GetSkinIDList()
+        skinID = skinIDList[0] if skinIDList else 0
+        skillIDList = GetNPCHeroSkillIDList(heroID, heroIpyData, lvIpyData.GetReHeroBreakLV(), lvIpyData.GetReHeroAwakeLV())
+    else:
+        heroID = 0
+        skinID = 0
+        skillIDList = [] + npcData.GetSkillIDList()
+        
+    # 成长怪属性
+    batAttrDict = GetNPCStrongerAttrDict(npcID, lvIpyData, npcStronger, difficulty)
+    if not batAttrDict:
         batAttrDict = {ChConfig.AttrID_Atk:npcData.GetAtk(), ChConfig.AttrID_Def:npcData.GetDef(), ChConfig.AttrID_MaxHP:npcData.GetMaxHP(), 
                        ChConfig.AttrID_FinalDamPer:npcData.GetFinalDamPer(), ChConfig.AttrID_FinalDamPerDef:npcData.GetFinalDamPerDef(), 
                        ChConfig.AttrID_MissRate:npcData.GetMissRate(), ChConfig.AttrID_MissRateDef:npcData.GetMissRateDef(), 
@@ -528,14 +568,68 @@
                        ChConfig.AttrID_SuckHPPer:npcData.GetSuckHPPer(), ChConfig.AttrID_SuckHPPerDef:npcData.GetSuckHPPerDef(), 
                        }
         batAttrDict.update(npcData.GetSpecAttrInfo())
-        skillIDList = [] + npcData.GetSkillIDList()
-        heroDict[str(posNum)] = {"NPCID":npcID, 
-                                 "AttrDict":{str(k):v for k, v in batAttrDict.items() if v > 0},
-                                 "SkillIDList":skillIDList
-                                 }
         
-    lineupInfo = {"NPCLineupID":lineupID, "Hero":heroDict}
-    return lineupInfo
+    battleDict = {"NPCID":npcID,
+                  "HeroID":heroID,
+                  "SkinID":skinID,
+                  "LV":npcLV,
+                  "AttrDict":{str(k):v for k, v in batAttrDict.items() if v > 0},
+                  "SkillIDList":skillIDList,
+                  }
+    
+    GameWorld.DebugLog("GetNPCBattleDict npcID=%s,strongerLV=%s,difficulty=%s,%s" % (npcID, strongerLV, difficulty, battleDict))
+    return battleDict
+
+def GetNPCHeroSkillIDList(heroID, heroIpyData, breakLV, awakeLV):
+    ## 获取NPC对应武将的技能ID列表
+    normalSkillID = heroIpyData.GetNormalSkillID()
+    angerSkillID = heroIpyData.GetAngerSkillID()
+    skillIDList = [normalSkillID, angerSkillID]
+    
+    breakIpyDataList = IpyGameDataPY.GetIpyGameDataList("HeroBreak", heroID)
+    if breakIpyDataList:
+        for breakIpyData in breakIpyDataList:
+            if breakIpyData.GetBreakLV() > breakLV:
+                break
+            skillID = breakIpyData.GetSkillID()
+            if skillID:
+                skillIDList.append(skillID)
+                
+    awakeIpyDataList = IpyGameDataPY.GetIpyGameDataList("HeroAwake", heroID)
+    if awakeIpyDataList:
+        for awakeIpyData in awakeIpyDataList:
+            if awakeIpyData.GetAwakeLV() > awakeLV:
+                break
+            skillID = awakeIpyData.GetSkillID()
+            if skillID:
+                skillIDList.append(skillID)
+                
+    return skillIDList
+
+def GetNPCStrongerAttrDict(npcID, lvIpyData, npcStronger, difficulty):
+    ## 获取NPC成长属性
+    # @param strongerLV: 成长等级
+    # @param difficulty: 难度系数
+    
+    batAttrDict = {}
+    if not lvIpyData or not npcStronger or not difficulty:
+        return batAttrDict
+    lv = lvIpyData.GetLV()
+    for attrID in ChConfig.CalcBattleAttrIDList:
+        attrIpyData = IpyGameDataPY.GetIpyGameData("PlayerAttr", attrID)
+        if not attrIpyData:
+            continue
+        attrName = attrIpyData.GetParameter()
+        if not hasattr(lvIpyData, "GetRe%s" % attrName):
+            continue
+        reValue = getattr(lvIpyData, "GetRe%s" % attrName)() # 基础参考值
+        ratio = getattr(npcStronger, "Get%sRatio" % attrName)() if hasattr(npcStronger, "Get%sRatio" % attrName) else 1 # 属性系数
+        attrValue = int(reValue * ratio * difficulty)
+        batAttrDict[attrID] = attrValue
+        #GameWorld.DebugLog("    attrID=%s,attrValue=%s,reValue=%s,ratio=%s,difficulty=%s" % (attrID, attrValue, reValue, ratio, difficulty))
+        
+    GameWorld.DebugLog("NPC成长属性: npcID=%s,lv=%s,difficulty=%s,%s" % (npcID, lv, difficulty, batAttrDict))
+    return batAttrDict
 
 def SummonLineupObjs(batLineup, faction, num, lineupInfo, playerID=0):
     '''召唤阵容战斗实例
@@ -556,52 +650,61 @@
     
     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)
         
-        npcID, heroID, skinID = 0, 0, 0
         atkBackSkillID = 0 # 反击技能ID
         fightPower = 0
         skillIDList = [] # 战斗对象可能改变属性或技能,重新创建,防止误修改来源值
         attrDict = {}
         skillIDList += heroInfo.get("SkillIDList", [])
         attrDict.update(heroInfo.get("AttrDict", {}))
-        objName = ""
-        if lineupPlayerID:
-            heroID = heroInfo.get("HeroID", 0)
-            skinID = heroInfo.get("SkinID", 0)
-            lv = heroInfo.get("LV", 1)
-            fightPower = heroInfo.get("FightPower", 0)
-            heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID)
-            if not heroIpyData:
-                continue
+        npcID = heroInfo.get("NPCID", 0)
+        heroID = heroInfo.get("HeroID", 0)
+        skinID = heroInfo.get("SkinID", 0)
+        lv = heroInfo.get("LV", 1)
+        heroIpyData = IpyGameDataPY.GetIpyGameData("Hero", heroID) if heroID else None
+        if heroIpyData:
             atkDistType = heroIpyData.GetAtkDistType()
             objName = heroIpyData.GetName()
+            country = heroIpyData.GetCountry()
+            sex = heroIpyData.GetSex()
+            
+        if lineupPlayerID:
+            fightPower = heroInfo.get("FightPower", 0)
+            if not heroIpyData:
+                continue
+            
         else:
-            npcID = heroInfo.get("NPCID", 0)
             npcDataEx = NPCCommon.GetNPCDataPy(npcID)
             if not npcDataEx:
                 continue
-            objName = npcDataEx.GetNPCName()
-            atkDistType = npcDataEx.GetAtkDistType()
-            lv = npcDataEx.GetLV()
-            
+            if not heroIpyData:
+                atkDistType = npcDataEx.GetAtkDistType()
+                objName = npcDataEx.GetNPCName()
+                country = npcDataEx.GetCountry()
+                sex = npcDataEx.GetSex()
+                
         batObj = batObjMgr.addBatObj()
         if not batObj:
             break
         objID = batObj.GetID()
+        if npcID:
+            batObj.SetNPCID(npcID)
+        elif lineupPlayerID:
+            batObj.SetOwnerID(lineupPlayerID)
         batObj.SetTFGUID(tfGUID)
         batObj.SetName(objName)
         batObj.SetFaction(faction)
         batObj.SetLineupPos(posNum, num)
         batObj.SetFightPower(fightPower)
         batObj.SetLV(lv)
-        if npcID:
-            batObj.SetNPCID(npcID)
-        elif lineupPlayerID:
-            batObj.SetOwnerHero(lineupPlayerID, heroID, skinID)
-            
+        batObj.SetAtkDistType(atkDistType)
+        batObj.SetCountry(country)
+        batObj.SetSex(sex)
+        batObj.SetHero(heroID, skinID)
+        
         if atkDistType == ChConfig.AtkDistType_Short:
             atkBackSkillID = atkBackSkillIDList[0] if len(atkBackSkillIDList) > 0 else 0
         elif atkDistType == ChConfig.AtkDistType_Long:
@@ -614,7 +717,7 @@
             skillManager.LearnSkillByID(skillID)
             
         batLineup.posObjIDDict[posNum] = objID
-        GameWorld.DebugLog("AddBatObj ID:%s,%s,skill=%s" % (objID, GetObjName(batObj), skillIDList))
+        GameWorld.DebugLog("AddBatObj %s,skill=%s" % (GetObjName(batObj), skillIDList))
         batObj.InitBatAttr({int(k):v for k, v in attrDict.items()}, initXP)
         
     return
@@ -729,6 +832,8 @@
         GameWorld.DebugLog("没有设置主阵容!", playerID)
         return
     
+    strongerLV = levelIpyData.GetNPCLV()
+    difficulty = levelIpyData.GetDifficulty()
     mainFightMgr = GetMainFightMgr(curPlayer)
     mainFightMgr.nextTeam = False
     mainFightMgr.chapterID = chapterID
@@ -738,15 +843,17 @@
     mainFightMgr.waveLineupList = waveLineupList
     mainFightMgr.teamNum = teamNum
     mainFightMgr.teamMax = teamMax
+    mainFightMgr.strongerLV = strongerLV
+    mainFightMgr.difficulty = difficulty
     turnMax = IpyGameDataPY.GetFuncCfg("Mainline", 2)
     mapID, funcLineID = ChConfig.Def_FBMapID_Main, PlayerControl.ComMainLevelValue(chapterID, levelNum, wave)
-    GameWorld.DebugLog("设置起始关卡波: 关卡%s-%s,波=%s/%s,teamMax=%s,mapID=%s,funcLineID=%s,lineupID=%s" 
-                       % (chapterID, levelNum, wave, waveMax, teamMax, mapID, funcLineID, lineupID), playerID)
+    GameWorld.DebugLog("设置起始关卡波: 关卡%s-%s,波=%s/%s,teamMax=%s,mapID=%s,funcLineID=%s,lineupID=%s,strongerLV=%s,difficulty=%s" 
+                       % (chapterID, levelNum, wave, waveMax, teamMax, mapID, funcLineID, lineupID, strongerLV, difficulty), playerID)
     
     turnFight = mainFightMgr.turnFight
     turnFight.setTurn(mapID, funcLineID, turnMax, False, {"teamNum":teamNum, "teamMax":teamMax})
     turnFight.setFactionLineup(ChConfig.Def_FactionA, {1:lineupMainInfo})
-    turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:GetNPCLineupInfo(lineupID)})
+    turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:GetNPCLineupInfo(lineupID, strongerLV, difficulty)})
     turnFight.sortActionQueue()
     turnFight.startFight()
     return
@@ -802,7 +909,9 @@
     if not lineupMainInfo:
         GameWorld.DebugLog("没有设置主阵容!", playerID)
         return
-    
+        
+    strongerLV = levelIpyData.GetNPCLV()
+    difficulty = levelIpyData.GetDifficulty()
     mainFightMgr = GetMainFightMgr(curPlayer)
     mainFightMgr.nextTeam = False
     mainFightMgr.chapterID = chapterID
@@ -812,15 +921,17 @@
     mainFightMgr.waveLineupList = waveLineupList
     mainFightMgr.teamNum = teamNum
     mainFightMgr.teamMax = teamMax
+    mainFightMgr.strongerLV = strongerLV
+    mainFightMgr.difficulty = difficulty
     turnMax = IpyGameDataPY.GetFuncCfg("Mainline", 3)
     mapID, funcLineID = ChConfig.Def_FBMapID_MainBoss, PlayerControl.ComMainLevelValue(chapterID, levelNum, wave)
-    GameWorld.DebugLog("设置关卡boss: 关卡%s-%s,波=%s/%s,teamMax=%s,mapID=%s,funcLineID=%s,lineupID=%s" 
-                       % (chapterID, levelNum, wave, waveMax, teamMax, mapID, funcLineID, lineupID), playerID)
+    GameWorld.DebugLog("设置关卡boss: 关卡%s-%s,波=%s/%s,teamMax=%s,mapID=%s,funcLineID=%s,lineupID=%s,strongerLV=%s,difficulty=%s" 
+                       % (chapterID, levelNum, wave, waveMax, teamMax, mapID, funcLineID, lineupID, strongerLV, difficulty), playerID)
     
     turnFight = mainFightMgr.turnFight
     turnFight.setTurn(mapID, funcLineID, turnMax, False, {"teamNum":teamNum, "teamMax":teamMax})
     turnFight.setFactionLineup(ChConfig.Def_FactionA, {1:lineupMainInfo})
-    turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:GetNPCLineupInfo(lineupID)})
+    turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:GetNPCLineupInfo(lineupID, strongerLV, difficulty)})
     turnFight.sortActionQueue()
     turnFight.startFight()
     
@@ -858,7 +969,7 @@
             mainFightMgr.nextTeam = False
             turnFight.resetTurn({"teamNum":teamNum})
             # 切换小队时,玩家阵容不需要处理,保留状态
-            turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:GetNPCLineupInfo(lineupID)})
+            turnFight.setFactionLineup(ChConfig.Def_FactionB, {1:GetNPCLineupInfo(lineupID, mainFightMgr.strongerLV, mainFightMgr.difficulty)})
             turnFight.sortActionQueue()
             turnFight.startFight()
             
@@ -1088,10 +1199,13 @@
     num = batObj.lineupNum
     posNum = batObj.posNum
     heroID = batObj.heroID
-    if not heroID:
-        heroID = batObj.npcID
+    npcID = batObj.npcID
     objName = GameWorld.CodeToGbk(batObj.GetName())
-    return "%s%s-%s [%s-%s] %s" % ("A" if faction == ChConfig.Def_FactionA else "B", num, posNum, batObj.GetID(), heroID, objName)
+    if heroID:
+        objName += " Hero:%s" % heroID
+    if npcID:
+        objName += " NPC:%s" % npcID        
+    return "%s%s-P%s ID:%s %s" % ("A" if faction == ChConfig.Def_FactionA else "B", num, posNum, batObj.GetID(), objName)
 
 def EntryLogic(turnFight):
     ## 执行进场逻辑
@@ -1112,6 +1226,7 @@
     return
 
 def OnTimelineChange(turnFight):
+    ## 每个时间节点变化时处理
     
     nowTimeline = turnFight.getTimeline()
     
@@ -1120,8 +1235,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()):
@@ -1145,18 +1266,24 @@
                 buffMgr = batObj.GetBuffManager()
                 for index in range(buffMgr.GetBuffCount())[::-1]:
                     buff = buffMgr.GetBuffByIndex(index)
+                    buffID = buff.GetBuffID()
+                    skillID = buff.GetSkillID()
+                    skillData = buff.GetSkillData()
+                    if skillData.GetSkillType() in ChConfig.Def_LstBuff_List:
+                        #GameWorld.DebugLog("    持续类buff由触发时机决定剩余时间! curID=%s,index=%s,skillID=%s,buffID=%s" % (curID, index, skillID, buffID))
+                        continue
                     remainTime = buff.GetRemainTime()
                     if not remainTime:
                         # 永久buff不处理
+                        #GameWorld.DebugLog("    永久buff不处理! curID=%s,index=%s,skillID=%s" % (curID, index, skillID))
                         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, skillID))
                         continue
                     
                     updRemainTime = max(0, remainTime - passTurn)
-                    buffID = buff.GetBuffID()
-                    skillID = buff.GetSkillID()
                     GameWorld.DebugLog("更新buff剩余回合数: curID=%s,buffID=%s,skillID=%s,updRemainTime=%s,calcTimeline=%s,passTurn=%s" 
                                        % (curID, buffID, skillID, updRemainTime, calcTimeline, passTurn))
                     if updRemainTime > 0:
@@ -1194,40 +1321,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 +1364,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 +1374,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 +1398,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 +1432,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,172 +1451,23 @@
     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
     clientPack.KillerObjID = killerObjID
     clientPack.SkillID = skillID
-    turnFight.addBatPack(clientPack)        
+    turnFight.addBatPack(clientPack)
+    
+    curPlayer = turnFight.curPlayer
+    # 暂时只算主线小怪
+    if curPlayer and turnFight.mapID == ChConfig.Def_FBMapID_Main and gameObj.GetFaction() != ChConfig.Def_FactionA:
+        PlayerTask.AddTaskValue(curPlayer, ChConfig.TaskType_KillNPC, 1)    
     return True
 
 def OnTurnAllOver(guid):
@@ -1551,7 +1499,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 +1525,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}
                 

--
Gitblit v1.8.0